` markup. 🎉
-
-### Ternary vs Logical AND
-
-As you can see, ternaries are wonderful for `if/else` conditions. But what about simple `if` conditions?
-
-Let’s look at another example. If `isPro` (a boolean) is `true`, we are to display a trophy emoji. We are also to render the number of stars (if not zero). We could go about it like this.
-
-```
-const MyComponent = ({ name, isPro, stars}) => (
-
-
- Hello {name}
- {isPro ? '🏆' : null}
-
- {stars ? (
-
- Stars:{'⭐️'.repeat(stars)}
-
- ) : null}
-
-);
-```
-
-But notice the “else” conditions return `null`. This is becasue a ternary expects an else condition.
-
-For simple `if` conditions, we could use something a little more fitting: the logical AND operator. Here’s the same code written using a logical AND.
-
-```
-const MyComponent = ({ name, isPro, stars}) => (
-
-
- Hello {name}
- {isPro && '🏆'}
-
- {stars && (
-
- Stars:{'⭐️'.repeat(stars)}
-
- )}
-
-);
-```
-
-Not too different, but notice how we eliminated the `: null` (i.e. else condition) at the end of each ternary. Everything should render just like it did before.
-
-
-Hey! What gives with John? There is a `0` when nothing should be rendered. That’s the gotcha that I was referring to above. Here’s why.
-
-[According to MDN][3], a Logical AND (i.e. `&&`):
-
-> `expr1 && expr2`
-
-> Returns `expr1` if it can be converted to `false`; otherwise, returns `expr2`. Thus, when used with Boolean values, `&&` returns `true` if both operands are true; otherwise, returns `false`.
-
-OK, before you start pulling your hair out, let me break it down for you.
-
-In our case, `expr1` is the variable `stars`, which has a value of `0`. Because zero is falsey, `0` is returned and rendered. See, that wasn’t too bad.
-
-I would write this simply.
-
-> If `expr1` is falsey, returns `expr1`, else returns `expr2`.
-
-So, when using a logical AND with non-boolean values, we must make the falsey value return something that React won’t render. Say, like a value of `false`.
-
-There are a few ways that we can accomplish this. Let’s try this instead.
-
-```
-{!!stars && (
-
- {'⭐️'.repeat(stars)}
-
-)}
-```
-
-Notice the double bang operator (i.e. `!!`) in front of `stars`. (Well, actually there is no “double bang operator”. We’re just using the bang operator twice.)
-
-The first bang operator will coerce the value of `stars` into a boolean and then perform a NOT operation. If `stars` is `0`, then `!stars` will produce `true`.
-
-Then we perform a second NOT operation, so if `stars` is 0, `!!stars` would produce `false`. Exactly what we want.
-
-If you’re not a fan of `!!`, you can also force a boolean like this (which I find a little wordy).
-
-```
-{Boolean(stars) && (
-```
-
-Or simply give a comparator that results in a boolean value (which some might say is even more semantic).
-
-```
-{stars > 0 && (
-```
-
-#### A word on strings
-
-Empty string values suffer the same issue as numbers. But because a rendered empty string is invisible, it’s not a problem that you will likely have to deal with, or will even notice. However, if you are a perfectionist and don’t want an empty string on your DOM, you should take similar precautions as we did for numbers above.
-
-### Another solution
-
-A possible solution, and one that scales to other variables in the future, would be to create a separate `shouldRenderStars` variable. Then you are dealing with boolean values in your logical AND.
-
-```
-const shouldRenderStars = stars > 0;
-```
-
-```
-return (
-
- {shouldRenderStars && (
-
- {'⭐️'.repeat(stars)}
-
- )}
-
-);
-```
-
-Then, if in the future, the business rule is that you also need to be logged in, own a dog, and drink light beer, you could change how `shouldRenderStars` is computed, and what is returned would remain unchanged. You could also place this logic elsewhere where it’s testable and keep the rendering explicit.
-
-```
-const shouldRenderStars =
- stars > 0 && loggedIn && pet === 'dog' && beerPref === 'light`;
-```
-
-```
-return (
-
- {shouldRenderStars && (
-
- {'⭐️'.repeat(stars)}
-
- )}
-
-);
-```
-
-### Conclusion
-
-I’m of the opinion that you should make best use of the language. And for JavaScript, this means using conditional ternary operators for `if/else`conditions and logical AND operators for simple `if` conditions.
-
-While we could just retreat back to our safe comfy place where we use the ternary operator everywhere, you now possess the knowledge and power to go forth AND prosper.
-
---------------------------------------------------------------------------------
-
-作者简介:
-
-Managing Editor at the American Express Engineering Blog http://aexp.io and Director of Engineering @AmericanExpress. MyViews !== ThoseOfMyEmployer.
-
-----------------
-
-via: https://medium.freecodecamp.org/conditional-rendering-in-react-using-ternaries-and-logical-and-7807f53b6935
-
-作者:[Donavon West][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://medium.freecodecamp.org/@donavon
-[1]:https://unsplash.com/photos/pKeF6Tt3c08?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
-[2]:https://unsplash.com/search/photos/road-sign?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
-[3]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators
\ No newline at end of file
diff --git a/sources/tech/20180201 Here are some amazing advantages of Go that you dont hear much about.md b/sources/tech/20180201 Here are some amazing advantages of Go that you dont hear much about.md
deleted file mode 100644
index 12c581b773..0000000000
--- a/sources/tech/20180201 Here are some amazing advantages of Go that you dont hear much about.md
+++ /dev/null
@@ -1,223 +0,0 @@
-Here are some amazing advantages of Go that you don’t hear much about
-============================================================
-
-
-
-Artwork from [https://github.com/ashleymcnamara/gophers][1]
-
-In this article, I discuss why you should give Go a chance and where to start.
-
-Golang is a programming language you might have heard about a lot during the last couple years. Even though it was created back in 2009, it has started to gain popularity only in recent years.
-
-
-
-Golang popularity according to Google Trends
-
-This article is not about the main selling points of Go that you usually see.
-
-Instead, I would like to present to you some rather small but still significant features that you only get to know after you’ve decided to give Go a try.
-
-These are amazing features that are not laid out on the surface, but they can save you weeks or months of work. They can also make software development more enjoyable.
-
-Don’t worry if Go is something new for you. This article does not require any prior experience with the language. I have included a few extra links at the bottom, in case you would like to learn a bit more.
-
-We will go through such topics as:
-
-* GoDoc
-
-* Static code analysis
-
-* Built-in testing and profiling framework
-
-* Race condition detection
-
-* Learning curve
-
-* Reflection
-
-* Opinionatedness
-
-* Culture
-
-Please, note that the list doesn’t follow any particular order. It is also opinionated as hell.
-
-### GoDoc
-
-Documentation in code is taken very seriously in Go. So is simplicity.
-
-[GoDoc][4] is a static code analyzing tool that creates beautiful documentation pages straight out of your code. A remarkable thing about GoDoc is that it doesn’t use any extra languages, like JavaDoc, PHPDoc, or JSDoc to annotate constructions in your code. Just English.
-
-It uses as much information as it can get from the code to outline, structure, and format the documentation. And it has all the bells and whistles, such as cross-references, code samples, and direct links to your version control system repository.
-
-All you can do is to add a good old `// MyFunc transforms Foo into Bar` kind of comment which would be reflected in the documentation, too. You can even add [code examples][5] which are actually runnable via the web interface or locally.
-
-GoDoc is the only documentation engine for Go that is used by the whole community. This means that every library or application written in Go has the same format of documentation. In the long run, it saves you tons of time while browsing those docs.
-
-Here, for example, is the GoDoc page for my recent pet project: [pullkee — GoDoc][6].
-
-### Static code analysis
-
-Go heavily relies on static code analysis. Examples include [godoc][7] for documentation, [gofmt][8] for code formatting, [golint][9] for code style linting, and many others.
-
-There are so many of them that there’s even an everything-included-kind-of project called [gometalinter][10] to compose them all into a single utility.
-
-Those tools are commonly implemented as stand-alone command line applications and integrate easily with any coding environment.
-
-Static code analysis isn’t actually something new to modern programming, but Go sort of brings it to the absolute. I can’t overestimate how much time it saved me. Also, it gives you a feeling of safety, as though someone is covering your back.
-
-It’s very easy to create your own analyzers, as Go has dedicated built-in packages for parsing and working with Go sources.
-
-You can learn more from this talk: [GothamGo Kickoff Meetup: Go Static Analysis Tools by Alan Donovan][11].
-
-### Built-in testing and profiling framework
-
-Have you ever tried to pick a testing framework for a Javascript project you are starting from scratch? If so, you might understand that struggle of going through such an analysis paralysis. You might have also realized that you were not using like 80% of the framework you have chosen.
-
-The issue repeats over again once you need to do some reliable profiling.
-
-Go comes with a built-in testing tool designed for simplicity and efficiency. It provides you the simplest API possible, and makes minimum assumptions. You can use it for different kinds of testing, profiling, and even to provide executable code examples.
-
-It produces CI-friendly output out-of-box, and the usage is usually as easy as running `go test`. Of course, it also supports advanced features like running tests in parallel, marking them skipped, and many more.
-
-### Race condition detection
-
-You might already know about Goroutines, which are used in Go to achieve concurrent code execution. If you don’t, [here’s][12] a really brief explanation.
-
-Concurrent programming in complex applications is never easy regardless of the specific technique, partly due to the possibility of race conditions.
-
-Simply put, race conditions happen when several concurrent operations finish in an unpredicted order. It might lead to a huge number of bugs, which are particularly hard to chase down. Ever spent a day debugging an integration test which only worked in about 80% of executions? It probably was a race condition.
-
-All that said, concurrent programming is taken very seriously in Go and, luckily, we have quite a powerful tool to hunt those race conditions down. It is fully integrated into Go’s toolchain.
-
-You can read more about it and learn how to use it here: [Introducing the Go Race Detector — The Go Blog][13].
-
-### Learning curve
-
-You can learn ALL Go’s language features in one evening. I mean it. Of course, there are also the standard library, and the best practices in different, more specific areas. But two hours would totally be enough time to get you confidently writing a simple HTTP server, or a command-line app.
-
-The project has [marvelous documentation][14], and most of the advanced topics have already been covered on their blog: [The Go Programming Language Blog][15].
-
-Go is much easier to bring to your team than Java (and the family), Javascript, Ruby, Python, or even PHP. The environment is easy to setup, and the investment your team needs to make is much smaller before they can complete your first production code.
-
-### Reflection
-
-Code reflection is essentially an ability to sneak under the hood and access different kinds of meta-information about your language constructs, such as variables or functions.
-
-Given that Go is a statically typed language, it’s exposed to a number of various limitations when it comes to more loosely typed abstract programming. Especially compared to languages like Javascript or Python.
-
-Moreover, Go [doesn’t implement a concept called Generics][16] which makes it even more challenging to work with multiple types in an abstract way. Nevertheless, many people think it’s actually beneficial for the language because of the amount of complexity Generics bring along. And I totally agree.
-
-According to Go’s philosophy (which is a separate topic itself), you should try hard to not over-engineer your solutions. And this also applies to dynamically-typed programming. Stick to static types as much as possible, and use interfaces when you know exactly what sort of types you’re dealing with. Interfaces are very powerful and ubiquitous in Go.
-
-However, there are still cases in which you can’t possibly know what sort of data you are facing. A great example is JSON. You convert all the kinds of data back and forth in your applications. Strings, buffers, all sorts of numbers, nested structs and more.
-
-In order to pull that off, you need a tool to examine all the data in runtime that acts differently depending on its type and structure. Reflection to rescue! Go has a first-class [reflect][17] package to enable your code to be as dynamic as it would be in a language like Javascript.
-
-An important caveat is to know what price you pay for using it — and only use it when there is no simpler way.
-
-You can read more about it here: [The Laws of Reflection — The Go Blog][18].
-
-You can also read some real code from the JSON package sources here: [src/encoding/json/encode.go — Source Code][19]
-
-### Opinionatedness
-
-Is there such a word, by the way?
-
-Coming from the Javascript world, one of the most daunting processes I faced was deciding which conventions and tools I needed to use. How should I style my code? What testing library should I use? How should I go about structure? What programming paradigms and approaches should I rely on?
-
-Which sometimes basically got me stuck. I was doing this instead of writing the code and satisfying the users.
-
-To begin with, I should note that I totally get where those conventions should come from. It’s always you and your team. Anyway, even a group of experienced Javascript developers can easily find themselves having most of the experience with entirely different tools and paradigms to achieve kind of the same results.
-
-This makes the analysis paralysis cloud explode over the whole team, and also makes it harder for the individuals to integrate with each other.
-
-Well, Go is different. You have only one style guide that everyone follows. You have only one testing framework which is built into the basic toolchain. You have a lot of strong opinions on how to structure and maintain your code. How to pick names. What structuring patterns to follow. How to do concurrency better.
-
-While this might seem too restrictive, it saves tons of time for you and your team. Being somewhat limited is actually a great thing when you are coding. It gives you a more straightforward way to go when architecting new code, and makes it easier to reason about the existing one.
-
-As a result, most of the Go projects look pretty alike code-wise.
-
-### Culture
-
-People say that every time you learn a new spoken language, you also soak in some part of the culture of the people who speak that language. Thus, the more languages you learn, more personal changes you might experience.
-
-It’s the same with programming languages. Regardless of how you are going to apply a new programming language in the future, it always gives you a new perspective on programming in general, or on some specific techniques.
-
-Be it functional programming, pattern matching, or prototypal inheritance. Once you’ve learned it, you carry these approaches with you which broadens the problem-solving toolset that you have as a software developer. It also changes the way you see high-quality programming in general.
-
-And Go is a terrific investment here. The main pillar of Go’s culture is keeping simple, down-to-earth code without creating many redundant abstractions and putting the maintainability at the top. It’s also a part of the culture to spend the most time actually working on the codebase, instead of tinkering with the tools and the environment. Or choosing between different variations of those.
-
-Go is also all about “there should be only one way of doing a thing.”
-
-A little side note. It’s also partially true that Go usually gets in your way when you need to build relatively complex abstractions. Well, I’d say that’s the tradeoff for its simplicity.
-
-If you really need to write a lot of abstract code with complex relationships, you’d be better off using languages like Java or Python. However, even when it’s not obvious, it’s very rarely the case.
-
-Always use the best tool for the job!
-
-### Conclusion
-
-You might have heard of Go before. Or maybe it’s something that has been staying out of your radar for a while. Either way, chances are, Go can be a very decent choice for you or your team when starting a new project or improving the existing one.
-
-This is not a complete list of all the amazing things about Go. Just the undervalued ones.
-
-Please, give Go a try with [A Tour of Go][20] which is an incredible place to start.
-
-If you wish to learn more about Go’s benefits, you can check out these links:
-
-* [Why should you learn Go? — Keval Patel — Medium][2]
-
-* [Farewell Node.js — TJ Holowaychuk — Medium][3]
-
-Share your observations down in the comments!
-
-Even if you are not specifically looking for a new language to use, it’s worth it to spend an hour or two getting the feel of it. And maybe it can become quite useful for you in the future.
-
-Always be looking for the best tools for your craft!
-
-* * *
-
-If you like this article, please consider following me for more, and clicking on those funny green little hands right below this text for sharing. 👏👏👏
-
-Check out my [Github][21] and follow me on [Twitter][22]!
-
---------------------------------------------------------------------------------
-
-作者简介:
-
-Software Engineer and Traveler. Coding for fun. Javascript enthusiast. Tinkering with Golang. A lot into SOA and Docker. Architect at Velvica.
-
-------------
-
-
-via: https://medium.freecodecamp.org/here-are-some-amazing-advantages-of-go-that-you-dont-hear-much-about-1af99de3b23a
-
-作者:[Kirill Rogovoy][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:
-[1]:https://github.com/ashleymcnamara/gophers
-[2]:https://medium.com/@kevalpatel2106/why-should-you-learn-go-f607681fad65
-[3]:https://medium.com/@tjholowaychuk/farewell-node-js-4ba9e7f3e52b
-[4]:https://godoc.org/
-[5]:https://blog.golang.org/examples
-[6]:https://godoc.org/github.com/kirillrogovoy/pullkee
-[7]:https://godoc.org/
-[8]:https://golang.org/cmd/gofmt/
-[9]:https://github.com/golang/lint
-[10]:https://github.com/alecthomas/gometalinter#supported-linters
-[11]:https://vimeo.com/114736889
-[12]:https://gobyexample.com/goroutines
-[13]:https://blog.golang.org/race-detector
-[14]:https://golang.org/doc/
-[15]:https://blog.golang.org/
-[16]:https://golang.org/doc/faq#generics
-[17]:https://golang.org/pkg/reflect/
-[18]:https://blog.golang.org/laws-of-reflection
-[19]:https://golang.org/src/encoding/json/encode.go
-[20]:https://tour.golang.org/
-[21]:https://github.com/kirillrogovoy/
-[22]:https://twitter.com/krogovoy
\ No newline at end of file
diff --git a/sources/tech/20180203 API Star- Python 3 API Framework - Polyglot.Ninja().md b/sources/tech/20180203 API Star- Python 3 API Framework - Polyglot.Ninja().md
deleted file mode 100644
index 10bb70fe72..0000000000
--- a/sources/tech/20180203 API Star- Python 3 API Framework - Polyglot.Ninja().md
+++ /dev/null
@@ -1,259 +0,0 @@
-API Star: Python 3 API Framework – Polyglot.Ninja()
-======
-For building quick APIs in Python, I have mostly depended on [Flask][1]. Recently I came across a new API framework for Python 3 named “API Star” which seemed really interesting to me for several reasons. Firstly the framework embraces modern Python features like type hints and asyncio. And then it goes ahead and uses these features to provide awesome development experience for us, the developers. We will get into those features soon but before we begin, I would like to thank Tom Christie for all the work he has put into Django REST Framework and now API Star.
-
-Now back to API Star – I feel very productive in the framework. I can choose to write async codes based on asyncio or I can choose a traditional backend like WSGI. It comes with a command line tool – `apistar` to help us get things done faster. There’s (optional) support for both Django ORM and SQLAlchemy. There’s a brilliant type system that enables us to define constraints on our input and output and from these, API Star can auto generate api schemas (and docs), provide validation and serialization feature and a lot more. Although API Star is heavily focused on building APIs, you can also build web applications on top of it fairly easily. All these might not make proper sense until we build something all by ourselves.
-
-### Getting Started
-
-We will start by installing API Star. It would be a good idea to create a virtual environment for this exercise. If you don’t know how to create a virtualenv, don’t worry and go ahead.
-```
-pip install apistar
-
-```
-
-If you’re not using a virtual environment or the `pip` command for your Python 3 is called `pip3`, then please use `pip3 install apistar` instead.
-
-Once we have the package installed, we should have access to the `apistar` command line tool. We can create a new project with it. Let’s create a new project in our current directory.
-```
-apistar new .
-
-```
-
-Now we should have two files created – `app.py` – which contains the main application and then `test.py` for our tests. Let’s examine our `app.py` file:
-```
-from apistar import Include, Route
-from apistar.frameworks.wsgi import WSGIApp as App
-from apistar.handlers import docs_urls, static_urls
-
-
-def welcome(name=None):
- if name is None:
- return {'message': 'Welcome to API Star!'}
- return {'message': 'Welcome to API Star, %s!' % name}
-
-
-routes = [
- Route('/', 'GET', welcome),
- Include('/docs', docs_urls),
- Include('/static', static_urls)
-]
-
-app = App(routes=routes)
-
-
-if __name__ == '__main__':
- app.main()
-
-```
-
-Before we dive into the code, let’s run the app and see if it works. If we navigate to `http://127.0.0.1:8080/` we will get this following response:
-```
-{"message": "Welcome to API Star!"}
-
-```
-
-And if we navigate to: `http://127.0.0.1:8080/?name=masnun`
-```
-{"message": "Welcome to API Star, masnun!"}
-
-```
-
-Similarly if we navigate to: `http://127.0.0.1:8080/docs/`, we will see auto generated docs for our API.
-
-Now let’s look at the code. We have a `welcome` function that takes a parameter named `name` which has a default value of `None`. API Star is a smart api framework. It will try to find the `name` key in the url path or query string and pass it to our function. It also generates the API docs based on it. Pretty nice, no?
-
-We then create a list of `Route` and `Include` instances and pass the list to the `App` instance. `Route` objects are used to define custom user routing. `Include` , as the name suggests, includes/embeds other routes under the path provided to it.
-
-### Routing
-
-Routing is simple. When constructing the `App` instance, we need to pass a list as the `routes` argument. This list should comprise of `Route` or `Include` objects as we just saw above. For `Route`s, we pass a url path, http method name and the request handler callable (function or otherwise). For the `Include` instances, we pass a url path and a list of `Routes` instance.
-
-##### Path Parameters
-
-We can put a name inside curly braces to declare a url path parameter. For example `/user/{user_id}` defines a path where the `user_id` is a path parameter or a variable which will be injected into the handler function (actually callable). Here’s a quick example:
-```
-from apistar import Route
-from apistar.frameworks.wsgi import WSGIApp as App
-
-
-def user_profile(user_id: int):
- return {'message': 'Your profile id is: {}'.format(user_id)}
-
-
-routes = [
- Route('/user/{user_id}', 'GET', user_profile),
-]
-
-app = App(routes=routes)
-
-if __name__ == '__main__':
- app.main()
-
-```
-
-If we visit `http://127.0.0.1:8080/user/23` we will get a response like this:
-```
-{"message": "Your profile id is: 23"}
-
-```
-
-But if we try to visit `http://127.0.0.1:8080/user/some_string` – it will not match. Because the `user_profile` function we defined, we added a type hint for the `user_id` parameter. If it’s not integer, the path doesn’t match. But if we go ahead and delete the type hint and just use `user_profile(user_id)`, it will match this url. This is again API Star is being smart and taking advantages of typing.
-
-#### Including / Grouping Routes
-
-Sometimes it might make sense to group certain urls together. Say we have a `user` module that deals with user related functionality. It might be better to group all the user related endpoints under the `/user` path. For example – `/user/new`, `/user/1`, `/user/1/update` and what not. We can easily create our handlers and routes in a separate module or package even and then include them in our own routes.
-
-Let’s create a new module named `user`, the file name would be `user.py`. Let’s put these codes in this file:
-```
-from apistar import Route
-
-
-def user_new():
- return {"message": "Create a new user"}
-
-
-def user_update(user_id: int):
- return {"message": "Update user #{}".format(user_id)}
-
-
-def user_profile(user_id: int):
- return {"message": "User Profile for: {}".format(user_id)}
-
-
-user_routes = [
- Route("/new", "GET", user_new),
- Route("/{user_id}/update", "GET", user_update),
- Route("/{user_id}/profile", "GET", user_profile),
-]
-
-```
-
-Now we can import our `user_routes` from within our main app file and use it like this:
-```
-from apistar import Include
-from apistar.frameworks.wsgi import WSGIApp as App
-
-from user import user_routes
-
-routes = [
- Include("/user", user_routes)
-]
-
-app = App(routes=routes)
-
-if __name__ == '__main__':
- app.main()
-
-```
-
-Now `/user/new` will delegate to `user_new` function.
-
-### Accessing Query String / Query Parameters
-
-Any parameters passed in the query parameters can be injected directly into handler function. Say for the url `/call?phone=1234`, the handler function can define a `phone` parameter and it will receive the value from the query string / query parameters. If the url query string doesn’t include a value for `phone`, it will get `None` instead. We can also set a default value to the parameter like this:
-```
-def welcome(name=None):
- if name is None:
- return {'message': 'Welcome to API Star!'}
- return {'message': 'Welcome to API Star, %s!' % name}
-
-```
-
-In the above example, we set a default value to `name` which is `None` anyway.
-
-### Injecting Objects
-
-By type hinting a request handler, we can have different objects injected into our views. Injecting request related objects can be helpful for accessing them directly from inside the handler. There are several built in objects in the `http` package from API Star itself. We can also use it’s type system to create our own custom objects and have them injected into our functions. API Star also does data validation based on the constraints specified.
-
-Let’s define our own `User` type and have it injected in our request handler:
-```
-from apistar import Include, Route
-from apistar.frameworks.wsgi import WSGIApp as App
-from apistar import typesystem
-
-
-class User(typesystem.Object):
- properties = {
- 'name': typesystem.string(max_length=100),
- 'email': typesystem.string(max_length=100),
- 'age': typesystem.integer(maximum=100, minimum=18)
- }
-
- required = ["name", "age", "email"]
-
-
-def new_user(user: User):
- return user
-
-
-routes = [
- Route('/', 'POST', new_user),
-]
-
-app = App(routes=routes)
-
-if __name__ == '__main__':
- app.main()
-
-```
-
-Now if we send this request:
-
-```
-curl -X POST \
- http://127.0.0.1:8080/ \
- -H 'Cache-Control: no-cache' \
- -H 'Content-Type: application/json' \
- -d '{"name": "masnun", "email": "masnun@gmail.com", "age": 12}'
-```
-
-Guess what happens? We get an error saying age must be equal to or greater than 18. The type system is allowing us intelligent data validation as well. If we enable the `docs` url, we will also get these parameters automatically documented there.
-
-### Sending a Response
-
-If you have noticed so far, we can just pass a dictionary and it will be JSON encoded and returned by default. However, we can set the status code and any additional headers by using the `Response` class from `apistar`. Here’s a quick example:
-```
-from apistar import Route, Response
-from apistar.frameworks.wsgi import WSGIApp as App
-
-
-def hello():
- return Response(
- content="Hello".encode("utf-8"),
- status=200,
- headers={"X-API-Framework": "API Star"},
- content_type="text/plain"
- )
-
-
-routes = [
- Route('/', 'GET', hello),
-]
-
-app = App(routes=routes)
-
-if __name__ == '__main__':
- app.main()
-
-```
-
-It should send a plain text response along with a custom header. Please note that the `content` should be bytes, not string. That’s why I encoded it.
-
-### Moving On
-
-I just walked through some of the features of API Star. There’s a lot more of cool stuff in API Star. I do recommend going through the [Github Readme][2] for learning more about different features offered by this excellent framework. I shall also try to cover short, focused tutorials on API Star in the coming days.
-
---------------------------------------------------------------------------------
-
-via: http://polyglot.ninja/api-star-python-3-api-framework/
-
-作者:[MASNUN][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:http://polyglot.ninja/author/masnun/
-[1]:http://polyglot.ninja/rest-api-best-practices-python-flask-tutorial/
-[2]:https://github.com/encode/apistar
diff --git a/sources/tech/20180205 Writing eBPF tracing tools in Rust.md b/sources/tech/20180205 Writing eBPF tracing tools in Rust.md
index 18b8eb5742..093d3de215 100644
--- a/sources/tech/20180205 Writing eBPF tracing tools in Rust.md
+++ b/sources/tech/20180205 Writing eBPF tracing tools in Rust.md
@@ -1,3 +1,4 @@
+Zafiry translating...
Writing eBPF tracing tools in Rust
============================================================
diff --git a/sources/tech/20180215 Build a bikesharing app with Redis and Python.md b/sources/tech/20180215 Build a bikesharing app with Redis and Python.md
index 67ddd07730..06e4c6949a 100644
--- a/sources/tech/20180215 Build a bikesharing app with Redis and Python.md
+++ b/sources/tech/20180215 Build a bikesharing app with Redis and Python.md
@@ -1,5 +1,3 @@
-hankchow translating
-
Build a bikesharing app with Redis and Python
======
diff --git a/sources/tech/20180226 Linux Virtual Machines vs Linux Live Images.md b/sources/tech/20180226 Linux Virtual Machines vs Linux Live Images.md
deleted file mode 100644
index f846e9486d..0000000000
--- a/sources/tech/20180226 Linux Virtual Machines vs Linux Live Images.md
+++ /dev/null
@@ -1,58 +0,0 @@
-Linux Virtual Machines vs Linux Live Images
-======
-I'll be the first to admit that I tend to try out new [Linux distros][1] on a far too frequent basis. Yet the method I use to test them, does vary depending on my goals for each instance. In this article, we're going to look at both running Linux virtual machines and running Linux live images. There are advantages to each method, but there are some hurdles with each method as well.
-
-### Testing out a new Linux distro for the first time
-
-When I test out a brand new Linux distro for the first time, the method I use depends heavily on the resources of the PC I'm currently on. If I have access to my desktop PC, I'm going to run the distro to be tested in a virtual machine. The reason for this approach is that I can download and test the distro in not only a live environment, but also as an installed product with persistent storage abilities.
-
-On the other hand, if I am working with much less robust hardware on a PC, then testing out a distro with a virtual machine installation of Linux is counter-productive. I'd be pushing that PC to its limits and honestly would be better off using a live Linux image instead running from a flash drive.
-
-### Touring software on a new Linux distro
-
-If you're interested in checking out a distro's desktop environment or the available software, you can't go wrong with a live image of the distro. A live environment provides you with a birds eye view of what to expect in terms of overall layout, applications provided and how the user experience flows overall.
-
-To be fair, you could do the same thing with a virtual machine installation, but it may be a bit overkill if you would rather avoid filling up hard drive space with yet more data. After all, this is a simple tour of the distro. Remember what I said in the first section – I like to run Linux in a virtual machine to test it. This means I'm going to see how it installs, what the partition options look like and other elements you wouldn't see from using a live image of any given distro.
-
-Touring usually indicates that you're only looking to take a quick look at a distro, so in this case the method that can be done with the least amount of resistance and time investment is a good course of action.
-
-### Taking a Linux distro with you
-
-While it's not as common as it was a few years ago, the ability to take a Linux distro with you may be a consideration for some users. Obviously, virtual machine installations don't necessarily lend themselves favorably to portability. However a live image of a Linux distro is actually quite portable. A live image can be written to a DVD or copied onto a flash drive for easy traveling.
-
-Expanding on this concept of Linux portability, it's also beneficial to have a live image on a flash drive when showing off how Linux works on a friend's computer. This empowers you to demonstrate how Linux can enrich their life while not relying on running a virtual machine on their PC. It's a bit of a win-win in favor of using a live image.
-
-### Alternative to dual-booting Linux
-
-This next item is a huge one. Consider this – perhaps you're a Windows user. You like playing with Linux, but would rather not take the plunge. Dual-booting is out of the question in case something goes wrong or perhaps you're not comfortable identifying individual partitions. Whatever the case may be, both using Linux in a virtual machine or from a live image might be a great option for you.
-
-Now I'm going to take a rather odd stance on something. I think you'll get far more value in the long term running Linux on a flash drive using a live image than with a virtual machine. There are two reasons for this. First of all, you'll get used to truly running Linux vs running it inside of a virtual machine on top of Windows. Second, you can setup your flash drive to contain user data with persistent storage.
-
-I'll grant you the same could be said with a virtual machine running Linux, however you will never have an update break anything using the live image approach. Why? Because you're not updating a host OS or the guest OS. Remember there are entire distros that are designed to be nothing more than persistent storage Linux distros. Puppy Linux is one great example. Not only can it run on PCs that would otherwise be recycled or thrown away, it allows you to never be bothered again with tedious system updates thanks to the way the distro handles security. It's not a normal Linux distro and it's walled off in such a way that the persistent live image is free from anything scary.
-
-### When a Linux virtual machine is absolutely the best option
-
-As I bring this article to a close, let me leave you with this. There is one instance where using a virtual machine such as Virtual Box is absolutely better than using a live image – recording the desktop environment of any Linux distro.
-
-For example, I make videos that provide a tour and review of a variety of Linux distros. Doing this with live images would require me to capture the screen with a hardware device or install a software capture device from the live image's repositories. Clearly, a virtual machine is better suited for this job than a live image of a Linux distro.
-
-Once you toss audio capture into the mix, there is no question that if you're going to use software to capture your review, you really want to have a host OS that has all the basic needs covered for a reasonably decent capture environment. Again, you could do all of this with a hardware device...but that might be cost prohibitive if you're only do video/audio capturing as a part time endeavor.
-
-### A Linux virtual machine vs a Linux live image
-
-What is your preferred method of trying out new distros? Perhaps you're someone who is fine with formatting their hard drive and throwing caution to the wind, thus, making the idea of any of this unneeded?
-
-Most people I've interacted with online tend to follow much of the methodology I've touched on above, but I'd love to hear what approach works best for you. Hit the comments, let me know which method you prefer when checking out the greatest and latest from the Linux distro world.
-
---------------------------------------------------------------------------------
-
-via: https://www.datamation.com/open-source/linux-virtual-machines-vs-linux-live-images.html
-
-作者:[Matt Hartley][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://www.datamation.com/author/Matt-Hartley-3080.html
-[1]:https://www.datamation.com/open-source/best-linux-distro.html
diff --git a/sources/tech/20180306 How To Check All Running Services In Linux.md b/sources/tech/20180306 How To Check All Running Services In Linux.md
deleted file mode 100644
index 7baf3c3e14..0000000000
--- a/sources/tech/20180306 How To Check All Running Services In Linux.md
+++ /dev/null
@@ -1,516 +0,0 @@
-How To Check All Running Services In Linux
-======
-
-There are many ways and tools to check and list all running services in Linux. Usually most of the administrator use `service service-name status` or `/etc/init.d/service-name status` for sysVinit system and `systemctl status service-name` for systemd systems.
-
-The above command clearly shows that the mentioned service is running on server or not. It is very simple and basic command that should known by every Linux administrator.
-
-If you are new to your environment and you don’t know what services are running on the system. How do you check?
-
-Yes, we can check this. This will will help us to understand what are the services are running on the system and whether it’s necessary or need to disable.
-
-### What Is SysVinit
-
-init (short for initialization) is the first process started during booting of the computer system. Init is a daemon process that continues running until the system is shut down.
-
-SysVinit is an old and traditional init system and system manager for old systems. Most of the latest distributions were adapted to systemd system due to some of the long pending issues on sysVinit system.
-
-### What Is systemd
-
-systemd is a new init system and system manager which is become very popular and widely adapted new standard init system by most of Linux distributions. Systemctl is a systemd utility which is help us to manage systemd system.
-
-### Method-1: How To Check Running Services In sysVinit System
-
-The below command helps us to check and list all running services in sysVinit system.
-
-If you have many number of services, i would advise you to use file view commands such as less, more, etc commands for clear view.
-```
-# service --status-all
-or
-# service --status-all | more
-or
-# service --status-all | less
-
-abrt-ccpp hook is installed
-abrtd (pid 2131) is running...
-abrt-dump-oops is stopped
-acpid (pid 1958) is running...
-atd (pid 2164) is running...
-auditd (pid 1731) is running...
-Frequency scaling enabled using ondemand governor
-crond (pid 2153) is running...
-hald (pid 1967) is running...
-htcacheclean is stopped
-httpd is stopped
-Table: filter
-Chain INPUT (policy ACCEPT)
-num target prot opt source destination
-1 ACCEPT all ::/0 ::/0 state RELATED,ESTABLISHED
-2 ACCEPT icmpv6 ::/0 ::/0
-3 ACCEPT all ::/0 ::/0
-4 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:80
-5 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:21
-6 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:22
-7 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:25
-8 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:2082
-9 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:2086
-10 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:2083
-11 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:2087
-12 ACCEPT tcp ::/0 ::/0 state NEW tcp dpt:10000
-13 REJECT all ::/0 ::/0 reject-with icmp6-adm-prohibited
-
-Chain FORWARD (policy ACCEPT)
-num target prot opt source destination
-1 REJECT all ::/0 ::/0 reject-with icmp6-adm-prohibited
-
-Chain OUTPUT (policy ACCEPT)
-num target prot opt source destination
-
-iptables: Firewall is not running.
-irqbalance (pid 1826) is running...
-Kdump is operational
-lvmetad is stopped
-mdmonitor is stopped
-messagebus (pid 1929) is running...
- SUCCESS! MySQL running (24376)
-rndc: neither /etc/rndc.conf nor /etc/rndc.key was found
-named is stopped
-netconsole module not loaded
-Usage: startup.sh { start | stop }
-Configured devices:
-lo eth0 eth1
-Currently active devices:
-lo eth0
-ntpd is stopped
-portreserve (pid 1749) is running...
-master (pid 2107) is running...
-Process accounting is disabled.
-quota_nld is stopped
-rdisc is stopped
-rngd is stopped
-rpcbind (pid 1840) is running...
-rsyslogd (pid 1756) is running...
-sandbox is stopped
-saslauthd is stopped
-smartd is stopped
-openssh-daemon (pid 9859) is running...
-svnserve is stopped
-vsftpd (pid 4008) is running...
-xinetd (pid 2031) is running...
-zabbix_agentd (pid 2150 2149 2148 2147 2146 2140) is running...
-
-```
-
-Run the following command to view only running services in the system.
-```
-# service --status-all | grep running
-
-crond (pid 535) is running...
-httpd (pid 627) is running...
-mysqld (pid 911) is running...
-rndc: neither /etc/rndc.conf nor /etc/rndc.key was found
-rsyslogd (pid 449) is running...
-saslauthd (pid 492) is running...
-sendmail (pid 509) is running...
-sm-client (pid 519) is running...
-openssh-daemon (pid 478) is running...
-xinetd (pid 485) is running...
-
-```
-
-Run the following command to view the particular service status.
-```
-# service --status-all | grep httpd
-httpd (pid 627) is running...
-
-```
-
-Alternatively use the following command to view the particular service status.
-```
-# service httpd status
-
-httpd (pid 627) is running...
-
-```
-
-Use the following command to view the list of running services enabled in boot.
-```
-# chkconfig --list
-crond 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-htcacheclean 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-httpd 0:off 1:off 2:off 3:on 4:off 5:off 6:off
-ip6tables 0:off 1:off 2:on 3:off 4:on 5:on 6:off
-iptables 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-modules_dep 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-mysqld 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-named 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-netconsole 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-netfs 0:off 1:off 2:off 3:off 4:on 5:on 6:off
-network 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-nmb 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-nscd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-portreserve 0:off 1:off 2:on 3:off 4:on 5:on 6:off
-quota_nld 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-rdisc 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-restorecond 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-rpcbind 0:off 1:off 2:on 3:off 4:on 5:on 6:off
-rsyslog 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-saslauthd 0:off 1:off 2:off 3:on 4:off 5:off 6:off
-sendmail 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-smb 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-snmpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-snmptrapd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
-udev-post 0:off 1:on 2:on 3:off 4:on 5:on 6:off
-winbind 0:off 1:off 2:off 3:off 4:off 5:off 6:off
-xinetd 0:off 1:off 2:off 3:on 4:on 5:on 6:off
-
-xinetd based services:
- chargen-dgram: off
- chargen-stream: off
- daytime-dgram: off
- daytime-stream: off
- discard-dgram: off
- discard-stream: off
- echo-dgram: off
- echo-stream: off
- finger: off
- ntalk: off
- rsync: off
- talk: off
- tcpmux-server: off
- time-dgram: off
- time-stream: off
-
-```
-
-### Method-2: How To Check Running Services In systemd System
-
-The below command helps us to check and list all running services in “systemd” system.
-```
-# systemctl
-
- UNIT LOAD ACTIVE SUB DESCRIPTION
- sys-devices-virtual-block-loop0.device loaded active plugged /sys/devices/virtual/block/loop0
- sys-devices-virtual-block-loop1.device loaded active plugged /sys/devices/virtual/block/loop1
- sys-devices-virtual-block-loop2.device loaded active plugged /sys/devices/virtual/block/loop2
- sys-devices-virtual-block-loop3.device loaded active plugged /sys/devices/virtual/block/loop3
- sys-devices-virtual-block-loop4.device loaded active plugged /sys/devices/virtual/block/loop4
- sys-devices-virtual-misc-rfkill.device loaded active plugged /sys/devices/virtual/misc/rfkill
- sys-devices-virtual-tty-ttyprintk.device loaded active plugged /sys/devices/virtual/tty/ttyprintk
- sys-module-fuse.device loaded active plugged /sys/module/fuse
- sys-subsystem-net-devices-enp0s3.device loaded active plugged 82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter)
- -.mount loaded active mounted Root Mount
- dev-hugepages.mount loaded active mounted Huge Pages File System
- dev-mqueue.mount loaded active mounted POSIX Message Queue File System
- run-user-1000-gvfs.mount loaded active mounted /run/user/1000/gvfs
- run-user-1000.mount loaded active mounted /run/user/1000
- snap-core-3887.mount loaded active mounted Mount unit for core
- snap-core-4017.mount loaded active mounted Mount unit for core
- snap-core-4110.mount loaded active mounted Mount unit for core
- snap-gping-13.mount loaded active mounted Mount unit for gping
- snap-termius\x2dapp-8.mount loaded active mounted Mount unit for termius-app
- sys-fs-fuse-connections.mount loaded active mounted FUSE Control File System
- sys-kernel-debug.mount loaded active mounted Debug File System
- acpid.path loaded active running ACPI Events Check
- cups.path loaded active running CUPS Scheduler
- systemd-ask-password-plymouth.path loaded active waiting Forward Password Requests to Plymouth Directory Watch
- systemd-ask-password-wall.path loaded active waiting Forward Password Requests to Wall Directory Watch
- init.scope loaded active running System and Service Manager
- session-c2.scope loaded active running Session c2 of user magi
- accounts-daemon.service loaded active running Accounts Service
- acpid.service loaded active running ACPI event daemon
- anacron.service loaded active running Run anacron jobs
- apache2.service loaded active running The Apache HTTP Server
- apparmor.service loaded active exited AppArmor initialization
- apport.service loaded active exited LSB: automatic crash report generation
- aptik-battery-monitor.service loaded active running LSB: start/stop the aptik battery monitor daemon
- atop.service loaded active running Atop advanced performance monitor
- atopacct.service loaded active running Atop process accounting daemon
- avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
- colord.service loaded active running Manage, Install and Generate Color Profiles
- console-setup.service loaded active exited Set console font and keymap
- cron.service loaded active running Regular background program processing daemon
- cups-browsed.service loaded active running Make remote CUPS printers available locally
- cups.service loaded active running CUPS Scheduler
- dbus.service loaded active running D-Bus System Message Bus
- postfix.service loaded active exited Postfix Mail Transport Agent
-
-```
-
- * **`UNIT`** Unit describe about the corresponding systemd unit name.
- * **`LOAD`** This describes whether the corresponding unit currently loaded in memory or not.
- * **`ACTIVE`** It’s indicate whether the unit is active or not.
- * **`SUB`** It’s indicate whether the unit is running state or not.
- * **`DESCRIPTION`** A short description about the unit.
-
-
-
-The below option help you to list units based on the type.
-```
-# systemctl list-units --type service
- UNIT LOAD ACTIVE SUB DESCRIPTION
- accounts-daemon.service loaded active running Accounts Service
- acpid.service loaded active running ACPI event daemon
- anacron.service loaded active running Run anacron jobs
- apache2.service loaded active running The Apache HTTP Server
- apparmor.service loaded active exited AppArmor initialization
- apport.service loaded active exited LSB: automatic crash report generation
- aptik-battery-monitor.service loaded active running LSB: start/stop the aptik battery monitor daemon
- atop.service loaded active running Atop advanced performance monitor
- atopacct.service loaded active running Atop process accounting daemon
- avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
- colord.service loaded active running Manage, Install and Generate Color Profiles
- console-setup.service loaded active exited Set console font and keymap
- cron.service loaded active running Regular background program processing daemon
- cups-browsed.service loaded active running Make remote CUPS printers available locally
- cups.service loaded active running CUPS Scheduler
- dbus.service loaded active running D-Bus System Message Bus
- fwupd.service loaded active running Firmware update daemon
- [email protected] loaded active running Getty on tty1
- grub-common.service loaded active exited LSB: Record successful boot for GRUB
- irqbalance.service loaded active running LSB: daemon to balance interrupts for SMP systems
- keyboard-setup.service loaded active exited Set the console keyboard layout
- kmod-static-nodes.service loaded active exited Create list of required static device nodes for the current kernel
-
-```
-
-The below option help you to list units based on the state. It’s similar to the above output but straight forward.
-```
-# systemctl list-unit-files --type service
-
-UNIT FILE STATE
-accounts-daemon.service enabled
-acpid.service disabled
-alsa-restore.service static
-alsa-state.service static
-alsa-utils.service masked
-anacron-resume.service enabled
-anacron.service enabled
-apache-htcacheclean.service disabled
-[email protected] disabled
-apache2.service enabled
-[email protected] disabled
-apparmor.service enabled
-[email protected] static
-apport.service generated
-apt-daily-upgrade.service static
-apt-daily.service static
-aptik-battery-monitor.service generated
-atop.service enabled
-atopacct.service enabled
-[email protected] enabled
-avahi-daemon.service enabled
-bluetooth.service enabled
-
-```
-
-Run the following command to view the particular service status.
-```
-# systemctl | grep apache2
- apache2.service loaded active running The Apache HTTP Server
-
-```
-
-Alternatively use the following command to view the particular service status.
-```
-# systemctl status apache2
-● apache2.service - The Apache HTTP Server
- Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
- Drop-In: /lib/systemd/system/apache2.service.d
- └─apache2-systemd.conf
- Active: active (running) since Tue 2018-03-06 12:34:09 IST; 8min ago
- Process: 2786 ExecReload=/usr/sbin/apachectl graceful (code=exited, status=0/SUCCESS)
- Main PID: 1171 (apache2)
- Tasks: 55 (limit: 4915)
- CGroup: /system.slice/apache2.service
- ├─1171 /usr/sbin/apache2 -k start
- ├─2790 /usr/sbin/apache2 -k start
- └─2791 /usr/sbin/apache2 -k start
-
-Mar 06 12:34:08 magi-VirtualBox systemd[1]: Starting The Apache HTTP Server...
-Mar 06 12:34:09 magi-VirtualBox apachectl[1089]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 10.0.2.15. Set the 'ServerName' directive globally to suppre
-Mar 06 12:34:09 magi-VirtualBox systemd[1]: Started The Apache HTTP Server.
-Mar 06 12:39:10 magi-VirtualBox systemd[1]: Reloading The Apache HTTP Server.
-Mar 06 12:39:10 magi-VirtualBox apachectl[2786]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using fe80::7929:4ed1:279f:4d65. Set the 'ServerName' directive gl
-Mar 06 12:39:10 magi-VirtualBox systemd[1]: Reloaded The Apache HTTP Server.
-
-```
-
-Run the following command to view only running services in the system.
-```
-# systemctl | grep running
- acpid.path loaded active running ACPI Events Check
- cups.path loaded active running CUPS Scheduler
- init.scope loaded active running System and Service Manager
- session-c2.scope loaded active running Session c2 of user magi
- accounts-daemon.service loaded active running Accounts Service
- acpid.service loaded active running ACPI event daemon
- apache2.service loaded active running The Apache HTTP Server
- aptik-battery-monitor.service loaded active running LSB: start/stop the aptik battery monitor daemon
- atop.service loaded active running Atop advanced performance monitor
- atopacct.service loaded active running Atop process accounting daemon
- avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
- colord.service loaded active running Manage, Install and Generate Color Profiles
- cron.service loaded active running Regular background program processing daemon
- cups-browsed.service loaded active running Make remote CUPS printers available locally
- cups.service loaded active running CUPS Scheduler
- dbus.service loaded active running D-Bus System Message Bus
- fwupd.service loaded active running Firmware update daemon
- [email protected] loaded active running Getty on tty1
- irqbalance.service loaded active running LSB: daemon to balance interrupts for SMP systems
- lightdm.service loaded active running Light Display Manager
- ModemManager.service loaded active running Modem Manager
- NetworkManager.service loaded active running Network Manager
- polkit.service loaded active running Authorization Manager
-
-```
-
-Use the following command to view the list of running services enabled in boot.
-```
-# systemctl list-unit-files | grep enabled
-acpid.path enabled
-cups.path enabled
-accounts-daemon.service enabled
-anacron-resume.service enabled
-anacron.service enabled
-apache2.service enabled
-apparmor.service enabled
-atop.service enabled
-atopacct.service enabled
-[email protected] enabled
-avahi-daemon.service enabled
-bluetooth.service enabled
-console-setup.service enabled
-cron.service enabled
-cups-browsed.service enabled
-cups.service enabled
-display-manager.service enabled
-dns-clean.service enabled
-friendly-recovery.service enabled
-[email protected] enabled
-gpu-manager.service enabled
-keyboard-setup.service enabled
-lightdm.service enabled
-ModemManager.service enabled
-network-manager.service enabled
-networking.service enabled
-NetworkManager-dispatcher.service enabled
-NetworkManager-wait-online.service enabled
-NetworkManager.service enabled
-
-```
-
-systemd-cgtop show top control groups by their resource usage such as tasks, CPU, Memory, Input, and Output.
-```
-# systemd-cgtop
-
-Control Group Tasks %CPU Memory Input/s Output/s
-/ - - 1.5G - -
-/init.scope 1 - - - -
-/system.slice 153 - - - -
-/system.slice/ModemManager.service 3 - - - -
-/system.slice/NetworkManager.service 4 - - - -
-/system.slice/accounts-daemon.service 3 - - - -
-/system.slice/acpid.service 1 - - - -
-/system.slice/apache2.service 55 - - - -
-/system.slice/aptik-battery-monitor.service 1 - - - -
-/system.slice/atop.service 1 - - - -
-/system.slice/atopacct.service 1 - - - -
-/system.slice/avahi-daemon.service 2 - - - -
-/system.slice/colord.service 3 - - - -
-/system.slice/cron.service 1 - - - -
-/system.slice/cups-browsed.service 3 - - - -
-/system.slice/cups.service 2 - - - -
-/system.slice/dbus.service 6 - - - -
-/system.slice/fwupd.service 5 - - - -
-/system.slice/irqbalance.service 1 - - - -
-/system.slice/lightdm.service 7 - - - -
-/system.slice/polkit.service 3 - - - -
-/system.slice/repowerd.service 14 - - - -
-/system.slice/rsyslog.service 4 - - - -
-/system.slice/rtkit-daemon.service 3 - - - -
-/system.slice/snapd.service 8 - - - -
-/system.slice/system-getty.slice 1 - - - -
-
-```
-
-Also we can check the running services using pstree command (Output from SysVinit system).
-```
-# pstree
-init-|-crond
- |-httpd---2*[httpd]
- |-kthreadd/99149---khelper/99149
- |-2*[mingetty]
- |-mysqld_safe---mysqld---9*[{mysqld}]
- |-rsyslogd---3*[{rsyslogd}]
- |-saslauthd---saslauthd
- |-2*[sendmail]
- |-sshd---sshd---bash---pstree
- |-udevd
- `-xinetd
-
-```
-
-Also we can check the running services using pstree command (Output from systemd system).
-```
-# pstree
-systemd─┬─ModemManager─┬─{gdbus}
- │ └─{gmain}
- ├─NetworkManager─┬─dhclient
- │ ├─{gdbus}
- │ └─{gmain}
- ├─accounts-daemon─┬─{gdbus}
- │ └─{gmain}
- ├─acpid
- ├─agetty
- ├─anacron
- ├─apache2───2*[apache2───26*[{apache2}]]
- ├─aptd───{gmain}
- ├─aptik-battery-m
- ├─atop
- ├─atopacctd
- ├─avahi-daemon───avahi-daemon
- ├─colord─┬─{gdbus}
- │ └─{gmain}
- ├─cron
- ├─cups-browsed─┬─{gdbus}
- │ └─{gmain}
- ├─cupsd
- ├─dbus-daemon
- ├─fwupd─┬─{GUsbEventThread}
- │ ├─{fwupd}
- │ ├─{gdbus}
- │ └─{gmain}
- ├─gnome-keyring-d─┬─{gdbus}
- │ ├─{gmain}
- │ └─{timer}
-
-```
-
-### Method-3: How To Check Running Services In systemd System using chkservice
-
-chkservice is a new tool for managing systemd units in terminal. It requires super user privileges to manage the units.
-```
-# chkservice
-
-```
-
-![][1]
-
-To view help page, hit `?` button. This will shows you available options to manage the systemd services.
-![][2]
-
---------------------------------------------------------------------------------
-
-via: https://www.2daygeek.com/how-to-check-all-running-services-in-linux/
-
-作者:[Magesh Maruthamuthu][a]
-译者:[译者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/magesh/
-[1]:https://www.2daygeek.com/wp-content/uploads/2018/03/chkservice-1.png
-[2]:https://www.2daygeek.com/wp-content/uploads/2018/03/chkservice-2.png
diff --git a/sources/tech/20180313 Migrating to Linux- Using Sudo.md b/sources/tech/20180313 Migrating to Linux- Using Sudo.md
deleted file mode 100644
index 7ad9426ab8..0000000000
--- a/sources/tech/20180313 Migrating to Linux- Using Sudo.md
+++ /dev/null
@@ -1,84 +0,0 @@
-translating---geekpi
-
-Migrating to Linux: Using Sudo
-======
-
-
-
-This article is the fifth in our series about migrating to Linux. If you missed earlier ones, you can catch up here:
-
-[Part 1 - An Introduction][1]
-
-[Part 2 - Disks, Files, and Filesystems][2]
-
-[Part 3 - Graphical Environments][3]
-
-[Part 4 - The Command Line][4]
-
-You may have been wondering about Linux for a while. Perhaps it's used in your workplace and you'd be more efficient at your job if you used it on a daily basis. Or, perhaps you'd like to install Linux on some computer equipment you have at home. Whatever the reason, this series of articles is here to make the transition easier.
-
-Linux, like many other operating systems supports multiple users. It even supports multiple users being logged in simultaneously.
-
-User accounts are typically assigned a home directory where files can be stored. Usually this home directory is in:
-```
-/home/
-
-```
-
-This way, each user has their own separate location for their documents and other files.
-
-### Admin Tasks
-
-In a traditional Linux installation, regular user accounts don't have permissions to perform administrative tasks on the system. And instead of assigning rights to each user to perform various tasks, a typical Linux installation will require a user to log in as the admin to do certain tasks.
-
-The administrator account on Linux is called root.
-
-### Sudo Explained
-
-Historically, to perform admin tasks, one would have to login as root, perform the task, and then log back out. This process was a bit tedious, so many folks logged in as root and worked all day long as the admin. This practice could lead to disastrous results, for example, accidentally deleting all the files in the system. The root user, of course, can do anything, so there are no protections to prevent someone from accidentally performing far-reaching actions.
-
-The sudo facility was created to make it easier to login as your regular user account and occasionally perform admin tasks as root without having to login, do the task, and log back out. Specifically, sudo allows you to run a command as a different user. If you don't specify a specific user, it assumes you mean root.
-
-Sudo can have complex settings to allow users certain permissions to use sudo for some commands but not for others. Typically, a desktop installation will make it so the first account created has full permissions in sudo, so you as the primary user can fully administer your Linux installation.
-
-### Using Sudo
-
-Some Linux installations set up sudo so that you still need to know the password for the root account to perform admin tasks. Others, set up sudo so that you type in your own password. There are different philosophies here.
-
-When you try to perform an admin task in the graphical environment, it will usually open a dialog box asking for a password. Enter either your own password (e.g., on Ubuntu), or the root account's password (e.g., Red Hat).
-
-When you try to perform an admin task in the command line, it will usually just give you a "permission denied" error. Then you would re-run the command with sudo in front. For example:
-```
-systemctl start vsftpd
-Failed to start vsftpd.service: Access denied
-
-sudo systemctl start vsftpd
-[sudo] password for user1:
-
-```
-
-### When to Use Sudo
-
-Running commands as root (under sudo or otherwise) is not always the best solution to get around permission errors. While will running as root will remove the "permission denied" errors, it's sometimes best to look for the root cause rather than just addressing the symptom. Sometimes files have the wrong owner and permissions.
-
-Use sudo when you are trying to perform a task or run a program and the program requires root privileges to perform the operation. Don't use sudo if the file just happens to be owned by another user (including root). In this second case, it's better to set the permission on the file correctly.
-
-Learn more about Linux through the free ["Introduction to Linux" ][5]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/learn/2018/3/migrating-linux-using-sudo
-
-作者:[John Bonesio][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://www.linux.com/users/johnbonesio
-[1]:https://www.linux.com/blog/learn/intro-to-linux/2017/10/migrating-linux-introduction
-[2]:https://www.linux.com/blog/learn/intro-to-linux/2017/11/migrating-linux-disks-files-and-filesystems
-[3]:https://www.linux.com/blog/learn/2017/12/migrating-linux-graphical-environments
-[4]:https://www.linux.com/blog/learn/2018/1/migrating-linux-command-line
-[5]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180316 How to Encrypt Files From Within a File Manager.md b/sources/tech/20180316 How to Encrypt Files From Within a File Manager.md
deleted file mode 100644
index 491c18eb04..0000000000
--- a/sources/tech/20180316 How to Encrypt Files From Within a File Manager.md
+++ /dev/null
@@ -1,179 +0,0 @@
-How to Encrypt Files From Within a File Manager
-======
-
-
-The Linux desktop and server enjoys a remarkable level of security. That doesn’t mean, however, you should simply rest easy. You should always consider that your data is always a quick hack away from being compromised. That being said, you might want to employ various tools for encryption, such as GnuPG, which lets you encrypt and decrypt files and much more. One problem with GnuPG is that some users don’t want to mess with the command line. If that’s the case, you can turn to a desktop file manager. Many Linux desktops include the ability to easily encrypt or decrypt files, and if that capability is not built in, it’s easy to add.
-
-I will walk you through the process of encrypting and decrypting a file from within three popular Linux file managers:
-
- * Nautilus (aka GNOME Files)
-
- * Dolphin
-
- * Thunar
-
-
-
-
-### Installing GnuPG
-
-Before we get into the how to of this, we have to ensure your system includes the necessary base component… [GnuPG][1]. Most distributions ship with GnuPG included. On the off chance you use a distribution that doesn’t ship with GnuPG, here’s how to install it:
-
- * Ubuntu-based distribution: sudo apt install gnupg
-
- * Fedora-based distribution: sudo yum install gnupg
-
- * openSUSE: sudo zypper in gnupg
-
- * Arch-based distribution: sudo pacman -S gnupg
-
-
-
-
-Whether you’ve just now installed GnuPG or it was installed by default, you will have to create a GPG key for this to work. Each desktop uses a different GUI tool for this (or may not even include a GUI tool for the task), so let’s create that key from the command line. Open up your terminal window and issue the following command:
-```
-gpg --gen-key
-
-```
-
-You will then be asked to answer the following questions. Unless you have good reason, you can accept the defaults:
-
- * What kind of key do you want?
-
- * What key size do you want?
-
- * Key is valid for?
-
-
-
-
-Once you’ve answered these questions, type y to indicate the answers are correct. Next you’ll need to supply the following information:
-
- * Real name.
-
- * Email address.
-
- * Comment.
-
-
-
-
-Complete the above and then, when prompted, type O (for Okay). You will then be required to type a passphrase for the new key. Once the system has collected enough entropy (you’ll need to do some work on the desktop so this can happen), your key will have been created and you’re ready to go.
-
-Let’s see how to encrypt/decrypt files from within the file managers.
-
-### Nautilus
-
-We start with the default GNOME file manager because it is the easiest. Nautilus requires no extra installation or extra work to encrypt/decrypt files from within it’s well-designed interface. Once you have your gpg key created, you can open up the file manager, navigate to the directory housing the file to be encrypted, right-click the file in question, and select Encrypt from the menu (Figure 1).
-
-
-![nautilus][3]
-
-Figure 1: Encrypting a file from within Nautilus.
-
-[Used with permission][4]
-
-You will be asked to select a recipient (or list of recipients — Figure 2). NOTE: Recipients will be those users whose public keys you have imported. Select the necessary keys and then select your key (email address) from the Sign message as drop-down.
-
-![nautilus][6]
-
-Figure 2: Selecting recipients and a signer.
-
-[Used with permission][4]
-
-Notice you can also opt to encrypt the file with only a passphrase. This is important if the file will remain on your local machine (more on this later). Once you’ve set up the encryption, click OK and (when prompted) type the passphrase for your key. The file will be encrypted (now ending in .gpg) and saved in the working directory. You can now send that encrypted file to the recipients you selected during the encryption process.
-
-Say someone (who has your public key) has sent you an encrypted file. Save that file, open the file manager, navigate to the directory housing that file, right-click the encrypted file, select Open With Decrypt File, give the file a new name (without the .gpg extension), and click Save. When prompted, type your gpg key passphrase and the file will be decrypted and ready to use.
-
-### Dolphin
-
-On the KDE front, there’s a package that must be installed in order to encrypt/decrypt from with the Dolphin file manager. Log into your KDE desktop, open the terminal window, and issue the following command (I’m demonstrating with Neon. If your distribution isn’t Ubuntu-based, you’ll have to alter the command accordingly):
-```
-sudo apt install kgpg
-
-```
-
-Once that installs, logout and log back into the KDE desktop. You can open up Dolphin and right-click a file to be encrypted. Since this is the first time you’ve used kgpg, you’ll have to walk through a quick setup wizard (which self-explanatory). When you’ve completed the wizard, you can go back to that file, right-click it (Figure 3), and select Encrypt File.
-
-
-![Dolphin][8]
-
-Figure 3: Encrypting a file within Dolphin.
-
-[Used with permission][4]
-
-You’ll be prompted to select the key to use for encryption (Figure 4). Make your selection and click OK. The file will encrypt and you’re ready to send it to the recipient.
-
-Note: With KDE’s Dolphin file manager, you cannot encrypt with a passphrase only.
-
-
-![Dolphin][10]
-
-Figure 4: Selecting your recipients for encryption.
-
-[Used with permission][4]
-
-If you receive an encrypted file from a user who has your public key (or you have a file you’ve encrypted yourself), open up Dolphin, navigate to the file in question, double-click the file, give the file a new name, type the encryption passphrase, and click OK. You can now read your newly decrypted file. If you’ve encrypted the file with your own key, you won’t be prompted to type the passphrase (as it has already been stored).
-
-### Thunar
-
-The Thunar file manager is a bit trickier. There aren’t any extra packages to install; instead, you need to create new custom action for Encrypt. Once you’ve done this, you’ll have the ability to do this from within the file manager.
-
-To create the custom actions, open up the Thunar file manager and click Edit > Configure Custom Actions. In the resulting window, click the + button (Figure 5) and enter the following for an Encrypt action:
-
-Name: Encrypt
-
-Description: File Encryption
-
-Command: gnome-terminal -x gpg --encrypt --recipient %f
-
-Click OK to save this action.
-
-
-![Thunar][12]
-
-Figure 5: Creating an custom action within Thunar.
-
-[Used with permission][4]
-
-NOTE: If gnome-terminal isn’t your default terminal, substitute the command to open your default terminal in.
-
-You can also create an action that encrypts with a passphrase only (not a key). To do this, the details for the action would be:
-
-Name: Encrypt Passphrase
-
-Description: Encrypt with Passphrase only
-
-Command: gnome-terminal -x gpg -c %f
-
-You don’t need to create a custom action for the decryption process, as Thunar already knows what to do with an encrypted file. To decrypt a file, simply right-click it (within Thunar), select Open With Decrypt File, give the decrypted file a name, and (when/if prompted) type the encryption passphrase. Viola, your encrypted file has been decrypted and is ready to use.
-
-### One caveat
-
-Do note: If you encrypt your own files, using your own keys, you won’t need to enter an encryption passphrase to decrypt them (because your public keys are stored). If, however, you receive files from others (who have your public key) you will be required to enter your passphrase. If you’re wanting to store your own encrypted files, instead of encrypting them with a key, encrypt them with a passphrase only. This is possible with Nautilus and Thunar (but not KDE). By opting for passphrase encryption (over key encryption), when you go to decrypt the file, it will always prompt you for the passphrase.
-
-### Other file managers
-
-There are plenty of other file managers out there, some of them can work with encryption, some cannot. Chances are, you’re using one of these three tools, so the ability to add encryption/decryption to the contextual menu is not only possible, it’s pretty easy. Give this a try and see if it doesn’t make the process of encryption and decryption much easier.
-
-Learn more about Linux through the free ["Introduction to Linux" ][13] course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/learn/intro-to-linux/2018/3/how-encrypt-files-within-file-manager
-
-作者:[JACK WALLEN][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://www.linux.com/users/jlwallen
-[1]:https://www.gnupg.org/
-[3]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/nautilus.jpg?itok=ae7Gtj60 (nautilus)
-[4]:https://www.linux.com/licenses/category/used-permission
-[6]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/nautilus_2.jpg?itok=3ht7j63n (nautilus)
-[8]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/kde_0.jpg?itok=KSTctVw0 (Dolphin)
-[10]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/kde_2.jpg?itok=CeqWikNl (Dolphin)
-[12]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/thunar.jpg?itok=fXcHk08B (Thunar)
-[13]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180324 How To Compress And Decompress Files In Linux.md b/sources/tech/20180324 How To Compress And Decompress Files In Linux.md
deleted file mode 100644
index 8766b9e39b..0000000000
--- a/sources/tech/20180324 How To Compress And Decompress Files In Linux.md
+++ /dev/null
@@ -1,210 +0,0 @@
-How To Compress And Decompress Files In Linux
-======
-
-
-Compressing is quite useful when backing up important files and also sending large files over Internet. Please note that compressing an already compressed file adds extra overhead, hence you will get a slightly bigger file. So, stop compressing a compressed file. There are many programs to compress and decompress files in GNU/Linux. In this tutorial, we’re going to learn about two applications only.
-
-### Compress and decompress files
-
-The most common programs used to compress files in Unix-like systems are:
-
- 1. gzip
- 2. bzip2
-
-
-
-##### 1\. Compress and decompress files using Gzip program
-
-The gzip is an utility to compress and decompress files using Lempel-Ziv coding (LZ77) algorithm.
-
-**1.1 Compress files**
-
-To compress a file named **ostechnix.txt** , replacing it with a gzipped compressed version, run:
-```
-$ gzip ostechnix.txt
-
-```
-
-Gzip will replace the original file **ostechnix.txt** with a gzipped compressed version named **ostechnix.txt.gz**.
-
-The gzip command can also be used in other ways too. One fine example is we can create a compressed version of a specific command’s output. Look at the following command.
-```
-$ ls -l Downloads/ | gzip > ostechnix.txt.gz
-
-```
-
-The above command creates compressed version of the directory listing of Downloads folder.
-
-**1.2 Compress files and write the output to different files (Don’t replace the original file)
-**
-
-By default, gzip program will compress the given file, replacing it with a gzipped compressed version. You can, however, keep the original file and write the output to standard output. For example, the following command, compresses **ostechnix.txt** and writes the output to **output.txt.gz**.
-```
-$ gzip -c ostechnix.txt > output.txt.gz
-
-```
-
-Similarly, to decompress a gzipped file specifying the output filename:
-```
-$ gzip -c -d output.txt.gz > ostechnix1.txt
-
-```
-
-The above command decompresses the **output.txt.gz** file and writes the output to **ostechnix1.txt** file. In both cases, it won’t delete the original file.
-
-**1.3 Decompress files**
-
-To decompress the file **ostechnix.txt.gz** , replacing it with the original uncompressed version, we do:
-```
-$ gzip -d ostechnix.txt.gz
-
-```
-
-We can also use gunzip to decompress the files.
-```
-$ gunzip ostechnix.txt.gz
-
-```
-
-**1.4 View contents of compressed files without decompressing them**
-
-To view the contents of the compressed file using gzip without decompressing it, use **-c** flag as shown below:
-```
-$ gunzip -c ostechnix1.txt.gz
-
-```
-
-Alternatively, use **zcat** utility like below.
-```
-$ zcat ostechnix.txt.gz
-
-```
-
-You can also pipe the output to “less” command to view the output page by page like below.
-```
-$ gunzip -c ostechnix1.txt.gz | less
-
-$ zcat ostechnix.txt.gz | less
-
-```
-
-Alternatively, there is a **zless** program which performs the same function as the pipeline above.
-```
-$ zless ostechnix1.txt.gz
-
-```
-
-**1.5 Compress file with gzip by specifying compression level**
-
-Another notable advantage of gzip is it supports compression level. It supports 3 compression levels as given below.
-
- * **1** – Fastest (Worst)
- * **9** – Slowest (Best)
- * **6** – Default level
-
-
-
-To compress a file named **ostechnix.txt** , replacing it with a gzipped compressed version with **best** compression level, we use:
-```
-$ gzip -9 ostechnix.txt
-
-```
-
-**1.6 Concatenate multiple compressed files**
-
-It is also possible to concatenate multiple compressed files into one. How? Have a look at the following example.
-```
-$ gzip -c ostechnix1.txt > output.txt.gz
-
-$ gzip -c ostechnix2.txt >> output.txt.gz
-
-```
-
-The above two commands will compress ostechnix1.txt and ostechnix2.txt and saves them in one file named **output.txt.gz**.
-
-You can view the contents of both files (ostechnix1.txt and ostechnix2.txt) without extracting them using any one of the following commands:
-```
-$ gunzip -c output.txt.gz
-
-$ gunzip -c output.txt
-
-$ zcat output.txt.gz
-
-$ zcat output.txt
-
-```
-
-For more details, refer the man pages.
-```
-$ man gzip
-
-```
-
-##### 2\. Compress and decompress files using bzip2 program
-
-The **bzip2** is very similar to gzip program, but uses different compression algorithm named the Burrows-Wheeler block sorting text compression algorithm, and Huffman coding. The files compressed using bzip2 will end with **.bz2** extension.
-
-Like I said, the usage of bzip2 is almost same as gzip. Just replace **gzip** in the above examples with **bzip2** , **gunzip** with **bunzip2** , **zcat** with **bzcat** and so on.
-
-To compress a file using bzip2, replacing it with compressed version, run:
-```
-$ bzip2 ostechnix.txt
-
-```
-
-If you don’t want to replace the original file, use **-c** flag and write the output to a new file.
-```
-$ bzip2 -c ostechnix.txt > output.txt.bz2
-
-```
-
-To decompress a compressed file:
-```
-$ bzip2 -d ostechnix.txt.bz2
-
-```
-
-Or,
-```
-$ bunzip2 ostechnix.txt.bz2
-
-```
-
-To view the contents of a compressed file without decompressing it:
-```
-$ bunzip2 -c ostechnix.txt.bz2
-
-```
-
-Or,
-```
-$ bzcat ostechnix.txt.bz2
-
-```
-
-For more details, refer man pages.
-```
-$ man bzip2
-
-```
-
-##### Summary
-
-In this tutorial, we learned what is gzip and bzip2 programs and how to use them to compress and decompress files with some examples in GNU/Linux. In this next, guide we are going to learn how to archive files and directories in Linux.
-
-Cheers!
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/how-to-compress-and-decompress-files-in-linux/
-
-作者:[SK][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-选题:[lujun9972](https://github.com/lujun9972)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://www.ostechnix.com/author/sk/
diff --git a/sources/tech/20180326 Start a blog in 30 minutes with Hugo, a static site generator written in Go.md b/sources/tech/20180326 Start a blog in 30 minutes with Hugo, a static site generator written in Go.md
deleted file mode 100644
index 465941491c..0000000000
--- a/sources/tech/20180326 Start a blog in 30 minutes with Hugo, a static site generator written in Go.md
+++ /dev/null
@@ -1,191 +0,0 @@
-Start a blog in 30 minutes with Hugo, a static site generator written in Go
-======
-
-
-Do you want to start a blog to share your latest adventures with various software frameworks? Do you love a project that is poorly documented and want to fix that? Or do you just want to create a personal website?
-
-Many people who want to start a blog have a significant caveat: lack of knowledge about a content management system (CMS) or time to learn. Well, what if I said you don't need to spend days learning a new CMS, setting up a basic website, styling it, and hardening it against attackers? What if I said you could create a blog in 30 minutes, start to finish, with [Hugo][1]?
-
-
-
-Hugo is a static site generator written in Go. Why use Hugo, you ask?
-
- * Because there is no database, no plugins requiring any permissions, and no underlying platform running on your server, there's no added security concern.
- * The blog is a set of static websites, which means lightning-fast serve time. Additionally, all pages are rendered at deploy time, so your server's load is minimal.
- * Version control is easy. Some CMS platforms use their own version control system (VCS) or integrate Git into their interface. With Hugo, all your source files can live natively on the VCS of your choice.
-
-
-
-### Minutes 0-5: Download Hugo and generate a site
-
-To put it bluntly, Hugo is here to make writing a website fun again. Let's time the 30 minutes, shall we?
-
-To simplify the installation of Hugo, download the binary file. To do so:
-
- 1. Download the appropriate [archive][2] for your operating system.
-
- 2. Unzip the archive into a directory of your choice, for example `C:\hugo_dir` or `~/hugo_dir`; this path will be referred to as `${HUGO_HOME}`.
-
- 3. Open the command line and change into your directory: `cd ${HUGO_HOME}`.
-
- 4. Verify that Hugo is working:
-
- * On Unix: `${HUGO_HOME}/[hugo version]`
- * On Windows: `${HUGO_HOME}\[hugo.exe version]`
-For example, `c:\hugo_dir\hugo version`.
-
-For simplicity, I'll refer to the path to the Hugo binary (including the binary) as `hugo`. For example, `hugo version` would translate to `C:\hugo_dir\hugo version` on your computer.
-
-If you get an error message, you may have downloaded the wrong version. Also note there are many possible ways to install Hugo. See the [official documentation][3] for more information. Ideally, you put the Hugo binary on PATH. For this quick start, it's fine to use the full path of the Hugo binary.
-
-
-
- 5. Create a new site that will become your blog: `hugo new site awesome-blog`.
- 6. Change into the newly created directory: `cd awesome-blog`.
-
-
-
-Congratulations! You have just created your new blog.
-
-### Minutes 5-10: Theme your blog
-
-With Hugo, you can either theme your blog yourself or use one of the beautiful, ready-made [themes][4]. I chose [Kiera][5] because it is deliciously simple. To install the theme:
-
- 1. Change into the themes directory: `cd themes`.
- 2. Clone your theme: `git clone https://github.com/avianto/hugo-kiera kiera`. If you do not have Git installed:
- * Download the .zip file from [GitHub][5].
- * Unzip it to your site's `themes` directory.
- * Rename the directory from `hugo-kiera-master` to `kiera`.
- 3. Change the directory to the awesome-blog level: `cd awesome-blog`.
- 4. Activate the theme. Themes (including Kiera) often come with a directory called `exampleSite`, which contains example content and an example settings file. To activate Kiera, copy the provided `config.toml` file to your blog:
- * On Unix: `cp themes/kiera/exampleSite/config.toml .`
- * On Windows: `copy themes\kiera\exampleSite\config.toml .`
- * Confirm `Yes` to override the old `config.toml`
- 5. (Optional) You can start your server to visually verify the theme is activated: `hugo server -D` and access `http://localhost:1313` in your web browser. Once you've reviewed your blog, you can turn off the server by pressing `Ctrl+C` in the command line. Your blog is empty, but we're getting someplace. It should look something like this:
-
-
-
-You have just themed your blog! You can find hundreds of beautiful themes on the official [Hugo themes][4] site.
-
-### Minutes 10-20: Add content to your blog
-
-Whereas a bowl is most useful when it is empty, this is not the case for a blog. In this step, you'll add content to your blog. Hugo and the Kiera theme simplify this process. To add your first post:
-
- 1. Article archetypes are templates for your content.
- 2. Add theme archetypes to your blog site:
- * On Unix: `cp themes/kiera/archetypes/* archetypes/`
- * On Windows: `copy themes\kiera\archetypes\* archetypes\`
- * Confirm `Yes` to override the `default.md` archetype
- 3. Create a new directory for your blog posts:
- * On Unix: `mkdir content/posts`
- * On Windows: `mkdir content\posts`
- 4. Use Hugo to generate your post:
- * On Unix: `hugo new posts/first-post.md`
- * On Windows: `hugo new posts\first-post.md`
- 5. Open the new post in a text editor of your choice:
- * On Unix: `gedit content/posts/first-post.md`
- * On Windows: `notepad content\posts\first-post.md`
-
-
-
-At this point, you can go wild. Notice that your post consists of two sections. The first one is separated by `+++`. It contains metadata about your post, such as its title. In Hugo, this is called front matter. After the front matter, the article begins. Create the first post:
-```
-+++
-
-title = "First Post"
-
-date = 2018-03-03T13:23:10+01:00
-
-draft = false
-
-tags = ["Getting started"]
-
-categories = []
-
-+++
-
-
-
-Hello Hugo world! No more excuses for having no blog or documentation now!
-
-```
-
-All you need to do now is start the server: `hugo server -D`. Open your browser and enter: `http://localhost:1313/`.
-
-
-### Minutes 20-30: Tweak your site
-
-What we've done is great, but there are still a few niggles to iron out. For example, naming your site is simple:
-
- 1. Stop your server by pressing `Ctrl+C` on the command line.
- 2. Open `config.toml` and edit settings such as the blog's title, copyright, name, your social network links, etc.
-
-
-
-When you start your server again, you'll see your blog has a bit more personalization. One more basic thing is missing: menus. That's a quick fix as well. Back in `config.toml`, insert the following at the bottom:
-```
-[[menu.main]]
-
- name = "Home" #Name in the navigation bar
-
- weight = 10 #The larger the weight, the more on the right this item will be
-
- url = "/" #URL address
-
-[[menu.main]]
-
- name = "Posts"
-
- weight = 20
-
- url = "/posts/"
-
-```
-
-This adds menus for Home and Posts. You still need an About page. Instead of referencing it from the `config.toml` file, reference it from a markdown file:
-
- 1. Create an About file: `hugo new about.md`. Notice that it's `about.md`, not `posts/about.md`. The About page is not a blog post, so you don't want it displayed in the Posts section.
- 2. Open the file in a text editor and enter the following:
-
-
-```
-+++
-
-title = "About"
-
-date = 2018-03-03T13:50:49+01:00
-
-menu = "main" #Display this page on the nav menu
-
-weight = "30" #Right-most nav item
-
-meta = "false" #Do not display tags or categories
-
-+++
-
-
-
-> Waves are the practice of the water. Shunryu Suzuki
-
-```
-
-When you start your Hugo server and open `http://localhost:1313/`, you should see your new blog ready to be used. (Check out [my example][6] on my GitHub page.) If you'd like to change the active style of menu items to make the padding slightly nicer (like the GitHub live version), apply [this patch][7] to your `themes/kiera/static/css/styles.css` file.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/3/start-blog-30-minutes-hugo
-
-作者:[Marek Czernek][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/mczernek
-[1]:https://gohugo.io/
-[2]:https://github.com/gohugoio/hugo/releases
-[3]:https://gohugo.io/getting-started/installing/
-[4]:https://themes.gohugo.io/
-[5]:https://github.com/avianto/hugo-kiera
-[6]:https://m-czernek.github.io/awesome-blog/
-[7]:https://github.com/avianto/hugo-kiera/pull/18/files
diff --git a/sources/tech/20180403 3 pitfalls everyone should avoid with hybrid multicloud.md b/sources/tech/20180403 3 pitfalls everyone should avoid with hybrid multicloud.md
new file mode 100644
index 0000000000..b128be62f0
--- /dev/null
+++ b/sources/tech/20180403 3 pitfalls everyone should avoid with hybrid multicloud.md
@@ -0,0 +1,87 @@
+3 pitfalls everyone should avoid with hybrid multicloud
+======
+
+
+This article was co-written with [Roel Hodzelmans][1].
+
+We're all told the cloud is the way to ensure a digital future for our businesses. But which cloud? From cloud to hybrid cloud to hybrid multi-cloud, you need to make choices, and these choices don't preclude the daily work of enhancing your customers' experience or agile delivery of the applications they need.
+
+This article is the first in a four-part series on avoiding pitfalls in hybrid multi-cloud computing. Let's start by examining multi-cloud, hybrid cloud, and hybrid multi-cloud and what makes them different from one another.
+
+### Hybrid vs. multi-cloud
+
+There are many conversations you may be having in your business around moving to the cloud. For example, you may want to take your on-premises computing capacity and turn it into your own private cloud. You may wish to provide developers with a cloud-like experience using the same resources you already have. A more traditional reason for expansion is to use external computing resources to augment those in your own data centers. The latter leads you to the various public cloud providers, as well as to our first definition, multi-cloud.
+
+#### Multi-cloud
+
+Multi-cloud means using multiple clouds from multiple providers for multiple tasks.
+
+![Multi-cloud][3]
+
+Figure 1. Multi-cloud IT with multiple isolated cloud environments
+
+Typically, multi-cloud refers to the use of several different public clouds in order to achieve greater flexibility, lower costs, avoid vendor lock-in, or use specific regional cloud providers.
+
+A challenge of the multi-cloud approach is achieving consistent policies, compliance, and management with different providers involved.
+
+Multi-cloud is mainly a strategy to expand your business while leveraging multi-vendor cloud solutions and spreading the risk of lock-in. Figure 1 shows the isolated nature of cloud services in this model, without any sort of coordination between the services and business applications. Each is managed separately, and applications are isolated to services found in their environments.
+
+#### Hybrid cloud
+
+Hybrid cloud solves issues where isolation and coordination are central to the solution. It is a combination of one or more public and private clouds with at least a degree of workload portability, integration, orchestration, and unified management.
+
+![Hybrid cloud][5]
+
+Figure 2. Hybrid clouds may be on or off premises, but must have a degree of interoperability
+
+The key issue here is that there is an element of interoperability, migration potential, and a connection between tasks running in public clouds and on-premises infrastructure, even if it's not always seamless or otherwise fully implemented.
+
+If your cloud model is missing portability, integration, orchestration, and management, then it's just a bunch of clouds, not a hybrid cloud.
+
+The cloud environments in Fig. 2 include at least one private and public cloud. They can be off or on premises, but they have some degree of the following:
+
+ * Interoperability
+ * Application portability
+ * Data portability
+ * Common management
+
+
+
+As you can probably guess, combining multi-cloud and hybrid cloud results in a hybrid multi-cloud. But what does that look like?
+
+### Hybrid multi-cloud
+
+Hybrid multi-cloud pulls together multiple clouds and provides the tools to ensure interoperability between the various services in hybrid and multi-cloud solutions.
+
+![Hybrid multi-cloud][7]
+
+Figure 3. Hybrid multi-cloud solutions using open technologies
+
+Bringing these together can be a serious challenge, but the result ensures better use of resources without isolation in their respective clouds.
+
+Fig. 3 shows an example of hybrid multi-cloud based on open technologies for interoperability, workload portability, and management.
+
+### Moving forward: Pitfalls of hybrid multi-cloud
+
+In part two of this series, we'll look at the first of three pitfalls to avoid with hybrid multi-cloud. Namely, why cost is not always the obvious motivator when determining how to transition your business to the cloud.
+
+This article is based on "[3 pitfalls everyone should avoid with hybrid multi-cloud][8]," a talk the authors will be giving at [Red Hat Summit 2018][9], which will be held May 8-10 in San Francisco. [Register by May 7][9] to save US$ 500 off of registration. Use discount code **OPEN18** on the payment page to apply the discount.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/4/pitfalls-hybrid-multi-cloud
+
+作者:[Eric D.Schabell][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/eschabell
+[1]:https://opensource.com/users/roelh
+[3]:https://opensource.com/sites/default/files/u128651/multi-cloud.png (Multi-cloud)
+[5]:https://opensource.com/sites/default/files/u128651/hybrid-cloud.png (Hybrid cloud)
+[7]:https://opensource.com/sites/default/files/u128651/hybrid-multicloud.png (Hybrid multi-cloud)
+[8]:https://agenda.summit.redhat.com/SessionDetail.aspx?id=153892
+[9]:https://www.redhat.com/en/summit/2018
diff --git a/sources/tech/20180424 A gentle introduction to FreeDOS.md b/sources/tech/20180424 A gentle introduction to FreeDOS.md
deleted file mode 100644
index ba43d23eb7..0000000000
--- a/sources/tech/20180424 A gentle introduction to FreeDOS.md
+++ /dev/null
@@ -1,110 +0,0 @@
-A gentle introduction to FreeDOS
-======
-
-
-
-FreeDOS is an old operating system, but it is new to many people. In 1994, several developers and I came together to [create FreeDOS][1]—a complete, free, DOS-compatible operating system you can use to play classic DOS games, run legacy business software, or develop embedded systems. Any program that works on MS-DOS should also run on FreeDOS.
-
-In 1994, FreeDOS was immediately familiar to anyone who had used Microsoft's proprietary MS-DOS. And that was by design; FreeDOS intended to mimic MS-DOS as much as possible. As a result, DOS users in the 1990s were able to jump right into FreeDOS. But times have changed. Today, open source developers are more familiar with the Linux command line or they may prefer a graphical desktop like [GNOME][2], making the FreeDOS command line seem alien at first.
-
-New users often ask, "I [installed FreeDOS][3], but how do I use it?" If you haven't used DOS before, the blinking `C:\>` DOS prompt can seem a little unfriendly. And maybe scary. This gentle introduction to FreeDOS should get you started. It offers just the basics: how to get around and how to look at files. If you want to learn more than what's offered here, visit the [FreeDOS wiki][4].
-
-### The DOS prompt
-
-First, let's look at the empty prompt and what it means.
-
-
-
-DOS is a "disk operating system" created when personal computers ran from floppy disks. Even when computers supported hard drives, it was common in the 1980s and 1990s to switch frequently between the different drives. For example, you might make a backup copy of your most important files to a floppy disk.
-
-DOS referenced each drive by a letter. Early PCs could have only two floppy drives, which were assigned as the `A:` and `B:` drives. The first partition on the first hard drive was the `C:` drive, and so on for other drives. The `C:` in the prompt means you are using the first partition on the first hard drive.
-
-Starting with PC-DOS 2.0 in 1983, DOS also supported directories and subdirectories, much like the directories and subdirectories on Linux filesystems. But unlike Linux, DOS directory names are delimited by `\` instead of `/`. Putting that together with the drive letter, the `C:\` in the prompt means you are in the top, or "root," directory of the `C:` drive.
-
-The `>` is the literal prompt where you type your DOS commands, like the `$` prompt on many Linux shells. The part before the `>` tells you the current working directory, and you type commands at the `>` prompt.
-
-### Finding your way around in DOS
-
-The basics of navigating through directories in DOS are very similar to the steps you'd use on the Linux command line. You need to remember only a few commands.
-
-#### Displaying a directory
-
-When you want to see the contents of the current directory, use the `DIR` command. Since DOS commands are not case-sensitive, you could also type `dir`. By default, DOS displays the details of every file and subdirectory, including the name, extension, size, and last modified date and time.
-
-
-
-If you don't want the extra details about individual file sizes, you can display a "wide" directory by using the `/w` option with the `DIR` command. Note that Linux uses the hyphen (`-`) or double-hyphen (`--`) to start command-line options, but DOS uses the slash character (`/`).
-
-
-
-You can look inside a specific subdirectory by passing the pathname as a parameter to `DIR`. Again, another difference from Linux is that Linux files and directories are case-sensitive, but DOS names are case-insensitive. DOS will usually display files and directories in all uppercase, but you can equally reference them in lowercase.
-
-
-
-
-#### Changing the working directory
-
-Once you can see the contents of a directory, you can "move into" any other directory. On DOS, you change your working directory with the `CHDIR` command, also abbreviated as `CD`. You can change into a subdirectory with a command like `CD CHOICE` or into a new path with `CD \FDOS\DOC\CHOICE`.
-
-
-
-Just like on the Linux command line, DOS uses `.` to represent the current directory, and `..` for the parent directory (one level "up" from the current directory). You can combine these. For example, `CD ..` changes to the parent directory, and `CD ..\..` moves you two levels "up" from the current directory.
-
-
-
-FreeDOS also borrows a feature from Linux: You can use `CD -` to jump back to your previous working directory. That is handy after you change into a new path to do one thing and want to go back to your previous work.
-
-#### Changing the working drive
-
-Under Linux, the concept of a "drive" is hidden. In Linux and other Unix systems, you "mount" a drive to a directory path, such as `/backup`, or the system does it for you automatically, such as `/var/run/media/user/flashdrive`. But DOS is a much simpler system. With DOS, you must change the working drive by yourself.
-
-Remember that DOS assigns the first partition on the first hard drive as the `C:` drive, and so on for other drive letters. On modern systems, people rarely divide a hard drive with multiple DOS partitions; they simply use the whole disk—or as much of it as they can assign to DOS. Today, `C:` is usually the first hard drive, and `D:` is usually another hard drive or the CD-ROM drive. Other network drives can be mapped to other letters, such as `E:` or `Z:` or however you want to organize them.
-
-Changing drives is easy under DOS. Just type the drive letter followed by a colon (`:`) on the command line, and DOS will change to that working drive. For example, on my [QEMU][5] system, I set my `D:` drive to a shared directory in my Linux home directory, where I keep installers for various DOS applications and games I want to test.
-
-
-
-Be careful that you don't try to change to a drive that doesn't exist. DOS may set the working drive, but if you try to do anything there you'll get the somewhat infamous "Abort, Retry, Fail" DOS error message.
-
-
-
-### Other things to try
-
-With the `CD` and `DIR` commands, you have the basics of DOS navigation. These commands allow you to find your way around DOS directories and see what other subdirectories and files exist. Once you are comfortable with basic navigation, you might also try these other basic DOS commands:
-
- * `MKDIR` or `MD` to create new directories
- * `RMDIR` or `RD` to remove directories
- * `TREE` to view a list of directories and subdirectories in a tree-like format
- * `TYPE` and `MORE` to display file contents
- * `RENAME` or `REN` to rename files
- * `DEL` or `ERASE` to delete files
- * `EDIT` to edit files
- * `CLS` to clear the screen
-
-
-
-If those aren't enough, you can find a list of [all DOS commands][6] on the FreeDOS wiki.
-
-In FreeDOS, you can use the `/?` parameter to get brief instructions to use each command. For example, `EDIT /?` will show you the usage and options for the editor. Or you can type `HELP` to use an interactive help system.
-
-Like any DOS, FreeDOS is meant to be a simple operating system. The DOS filesystem is pretty simple to navigate with only a few basic commands. So fire up a QEMU session, install FreeDOS, and experiment with the DOS command line. Maybe now it won't seem so scary.
-
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/4/gentle-introduction-freedos
-
-作者:[Jim Hall][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/jim-hall
-[1]:https://opensource.com/article/17/10/freedos
-[2]:https://opensource.com/article/17/8/gnome-20-anniversary
-[3]:http://www.freedos.org/
-[4]:http://wiki.freedos.org/
-[5]:https://www.qemu.org/
-[6]:http://wiki.freedos.org/wiki/index.php/Dos_commands
diff --git a/sources/tech/20180425 A gentle introduction to FreeDOS - Opensource.com.md b/sources/tech/20180425 A gentle introduction to FreeDOS - Opensource.com.md
deleted file mode 100644
index d68334db33..0000000000
--- a/sources/tech/20180425 A gentle introduction to FreeDOS - Opensource.com.md
+++ /dev/null
@@ -1,141 +0,0 @@
-# A gentle introduction to FreeDOS
-
-
-
-Image credits :
-
-Jim Hall, CC BY
-
-## Get the newsletter
-
-Join the 85,000 open source advocates who receive our giveaway alerts and article roundups.
-
-FreeDOS is an old operating system, but it is new to many people. In 1994, several developers and I came together to [create FreeDOS][1]—a complete, free, DOS-compatible operating system you can use to play classic DOS games, run legacy business software, or develop embedded systems. Any program that works on MS-DOS should also run on FreeDOS.
-
-In 1994, FreeDOS was immediately familiar to anyone who had used Microsoft's proprietary MS-DOS. And that was by design; FreeDOS intended to mimic MS-DOS as much as possible. As a result, DOS users in the 1990s were able to jump right into FreeDOS. But times have changed. Today, open source developers are more familiar with the Linux command line or they may prefer a graphical desktop like [GNOME][2], making the FreeDOS command line seem alien at first.
-
-New users often ask, "I [installed FreeDOS][3], but how do I use it?" If you haven't used DOS before, the blinking C:\> DOS prompt can seem a little unfriendly. And maybe scary. This gentle introduction to FreeDOS should get you started. It offers just the basics: how to get around and how to look at files. If you want to learn more than what's offered here, visit the [FreeDOS wiki][4].
-
-## The DOS prompt
-
-First, let's look at the empty prompt and what it means.
-
-
-
-DOS is a "disk operating system" created when personal computers ran from floppy disks. Even when computers supported hard drives, it was common in the 1980s and 1990s to switch frequently between the different drives. For example, you might make a backup copy of your most important files to a floppy disk.
-
-DOS referenced each drive by a letter. Early PCs could have only two floppy drives, which were assigned as the A: and B: drives. The first partition on the first hard drive was the C: drive, and so on for other drives. The C: in the prompt means you are using the first partition on the first hard drive.
-
-Starting with PC-DOS 2.0 in 1983, DOS also supported directories and subdirectories, much like the directories and subdirectories on Linux filesystems. But unlike Linux, DOS directory names are delimited by \ instead of /. Putting that together with the drive letter, the C:\ in the prompt means you are in the top, or "root," directory of the C: drive.
-
-The > is the literal prompt where you type your DOS commands, like the $ prompt on many Linux shells. The part before the > tells you the current working directory, and you type commands at the > prompt.
-
-## Finding your way around in DOS
-
-The basics of navigating through directories in DOS are very similar to the steps you'd use on the Linux command line. You need to remember only a few commands.
-
-### Displaying a directory
-
-When you want to see the contents of the current directory, use the DIR command. Since DOS commands are not case-sensitive, you could also type dir. By default, DOS displays the details of every file and subdirectory, including the name, extension, size, and last modified date and time.
-
-
-
-If you don't want the extra details about individual file sizes, you can display a "wide" directory by using the /w option with the DIR command. Note that Linux uses the hyphen (-) or double-hyphen (--) to start command-line options, but DOS uses the slash character (/).
-
-
-
-You can look inside a specific subdirectory by passing the pathname as a parameter to DIR. Again, another difference from Linux is that Linux files and directories are case-sensitive, but DOS names are case-insensitive. DOS will usually display files and directories in all uppercase, but you can equally reference them in lowercase.
-
-
-
-### Changing the working directory
-
-Once you can see the contents of a directory, you can "move into" any other directory. On DOS, you change your working directory with the CHDIR command, also abbreviated as CD. You can change into a subdirectory with a command like CD CHOICE or into a new path with CD \FDOS\DOC\CHOICE.
-
-
-
-Just like on the Linux command line, DOS uses . to represent the current directory, and .. for the parent directory (one level "up" from the current directory). You can combine these. For example, CD .. changes to the parent directory, and CD ..\.. moves you two levels "up" from the current directory.
-
-FreeDOS also borrows a feature from Linux: You can use CD - to jump back to your previous working directory. That is handy after you change into a new path to do one thing and want to go back to your previous work.
-
-
-
-### Changing the working drive
-
-Under Linux, the concept of a "drive" is hidden. In Linux and other Unix systems, you "mount" a drive to a directory path, such as /backup, or the system does it for you automatically, such as /var/run/media/user/flashdrive. But DOS is a much simpler system. With DOS, you must change the working drive by yourself.
-
-Remember that DOS assigns the first partition on the first hard drive as the C: drive, and so on for other drive letters. On modern systems, people rarely divide a hard drive with multiple DOS partitions; they simply use the whole disk—or as much of it as they can assign to DOS. Today, C: is usually the first hard drive, and D: is usually another hard drive or the CD-ROM drive. Other network drives can be mapped to other letters, such as E: or Z: or however you want to organize them.
-
-Changing drives is easy under DOS. Just type the drive letter followed by a colon (:) on the command line, and DOS will change to that working drive. For example, on my [QEMU][5] system, I set my D: drive to a shared directory in my Linux home directory, where I keep installers for various DOS applications and games I want to test.
-
-
-
-Be careful that you don't try to change to a drive that doesn't exist. DOS may set the working drive, but if you try to do anything there you'll get the somewhat infamous "Abort, Retry, Fail" DOS error message.
-
-
-
-## Other things to try
-
-With the CD and DIR commands, you have the basics of DOS navigation. These commands allow you to find your way around DOS directories and see what other subdirectories and files exist. Once you are comfortable with basic navigation, you might also try these other basic DOS commands:
-
-* MKDIR or MD to create new directories
-* RMDIR or RD to remove directories
-* TREE to view a list of directories and subdirectories in a tree-like format
-* TYPE and MORE to display file contents
-* RENAME or REN to rename files
-* DEL or ERASE to delete files
-* EDIT to edit files
-* CLS to clear the screen
-
-If those aren't enough, you can find a list of [all DOS commands][6] on the FreeDOS wiki.
-
-In FreeDOS, you can use the /? parameter to get brief instructions to use each command. For example, EDIT /? will show you the usage and options for the editor. Or you can type HELP to use an interactive help system.
-
-Like any DOS, FreeDOS is meant to be a simple operating system. The DOS filesystem is pretty simple to navigate with only a few basic commands. So fire up a QEMU session, install FreeDOS, and experiment with the DOS command line. Maybe now it won't seem so scary.
-
-## Related stories:
-
-* [How to install FreeDOS in QEMU][7]
-* [How to install FreeDOS on Raspberry Pi][8]
-* [The origin and evolution of FreeDOS][9]
-* [Four cool facts about FreeDOS][10]
-
-## About the author
-
-[][11]
-
-Jim Hall \- Jim Hall is an open source software developer and advocate, probably best known as the founder and project coordinator for FreeDOS. Jim is also very active in the usability of open source software, as a mentor for usability testing in GNOME Outreachy, and as an occasional adjunct professor teaching a course on the Usability of Open Source Software. From 2016 to 2017, Jim served as a director on the GNOME Foundation Board of Directors. At work, Jim is Chief Information Officer in local... [more about Jim Hall][12]
-
-[More about me][13]
-
-* [Learn how you can contribute][14]
-
----
-
-via: [https://opensource.com/article/18/4/gentle-introduction-freedos][15]
-
-作者: [undefined][16] 选题者: [@lujun9972][17] 译者: [译者ID][18] 校对: [校对者ID][19]
-
-本文由 [LCTT][20] 原创编译,[Linux中国][21] 荣誉推出
-
-[1]: https://opensource.com/article/17/10/freedos
-[2]: https://opensource.com/article/17/8/gnome-20-anniversary
-[3]: http://www.freedos.org/
-[4]: http://wiki.freedos.org/
-[5]: https://www.qemu.org/
-[6]: http://wiki.freedos.org/wiki/index.php/Dos_commands
-[7]: https://opensource.com/article/17/10/run-dos-applications-linux
-[8]: https://opensource.com/article/18/3/can-you-run-dos-raspberry-pi
-[9]: https://opensource.com/article/17/10/freedos
-[10]: https://opensource.com/article/17/6/freedos-still-cool-today
-[11]: https://opensource.com/users/jim-hall
-[12]: https://opensource.com/users/jim-hall
-[13]: https://opensource.com/users/jim-hall
-[14]: https://opensource.com/participate
-[15]: https://opensource.com/article/18/4/gentle-introduction-freedos
-[16]: undefined
-[17]: https://github.com/lujun9972
-[18]: https://github.com/译者ID
-[19]: https://github.com/校对者ID
-[20]: https://github.com/LCTT/TranslateProject
-[21]: https://linux.cn/
diff --git a/sources/tech/20180425 Understanding metrics and monitoring with Python - Opensource.com.md b/sources/tech/20180425 Understanding metrics and monitoring with Python - Opensource.com.md
deleted file mode 100644
index f181016aba..0000000000
--- a/sources/tech/20180425 Understanding metrics and monitoring with Python - Opensource.com.md
+++ /dev/null
@@ -1,488 +0,0 @@
-# Understanding metrics and monitoring with Python
-
-
-
-Image by :
-
-opensource.com
-
-## Get the newsletter
-
-Join the 85,000 open source advocates who receive our giveaway alerts and article roundups.
-
-My reaction when I first came across the terms counter and gauge and the graphs with colors and numbers labeled "mean" and "upper 90" was one of avoidance. It's like I saw them, but I didn't care because I didn't understand them or how they might be useful. Since my job didn't require me to pay attention to them, they remained ignored.
-
-That was about two years ago. As I progressed in my career, I wanted to understand more about our network applications, and that is when I started learning about metrics.
-
-The three stages of my journey to understanding monitoring (so far) are:
-
-* Stage 1: What? (Looks elsewhere)
-* Stage 2: Without metrics, we are really flying blind.
-* Stage 3: How do we keep from doing metrics wrong?
-
-I am currently in Stage 2 and will share what I have learned so far. I'm moving gradually toward Stage 3, and I will offer some of my resources on that part of the journey at the end of this article.
-
-Let's get started!
-
-## Software prerequisites
-
-More Python Resources
-
-* [What is Python?][1]
-* [Top Python IDEs][2]
-* [Top Python GUI frameworks][3]
-* [Latest Python content][4]
-* [More developer resources][5]
-
-All the demos discussed in this article are available on [my GitHub repo][6]. You will need to have docker and docker-compose installed to play with them.
-
-## Why should I monitor?
-
-The top reasons for monitoring are:
-
-* Understanding _normal_ and _abnormal_ system and service behavior
-* Doing capacity planning, scaling up or down
-* Assisting in performance troubleshooting
-* Understanding the effect of software/hardware changes
-* Changing system behavior in response to a measurement
-* Alerting when a system exhibits unexpected behavior
-
-## Metrics and metric types
-
-For our purposes, a **metric** is an _observed_ value of a certain quantity at a given point in _time_. The total of number hits on a blog post, the total number of people attending a talk, the number of times the data was not found in the caching system, the number of logged-in users on your website—all are examples of metrics.
-
-They broadly fall into three categories:
-
-### Counters
-
-Consider your personal blog. You just published a post and want to keep an eye on how many hits it gets over time, a number that can only increase. This is an example of a **counter** metric. Its value starts at 0 and increases during the lifetime of your blog post. Graphically, a counter looks like this:
-
-
-
-A counter metric always increases.
-
-### Gauges
-
-Instead of the total number of hits on your blog post over time, let's say you want to track the number of hits per day or per week. This metric is called a **gauge** and its value can go up or down. Graphically, a gauge looks like this:
-
-
-
-A gauge metric can increase or decrease.
-
-A gauge's value usually has a _ceiling_ and a _floor_ in a certain time window.
-
-### Histograms and timers
-
-A **histogram** (as Prometheus calls it) or a **timer** (as StatsD calls it) is a metric to track _sampled observations_. Unlike a counter or a gauge, the value of a histogram metric doesn't necessarily show an up or down pattern. I know that doesn't make a lot of sense and may not seem different from a gauge. What's different is what you expect to _do_ with histogram data compared to a gauge. Therefore, the monitoring system needs to know that a metric is a histogram type to allow you to do those things.
-
-
-
-A histogram metric can increase or decrease.
-
-## Demo 1: Calculating and reporting metrics
-
-[Demo 1][7] is a basic web application written using the [Flask][8] framework. It demonstrates how we can _calculate_ and _report_ metrics.
-
-The src directory has the application in app.py with the src/helpers/middleware.py containing the following:
-
-```
-from flask import request
-import csv
-import time
-
-
-def start_timer():
- request.start_time = time.time()
-
-
-def stop_timer(response):
- # convert this into milliseconds for statsd
- resp_time = (time.time() - request.start_time)*1000
- with open('metrics.csv', 'a', newline='') as f:
- csvwriter = csv.writer(f)
- csvwriter.writerow([str(int(time.time())), str(resp_time)])
-
- return response
-
-
-def setup_metrics(app):
- app.before_request(start_timer)
- app.after_request(stop_timer)
-```
-
-When setup_metrics() is called from the application, it configures the start_timer() function to be called before a request is processed and the stop_timer() function to be called after a request is processed but before the response has been sent. In the above function, we write the timestamp and the time it took (in milliseconds) for the request to be processed.
-
-When we run docker-compose up in the demo1 directory, it starts the web application, then a client container that makes a number of requests to the web application. You will see a src/metrics.csv file that has been created with two columns: timestamp and request_latency.
-
-Looking at this file, we can infer two things:
-
-* There is a lot of data that has been generated
-* No observation of the metric has any characteristic associated with it
-
-Without a characteristic associated with a metric observation, we cannot say which HTTP endpoint this metric was associated with or which node of the application this metric was generated from. Hence, we need to qualify each metric observation with the appropriate metadata.
-
-## Statistics 101
-
-If we think back to high school mathematics, there are a few statistics terms we should all recall, even if vaguely, including mean, median, percentile, and histogram. Let's briefly recap them without judging their usefulness, just like in high school.
-
-### Mean
-
-The **mean**, or the average of a list of numbers, is the sum of the numbers divided by the cardinality of the list. The mean of 3, 2, and 10 is (3+2+10)/3 = 5.
-
-### Median
-
-The **median** is another type of average, but it is calculated differently; it is the center numeral in a list of numbers ordered from smallest to largest (or vice versa). In our list above (2, 3, 10), the median is 3. The calculation is not very straightforward; it depends on the number of items in the list.
-
-### Percentile
-
-The **percentile** is a measure that gives us a measure below which a certain (k) percentage of the numbers lie. In some sense, it gives us an _idea_ of how this measure is doing relative to the k percentage of our data. For example, the 95th percentile score of the above list is 9.29999. The percentile measure varies from 0 to 100 (non-inclusive). The _zeroth_ percentile is the minimum score in a set of numbers. Some of you may recall that the median is the 50th percentile, which turns out to be 3.
-
-Some monitoring systems refer to the percentile measure as upper_X where _X_ is the percentile; _upper 90_ refers to the value at the 90th percentile.
-
-### Quantile
-
-The **q-Quantile** is a measure that ranks q_N_ in a set of _N_ numbers. The value of **q** ranges between 0 and 1 (both inclusive). When **q** is 0.5, the value is the median. The relationship between the quantile and percentile is that the measure at **q** quantile is equivalent to the measure at **100_q_** percentile.
-
-### Histogram
-
-The metric **histogram**, which we learned about earlier, is an _implementation detail_ of monitoring systems. In statistics, a histogram is a graph that groups data into _buckets_. Let's consider a different, contrived example: the ages of people reading your blog. If you got a handful of this data and wanted a rough idea of your readers' ages by group, plotting a histogram would show you a graph like this:
-
-
-
-### Cumulative histogram
-
-A **cumulative histogram** is a histogram where each bucket's count includes the count of the previous bucket, hence the name _cumulative_. A cumulative histogram for the above dataset would look like this:
-
-
-
-### Why do we need statistics?
-
-In Demo 1 above, we observed that there is a lot of data that is generated when we report metrics. We need statistics when working with metrics because there are just too many of them. We don't care about individual values, rather overall behavior. We expect the behavior the values exhibit is a proxy of the behavior of the system under observation.
-
-## Demo 2: Adding characteristics to metrics
-
-In our Demo 1 application above, when we calculate and report a request latency, it refers to a specific request uniquely identified by few _characteristics_. Some of these are:
-
-* The HTTP endpoint
-* The HTTP method
-* The identifier of the host/node where it's running
-
-If we attach these characteristics to a metric observation, we have more context around each metric. Let's explore adding characteristics to our metrics in [Demo 2][9].
-
-The src/helpers/middleware.py file now writes multiple columns to the CSV file when writing metrics:
-
-```
-node_ids = ['10.0.1.1', '10.1.3.4']
-
-
-def start_timer():
- request.start_time = time.time()
-
-
-def stop_timer(response):
- # convert this into milliseconds for statsd
- resp_time = (time.time() - request.start_time)*1000
- node_id = node_ids[random.choice(range(len(node_ids)))]
- with open('metrics.csv', 'a', newline='') as f:
- csvwriter = csv.writer(f)
- csvwriter.writerow([
- str(int(time.time())), 'webapp1', node_id,
- request.endpoint, request.method, str(response.status_code),
- str(resp_time)
- ])
-
- return response
-```
-
-Since this is a demo, I have taken the liberty of reporting random IPs as the node IDs when reporting the metric. When we run docker-compose up in the demo2 directory, it will result in a CSV file with multiple columns.
-
-### Analyzing metrics with pandas
-
-We'll now analyze this CSV file with [pandas][10]. Running docker-compose up will print a URL that we will use to open a [Jupyter][11] session. Once we upload the Analysis.ipynb notebook into the session, we can read the CSV file into a pandas DataFrame:
-
-```
-import pandas as pd
-metrics = pd.read_csv('/data/metrics.csv', index_col=0)
-```
-
-The index_col specifies that we want to use the timestamp as the index.
-
-Since each characteristic we add is a column in the DataFrame, we can perform grouping and aggregation based on these columns:
-
-```
-import numpy as np
-metrics.groupby(['node_id', 'http_status']).latency.aggregate(np.percentile, 99.999)
-```
-
-Please refer to the Jupyter notebook for more example analysis on the data.
-
-## What should I monitor?
-
-A software system has a number of variables whose values change during its lifetime. The software is running in some sort of an operating system, and operating system variables change as well. In my opinion, the more data you have, the better it is when something goes wrong.
-
-Key operating system metrics I recommend monitoring are:
-
-* CPU usage
-* System memory usage
-* File descriptor usage
-* Disk usage
-
-Other key metrics to monitor will vary depending on your software application.
-
-### Network applications
-
-If your software is a network application that listens to and serves client requests, the key metrics to measure are:
-
-* Number of requests coming in (counter)
-* Unhandled errors (counter)
-* Request latency (histogram/timer)
-* Queued time, if there is a queue in your application (histogram/timer)
-* Queue size, if there is a queue in your application (gauge)
-* Worker processes/threads usage (gauge)
-
-If your network application makes requests to other services in the context of fulfilling a client request, it should have metrics to record the behavior of communications with those services. Key metrics to monitor include number of requests, request latency, and response status.
-
-### HTTP web application backends
-
-HTTP applications should monitor all the above. In addition, they should keep granular data about the count of non-200 HTTP statuses grouped by all the other HTTP status codes. If your web application has user signup and login functionality, it should have metrics for those as well.
-
-### Long-running processes
-
-Long-running processes such as Rabbit MQ consumer or task-queue workers, although not network servers, work on the model of picking up a task and processing it. Hence, we should monitor the number of requests processed and the request latency for those processes.
-
-No matter the application type, each metric should have appropriate **metadata** associated with it.
-
-## Integrating monitoring in a Python application
-
-There are two components involved in integrating monitoring into Python applications:
-
-* Updating your application to calculate and report metrics
-* Setting up a monitoring infrastructure to house the application's metrics and allow queries to be made against them
-
-The basic idea of recording and reporting a metric is:
-
-```
-def work():
- requests += 1
- # report counter
- start_time = time.time()
-
- # < do the work >
-
- # calculate and report latency
- work_latency = time.time() - start_time
- ...
-```
-
-Considering the above pattern, we often take advantage of _decorators_, _context managers_, and _middleware_ (for network applications) to calculate and report metrics. In Demo 1 and Demo 2, we used decorators in a Flask application.
-
-### Pull and push models for metric reporting
-
-Essentially, there are two patterns for reporting metrics from a Python application. In the _pull_ model, the monitoring system "scrapes" the application at a predefined HTTP endpoint. In the _push_ model, the application sends the data to the monitoring system.
-
-
-
-An example of a monitoring system working in the _pull_ model is [Prometheus][12]. [StatsD][13] is an example of a monitoring system where the application _pushes_ the metrics to the system.
-
-### Integrating StatsD
-
-To integrate StatsD into a Python application, we would use the [StatsD Python client][14], then update our metric-reporting code to push data into StatsD using the appropriate library calls.
-
-First, we need to create a client instance:
-
-```
-statsd = statsd.StatsClient(host='statsd', port=8125, prefix='webapp1')
-```
-
-The prefix keyword argument will add the specified prefix to all the metrics reported via this client.
-
-Once we have the client, we can report a value for a timer using:
-
-```
-statsd.timing(key, resp_time)
-```
-
-To increment a counter:
-
-```
-statsd.incr(key)
-```
-
-To associate metadata with a metric, a key is defined as metadata1.metadata2.metric, where each metadataX is a field that allows aggregation and grouping.
-
-The demo application [StatsD][15] is a complete example of integrating a Python Flask application with statsd.
-
-### Integrating Prometheus
-
-To use the Prometheus monitoring system, we will use the [Promethius Python client][16]. We will first create objects of the appropriate metric class:
-
-```
-REQUEST_LATENCY = Histogram('request_latency_seconds', 'Request latency',
- ['app_name', 'endpoint']
-)
-```
-
-The third argument in the above statement is the labels associated with the metric. These labels are what defines the metadata associated with a single metric value.
-
-To record a specific metric observation:
-
-```
-REQUEST_LATENCY.labels('webapp', request.path).observe(resp_time)
-```
-
-The next step is to define an HTTP endpoint in our application that Prometheus can scrape. This is usually an endpoint called /metrics:
-
-```
-@app.route('/metrics')
-def metrics():
- return Response(prometheus_client.generate_latest(), mimetype=CONTENT_TYPE_LATEST)
-```
-
-The demo application [Prometheus][17] is a complete example of integrating a Python Flask application with prometheus.
-
-### Which is better: StatsD or Prometheus?
-
-The natural next question is: Should I use StatsD or Prometheus? I have written a few articles on this topic, and you may find them useful:
-
-* [Your options for monitoring multi-process Python applications with Prometheus][18]
-* [Monitoring your synchronous Python web applications using Prometheus][19]
-* [Monitoring your asynchronous Python web applications using Prometheus][20]
-
-## Ways to use metrics
-
-We've learned a bit about why we want to set up monitoring in our applications, but now let's look deeper into two of them: alerting and autoscaling.
-
-### Using metrics for alerting
-
-A key use of metrics is creating alerts. For example, you may want to send an email or pager notification to relevant people if the number of HTTP 500s over the past five minutes increases. What we use for setting up alerts depends on our monitoring setup. For Prometheus we can use [Alertmanager][21] and for StatsD, we use [Nagios][22].
-
-### Using metrics for autoscaling
-
-Not only can metrics allow us to understand if our current infrastructure is over- or under-provisioned, they can also help implement autoscaling policies in a cloud infrastructure. For example, if worker process usage on our servers routinely hits 90% over the past five minutes, we may need to horizontally scale. How we would implement scaling depends on the cloud infrastructure. AWS Auto Scaling, by default, allows scaling policies based on system CPU usage, network traffic, and other factors. However, to use application metrics for scaling up or down, we must publish [custom CloudWatch metrics][23].
-
-## Application monitoring in a multi-service architecture
-
-When we go beyond a single application architecture, such that a client request can trigger calls to multiple services before a response is sent back, we need more from our metrics. We need a unified view of latency metrics so we can see how much time each service took to respond to the request. This is enabled with [distributed tracing][24].
-
-You can see an example of distributed tracing in Python in my blog post [Introducing distributed tracing in your Python application via Zipkin][25].
-
-## Points to remember
-
-In summary, make sure to keep the following things in mind:
-
-* Understand what a metric type means in your monitoring system
-* Know in what unit of measurement the monitoring system wants your data
-* Monitor the most critical components of your application
-* Monitor the behavior of your application in its most critical stages
-
-The above assumes you don't have to manage your monitoring systems. If that's part of your job, you have a lot more to think about!
-
-## Other resources
-
-Following are some of the resources I found very useful along my monitoring education journey:
-
-### General
-
-* [Monitoring distributed systems][26]
-* [Observability and monitoring best practices][27]
-* [Who wants seconds?][28]
-
-### StatsD/Graphite
-
-* [StatsD metric types][29]
-
-### Prometheus
-
-* [Prometheus metric types][30]
-* [How does a Prometheus gauge work?][31]
-* [Why are Prometheus histograms cumulative?][32]
-* [Monitoring batch jobs in Python][33]
-* [Prometheus: Monitoring at SoundCloud][34]
-
-## Avoiding mistakes (i.e., Stage 3 learnings)
-
-As we learn the basics of monitoring, it's important to keep an eye on the mistakes we don't want to make. Here are some insightful resources I have come across:
-
-* [How not to measure latency][35]
-* [Histograms with Prometheus: A tale of woe][36]
-* [Why averages suck and percentiles are great][37]
-* [Everything you know about latency is wrong][38]
-* [Who moved my 99th percentile latency?][39]
-* [Logs and metrics and graphs][40]
-* [HdrHistogram: A better latency capture method][41]
-
----
-
-To learn more, attend Amit Saha's talk, [Counter, gauge, upper 90—Oh my!][42], at [PyCon Cleveland 2018][43].
-
-## About the author
-
-[][44]
-
-Amit Saha \- I am a software engineer interested in infrastructure, monitoring and tooling. I am the author of "Doing Math with Python" and creator and the maintainer of Fedora Scientific Spin.
-
-[More about me][45]
-
-* [Learn how you can contribute][46]
-
----
-
-via: [https://opensource.com/article/18/4/metrics-monitoring-and-python][47]
-
-作者: [Amit Saha][48] 选题者: [@lujun9972][49] 译者: [译者ID][50] 校对: [校对者ID][51]
-
-本文由 [LCTT][52] 原创编译,[Linux中国][53] 荣誉推出
-
-[1]: https://opensource.com/resources/python?intcmp=7016000000127cYAAQ
-[2]: https://opensource.com/resources/python/ides?intcmp=7016000000127cYAAQ
-[3]: https://opensource.com/resources/python/gui-frameworks?intcmp=7016000000127cYAAQ
-[4]: https://opensource.com/tags/python?intcmp=7016000000127cYAAQ
-[5]: https://developers.redhat.com/?intcmp=7016000000127cYAAQ
-[6]: https://github.com/amitsaha/python-monitoring-talk
-[7]: https://github.com/amitsaha/python-monitoring-talk/tree/master/demo1
-[8]: http://flask.pocoo.org/
-[9]: https://github.com/amitsaha/python-monitoring-talk/tree/master/demo2
-[10]: https://pandas.pydata.org/
-[11]: http://jupyter.org/
-[12]: https://prometheus.io/
-[13]: https://github.com/etsy/statsd
-[14]: https://pypi.python.org/pypi/statsd
-[15]: https://github.com/amitsaha/python-monitoring-talk/tree/master/statsd
-[16]: https://pypi.python.org/pypi/prometheus_client
-[17]: https://github.com/amitsaha/python-monitoring-talk/tree/master/prometheus
-[18]: http://echorand.me/your-options-for-monitoring-multi-process-python-applications-with-prometheus.html
-[19]: https://blog.codeship.com/monitoring-your-synchronous-python-web-applications-using-prometheus/
-[20]: https://blog.codeship.com/monitoring-your-asynchronous-python-web-applications-using-prometheus/
-[21]: https://github.com/prometheus/alertmanager
-[22]: https://www.nagios.org/about/overview/
-[23]: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html
-[24]: http://opentracing.io/documentation/
-[25]: http://echorand.me/introducing-distributed-tracing-in-your-python-application-via-zipkin.html
-[26]: https://landing.google.com/sre/book/chapters/monitoring-distributed-systems.html
-[27]: http://www.integralist.co.uk/posts/monitoring-best-practices/?imm_mid=0fbebf&cmp=em-webops-na-na-newsltr_20180309
-[28]: https://www.robustperception.io/who-wants-seconds/
-[29]: https://github.com/etsy/statsd/blob/master/docs/metric_types.md
-[30]: https://prometheus.io/docs/concepts/metric_types/
-[31]: https://www.robustperception.io/how-does-a-prometheus-gauge-work/
-[32]: https://www.robustperception.io/why-are-prometheus-histograms-cumulative/
-[33]: https://www.robustperception.io/monitoring-batch-jobs-in-python/
-[34]: https://developers.soundcloud.com/blog/prometheus-monitoring-at-soundcloud
-[35]: https://www.youtube.com/watch?v=lJ8ydIuPFeU&feature=youtu.be
-[36]: http://linuxczar.net/blog/2017/06/15/prometheus-histogram-2/
-[37]: https://www.dynatrace.com/news/blog/why-averages-suck-and-percentiles-are-great/
-[38]: https://bravenewgeek.com/everything-you-know-about-latency-is-wrong/
-[39]: https://engineering.linkedin.com/performance/who-moved-my-99th-percentile-latency
-[40]: https://grafana.com/blog/2016/01/05/logs-and-metrics-and-graphs-oh-my/
-[41]: http://psy-lob-saw.blogspot.com.au/2015/02/hdrhistogram-better-latency-capture.html
-[42]: https://us.pycon.org/2018/schedule/presentation/133/
-[43]: https://us.pycon.org/2018/
-[44]: https://opensource.com/users/amitsaha
-[45]: https://opensource.com/users/amitsaha
-[46]: https://opensource.com/participate
-[47]: https://opensource.com/article/18/4/metrics-monitoring-and-python
-[48]: https://opensource.com/users/amitsaha
-[49]: https://github.com/lujun9972
-[50]: https://github.com/译者ID
-[51]: https://github.com/校对者ID
-[52]: https://github.com/LCTT/TranslateProject
-[53]: https://linux.cn/
diff --git a/sources/tech/20180426 How To Check System Hardware Manufacturer, Model And Serial Number In Linux.md b/sources/tech/20180426 How To Check System Hardware Manufacturer, Model And Serial Number In Linux.md
deleted file mode 100644
index da97e87fc6..0000000000
--- a/sources/tech/20180426 How To Check System Hardware Manufacturer, Model And Serial Number In Linux.md
+++ /dev/null
@@ -1,155 +0,0 @@
-How To Check System Hardware Manufacturer, Model And Serial Number In Linux
-======
-Getting system hardware information is not a problem for Linux GUI and Windows users but CLI users facing trouble to get this details.
-
-Even most of us don’t know what is the best command to get this. There are many utilities available in Linux to get system hardware information such as
-
-System Hardware Manufacturer, Model And Serial Number.
-
-We are trying to write possible ways to get this details but you can choose the best method for you.
-
-It is mandatory to know all these information because it will be needed when you raise a case with hardware vendor for any kind of hardware issues.
-
-This can be achieved in six methods, let me show you how to do that.
-
-### Method-1 : Using Dmidecode Command
-
-Dmidecode is a tool which reads a computer’s DMI (stands for Desktop Management Interface) (some say SMBIOS – stands for System Management BIOS) table contents and display system hardware information in a human-readable format.
-
-This table contains a description of the system’s hardware components, as well as other useful information such as serial number, Manufacturer information, Release Date, and BIOS revision, etc,.,
-
-The DMI table doesn’t only describe what the system is currently made of, it also can report the possible evolution (such as the fastest supported CPU or the maximal amount of memory supported).
-
-This will help you to analyze your hardware capability like whether it’s support latest application version or not?
-```
-# dmidecode -t system
-
-# dmidecode 2.12
-# SMBIOS entry point at 0x7e7bf000
-SMBIOS 2.7 present.
-
-Handle 0x0024, DMI type 1, 27 bytes
-System Information
- Manufacturer: IBM
- Product Name: System x2530 M4: -[1214AC1]-
- Version: 0B
- Serial Number: MK2RL11
- UUID: 762A99BF-6916-450F-80A6-B2E9E78FC9A1
- Wake-up Type: Power Switch
- SKU Number: Not Specified
- Family: System X
-
-Handle 0x004B, DMI type 12, 5 bytes
-System Configuration Options
- Option 1: JP20 pin1-2: TPM PP Disable, pin2-3: TPM PP Enable
-
-Handle 0x004D, DMI type 32, 20 bytes
-System Boot Information
- Status: No errors detected
-
-```
-
-**Suggested Read :** [Dmidecode – Easy Way To Get Linux System Hardware Information][1]
-
-### Method-2 : Using inxi Command
-
-inxi is a nifty tool to check hardware information on Linux and offers wide range of option to get all the hardware information on Linux system that i never found in any other utility which are available in Linux. It was forked from the ancient and mindbendingly perverse yet ingenius infobash, by locsmif.
-
-inxi is a script that quickly shows system hardware, CPU, drivers, Xorg, Desktop, Kernel, GCC version(s), Processes, RAM usage, and a wide variety of other useful information, also used for forum technical support & debugging tool.
-```
-# inxi -M
-Machine: Device: server System: IBM product: N/A v: 0B serial: MK2RL11
- Mobo: IBM model: 00Y8494 serial: 37M17D UEFI: IBM v: -[VVE134MUS-1.50]- date: 08/30/2013
-
-```
-
-**Suggested Read :** [inxi – A Great Tool to Check Hardware Information on Linux][2]
-
-### Method-3 : Using lshw Command
-
-lshw (stands for Hardware Lister) is a small nifty tool that generates detailed reports about various hardware components on the machine such as memory configuration, firmware version, mainboard configuration, CPU version and speed, cache configuration, usb, network card, graphics cards, multimedia, printers, bus speed, etc.
-
-It’s generating hardware information by reading varies files under /proc directory and DMI table.
-
-lshw must be run as super user to detect the maximum amount of information or it will only report partial information. Special option is available in lshw called class which will shows specific given hardware information in detailed manner.
-```
-# lshw -C system
-enal-dbo01t
- description: Blade
- product: System x2530 M4: -[1214AC1]-
- vendor: IBM
- version: 0B
- serial: MK2RL11
- width: 64 bits
- capabilities: smbios-2.7 dmi-2.7 vsyscall32
- configuration: boot=normal chassis=enclosure family=System X uuid=762A99BF-6916-450F-80A6-B2E9E78FC9A1
-
-```
-
-**Suggested Read :** [LSHW (Hardware Lister) – A Nifty Tool To Get A Hardware Information On Linux][3]
-
-### Method-4 : Using /sys file system
-
-The kernel expose some DMI information in the /sys virtual filesystem. So we can easily get the machine type by running grep command with following format.
-```
-# grep "" /sys/class/dmi/id/[pbs]*
-
-```
-
-Alternatively we can print only specific details by using cat command.
-```
-# cat /sys/class/dmi/id/board_vendor
-IBM
-
-# cat /sys/class/dmi/id/product_name
-System x2530 M4: -[1214AC1]-
-
-# cat /sys/class/dmi/id/product_serial
-MK2RL11
-
-# cat /sys/class/dmi/id/bios_version
--[VVE134MUS-1.50]-
-
-```
-
-### Method-5 : Using dmesg Command
-
-The dmesg command is used to write the kernel messages (boot-time messages) in Linux before syslogd or klogd start. It obtains its data by reading the kernel ring buffer. dmesg can be very useful when troubleshooting or just trying to obtain information about the hardware on a system.
-```
-# dmesg | grep -i DMI
-DMI: System x2530 M4: -[1214AC1]-/00Y8494, BIOS -[VVE134MUS-1.50]- 08/30/2013
-
-```
-
-### Method-6 : Using hwinfo Command
-
-hwinfo stands for hardware information tool is another great utility that used to probe for the hardware present in the system and display detailed information about varies hardware components in human readable format.
-
-It reports information about CPU, RAM, keyboard, mouse, graphics card, sound, storage, network interface, disk, partition, bios, and bridge, etc,., This tool could display more detailed information among others like lshw, dmidecode, inxi, etc,.
-
-hwinfo uses libhd library libhd.so to gather hardware information on the system. This tool especially designed for openSUSE system, later other distributions are included the tool into their official repository.
-```
-# hwinfo | egrep "system.hardware.vendor|system.hardware.product"
- system.hardware.vendor = 'IBM'
- system.hardware.product = 'System x2530 M4: -[1214AC1]-'
-
-```
-
-**Suggested Read :** [hwinfo (Hardware Info) – A Nifty Tool To Detect System Hardware Information On Linux][4]
-
---------------------------------------------------------------------------------
-
-via: https://www.2daygeek.com/how-to-check-system-hardware-manufacturer-model-and-serial-number-in-linux/
-
-作者:[VINOTH KUMAR][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://www.2daygeek.com/author/vinoth/
-[1]:https://www.2daygeek.com/dmidecode-get-print-display-check-linux-system-hardware-information/
-[2]:https://www.2daygeek.com/inxi-system-hardware-information-on-linux/
-[3]:https://www.2daygeek.com/lshw-find-check-system-hardware-information-details-linux/
-[4]:https://www.2daygeek.com/hwinfo-check-display-detect-system-hardware-information-linux/
diff --git a/sources/tech/20180427 An Official Introduction to the Go Compiler.md b/sources/tech/20180427 An Official Introduction to the Go Compiler.md
deleted file mode 100644
index 65c35fee64..0000000000
--- a/sources/tech/20180427 An Official Introduction to the Go Compiler.md
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-## Introduction to the Go compiler
-
-`cmd/compile` contains the main packages that form the Go compiler. The compiler
-may be logically split in four phases, which we will briefly describe alongside
-the list of packages that contain their code.
-
-You may sometimes hear the terms "front-end" and "back-end" when referring to
-the compiler. Roughly speaking, these translate to the first two and last two
-phases we are going to list here. A third term, "middle-end", often refers to
-much of the work that happens in the second phase.
-
-Note that the `go/*` family of packages, such as `go/parser` and `go/types`,
-have no relation to the compiler. Since the compiler was initially written in C,
-the `go/*` packages were developed to enable writing tools working with Go code,
-such as `gofmt` and `vet`.
-
-It should be clarified that the name "gc" stands for "Go compiler", and has
-little to do with uppercase GC, which stands for garbage collection.
-
-### 1. Parsing
-
-* `cmd/compile/internal/syntax` (lexer, parser, syntax tree)
-
-In the first phase of compilation, source code is tokenized (lexical analysis),
-parsed (syntactic analyses), and a syntax tree is constructed for each source
-file.
-
-Each syntax tree is an exact representation of the respective source file, with
-nodes corresponding to the various elements of the source such as expressions,
-declarations, and statements. The syntax tree also includes position information
-which is used for error reporting and the creation of debugging information.
-
-### 2. Type-checking and AST transformations
-
-* `cmd/compile/internal/gc` (create compiler AST, type checking, AST transformations)
-
-The gc package includes an AST definition carried over from when it was written
-in C. All of its code is written in terms of it, so the first thing that the gc
-package must do is convert the syntax package's syntax tree to the compiler's
-AST representation. This extra step may be refactored away in the future.
-
-The AST is then type-checked. The first steps are name resolution and type
-inference, which determine which object belongs to which identifier, and what
-type each expression has. Type-checking includes certain extra checks, such as
-"declared and not used" as well as determining whether or not a function
-terminates.
-
-Certain transformations are also done on the AST. Some nodes are refined based
-on type information, such as string additions being split from the arithmetic
-addition node type. Some other examples are dead code elimination, function call
-inlining, and escape analysis.
-
-### 3. Generic SSA
-
-* `cmd/compile/internal/gc` (converting to SSA)
-* `cmd/compile/internal/ssa` (SSA passes and rules)
-
-
-In this phase, the AST is converted into Static Single Assignment (SSA) form, a
-lower-level intermediate representation with specific properties that make it
-easier to implement optimizations and to eventually generate machine code from
-it.
-
-During this conversion, function intrinsics are applied. These are special
-functions that the compiler has been taught to replace with heavily optimized
-code on a case-by-case basis.
-
-Certain nodes are also lowered into simpler components during the AST to SSA
-conversion, so that the rest of the compiler can work with them. For instance,
-the copy builtin is replaced by memory moves, and range loops are rewritten into
-for loops. Some of these currently happen before the conversion to SSA due to
-historical reasons, but the long-term plan is to move all of them here.
-
-Then, a series of machine-independent passes and rules are applied. These do not
-concern any single computer architecture, and thus run on all `GOARCH` variants.
-
-Some examples of these generic passes include dead code elimination, removal of
-unneeded nil checks, and removal of unused branches. The generic rewrite rules
-mainly concern expressions, such as replacing some expressions with constant
-values, and optimizing multiplications and float operations.
-
-### 4. Generating machine code
-
-* `cmd/compile/internal/ssa` (SSA lowering and arch-specific passes)
-* `cmd/internal/obj` (machine code generation)
-
-The machine-dependent phase of the compiler begins with the "lower" pass, which
-rewrites generic values into their machine-specific variants. For example, on
-amd64 memory operands are possible, so many load-store operations may be combined.
-
-Note that the lower pass runs all machine-specific rewrite rules, and thus it
-currently applies lots of optimizations too.
-
-Once the SSA has been "lowered" and is more specific to the target architecture,
-the final code optimization passes are run. This includes yet another dead code
-elimination pass, moving values closer to their uses, the removal of local
-variables that are never read from, and register allocation.
-
-Other important pieces of work done as part of this step include stack frame
-layout, which assigns stack offsets to local variables, and pointer liveness
-analysis, which computes which on-stack pointers are live at each GC safe point.
-
-At the end of the SSA generation phase, Go functions have been transformed into
-a series of obj.Prog instructions. These are passed to the assembler
-(`cmd/internal/obj`), which turns them into machine code and writes out the
-final object file. The object file will also contain reflect data, export data,
-and debugging information.
-
-### Further reading
-
-To dig deeper into how the SSA package works, including its passes and rules,
-head to `cmd/compile/internal/ssa/README.md`.
-
-
-
---------------------------------------------------------------------------------
-
-via: https://github.com/golang/go/blob/master/src/cmd/compile/README.md
-
-作者:[mvdan ][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://github.com/mvdan
diff --git a/sources/tech/20180428 How to get a core dump for a segfault on Linux.md b/sources/tech/20180428 How to get a core dump for a segfault on Linux.md
deleted file mode 100644
index 1fe70221ac..0000000000
--- a/sources/tech/20180428 How to get a core dump for a segfault on Linux.md
+++ /dev/null
@@ -1,195 +0,0 @@
-translating by stenphenxs
-How to get a core dump for a segfault on Linux
-============================================================
-
-This week at work I spent all week trying to debug a segfault. I’d never done this before, and some of the basic things involved (get a core dump! find the line number that segfaulted!) took me a long time to figure out. So here’s a blog post explaining how to do those things!
-
-At the end of this blog post, you should know how to go from “oh no my program is segfaulting and I have no idea what is happening” to “well I know what its stack / line number was when it segfaulted at at least!“.
-
-### what’s a segfault?
-
-A “segmentation fault” is when your program tries to access memory that it’s not allowed to access, or tries to . This can be caused by:
-
-* trying to dereference a null pointer (you’re not allowed to access the memory address `0`)
-
-* trying to dereference some other pointer that isn’t in your memory
-
-* a C++ vtable pointer that got corrupted and is pointing to the wrong place, which causes the program to try to execute some memory that isn’t executable
-
-* some other things that I don’t understand, like I think misaligned memory accesses can also segfault
-
-This “C++ vtable pointer” thing is what was happening to my segfaulting program. I might explain that in a future blog post because I didn’t know any C++ at the beginning of this week and this vtable lookup thing was a new way for a program to segfault that I didn’t know about.
-
-But! This blog post isn’t about C++ bugs. Let’s talk about the basics, like, how do we even get a core dump?
-
-### step 1: run valgrind
-
-I found the easiest way to figure out why my program is segfaulting was to use valgrind: I ran
-
-```
-valgrind -v your-program
-
-```
-
-and this gave me a stack trace of what happened. Neat!
-
-But I wanted also wanted to do a more in-depth investigation and find out more than just what valgrind was telling me! So I wanted to get a core dump and explore it.
-
-### How to get a core dump
-
-A core dump is a copy of your program’s memory, and it’s useful when you’re trying to debug what went wrong with your problematic program.
-
-When your program segfaults, the Linux kernel will sometimes write a core dump to disk. When I originally tried to get a core dump, I was pretty frustrated for a long time because – Linux wasn’t writing a core dump!! Where was my core dump????
-
-Here’s what I ended up doing:
-
-1. Run `ulimit -c unlimited` before starting my program
-
-2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
-
-### ulimit: set the max size of a core dump
-
-`ulimit -c` sets the maximum size of a core dump. It’s often set to 0, which means that the kernel won’t write core dumps at all. It’s in kilobytes. ulimits are per process – you can see a process’s limits by running `cat /proc/PID/limit`
-
-For example these are the limits for a random Firefox process on my system:
-
-```
-$ cat /proc/6309/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 30571 30571 processes
-Max open files 1024 1048576 files
-Max locked memory 65536 65536 bytes
-Max address space unlimited unlimited bytes
-Max file locks unlimited unlimited locks
-Max pending signals 30571 30571 signals
-Max msgqueue size 819200 819200 bytes
-Max nice priority 0 0
-Max realtime priority 0 0
-Max realtime timeout unlimited unlimited us
-
-```
-
-The kernel uses the soft limit (in this case, “max core file size = 0”) when deciding how big of a core file to write. You can increase the soft limit up to the hard limit using the `ulimit` shell builtin (`ulimit -c unlimited`!)
-
-### kernel.core_pattern: where core dumps are written
-
-`kernel.core_pattern` is a kernel parameter or a “sysctl setting” that controls where the Linux kernel writes core dumps to disk.
-
-Kernel parameters are a way to set global settings on your system. You can get a list of every kernel parameter by running `sysctl -a`, or use `sysctl kernel.core_pattern` to look at the `kernel.core_pattern` setting specifically.
-
-So `sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t` will write core dumps to `/tmp/core-`
-
-If you want to know more about what these `%e`, `%p` parameters read, see [man core][1].
-
-It’s important to know that `kernel.core_pattern` is a global settings – it’s good to be a little careful about changing it because it’s possible that other systems depend on it being set a certain way.
-
-### kernel.core_pattern & Ubuntu
-
-By default on Ubuntu systems, this is what `kernel.core_pattern` is set to
-
-```
-$ sysctl kernel.core_pattern
-kernel.core_pattern = |/usr/share/apport/apport %p %s %c %d %P
-
-```
-
-This caused me a lot of confusion (what is this apport thing and what is it doing with my core dumps??) so here’s what I learned about this:
-
-* Ubuntu uses a system called “apport” to report crashes in apt packages
-
-* Setting `kernel.core_pattern=|/usr/share/apport/apport %p %s %c %d %P`means that core dumps will be piped to `apport`
-
-* apport has logs in /var/log/apport.log
-
-* apport by default will ignore crashes from binaries that aren’t part of an Ubuntu packages
-
-I ended up just overriding this Apport business and setting `kernel.core_pattern` to `sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t` because I was on a dev machine, I didn’t care whether Apport was working on not, and I didn’t feel like trying to convince Apport to give me my core dumps.
-
-### So you have a core dump. Now what?
-
-Okay, now we know about ulimits and `kernel.core_pattern` and you have actually have a core dump file on disk in `/tmp`. Amazing! Now what??? We still don’t know why the program segfaulted!
-
-The next step is to open the core file with `gdb` and get a backtrace.
-
-### Getting a backtrace from gdb
-
-You can open a core file with gdb like this:
-
-```
-$ gdb -c my_core_file
-
-```
-
-Next, we want to know what the stack was when the program crashed. Running `bt` at the gdb prompt will give you a backtrace. In my case gdb hadn’t loaded symbols for the binary, so it was just like `??????`. Luckily, loading symbols fixed it.
-
-Here’s how to load debugging symbols.
-
-```
-symbol-file /path/to/my/binary
-sharedlibrary
-
-```
-
-This loads symbols from the binary and from any shared libraries the binary uses. Once I did that, gdb gave me a beautiful stack trace with line numbers when I ran `bt`!!!
-
-If you want this to work, the binary should be compiled with debugging symbols. Having line numbers in your stack traces is extremely helpful when trying to figure out why a program crashed :)
-
-### look at the stack for every thread
-
-Here’s how to get the stack for every thread in gdb!
-
-```
-thread apply all bt full
-
-```
-
-### gdb + core dumps = amazing
-
-If you have a core dump & debugging symbols and gdb, you are in an amazing situation!! You can go up and down the call stack, print out variables, and poke around in memory to see what happened. It’s the best.
-
-If you are still working on being a gdb wizard, you can also just print out the stack trace with `bt` and that’s okay :)
-
-### ASAN
-
-Another path to figuring out your segfault is to do one compile the program with AddressSanitizer (“ASAN”) (`$CC -fsanitize=address`) and run it. I’m not going to discuss that in this post because this is already pretty long and anyway in my case the segfault disappeared with ASAN turned on for some reason, possibly because the ASAN build used a different memory allocator (system malloc instead of tcmalloc).
-
-I might write about ASAN more in the future if I ever get it to work :)
-
-### getting a stack trace from a core dump is pretty approachable!
-
-This blog post sounds like a lot and I was pretty confused when I was doing it but really there aren’t all that many steps to getting a stack trace out of a segfaulting program:
-
-1. try valgrind
-
-if that doesn’t work, or if you want to have a core dump to investigate:
-
-1. make sure the binary is compiled with debugging symbols
-
-2. set `ulimit` and `kernel.core_pattern` correctly
-
-3. run the program
-
-4. open your core dump with `gdb`, load the symbols, and run `bt`
-
-5. try to figure out what happened!!
-
-I was able using gdb to figure out that there was a C++ vtable entry that is pointing to some corrupt memory, which was somewhat helpful and helped me feel like I understood C++ a bit better. Maybe we’ll talk more about how to use gdb to figure things out another day!
-
---------------------------------------------------------------------------------
-
-via: https://jvns.ca/blog/2018/04/28/debugging-a-segfault-on-linux/
-
-作者:[Julia Evans ][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://jvns.ca/about/
-[1]:http://man7.org/linux/man-pages/man5/core.5.html
diff --git a/sources/tech/20180430 3 practical Python tools- magic methods, iterators and generators, and method magic.md b/sources/tech/20180430 3 practical Python tools- magic methods, iterators and generators, and method magic.md
deleted file mode 100644
index 2cb0e5a948..0000000000
--- a/sources/tech/20180430 3 practical Python tools- magic methods, iterators and generators, and method magic.md
+++ /dev/null
@@ -1,633 +0,0 @@
-3 practical Python tools: magic methods, iterators and generators, and method magic
-======
-
-
-Python offers a unique set of tools and language features that help make your code more elegant, readable, and intuitive. By selecting the right tool for the right problem, your code will be easier to maintain. In this article, we'll examine three of those tools: magic methods, iterators and generators, and method magic.
-
-### Magic methods
-
-
-Magic methods can be considered the plumbing of Python. They're the methods that are called "under the hood" for certain built-in methods, symbols, and operations. A common magic method you may be familiar with is, `__init__()`,which is called when we want to initialize a new instance of a class.
-
-You may have seen other common magic methods, like `__str__` and `__repr__`. There is a whole world of magic methods, and by implementing a few of them, we can greatly modify the behavior of an object or even make it behave like a built-in datatype, such as a number, list, or dictionary.
-
-Let's take this `Money` class for example:
-```
-class Money:
-
-
-
- currency_rates = {
-
- '$': 1,
-
- '€': 0.88,
-
- }
-
-
-
- def __init__(self, symbol, amount):
-
- self.symbol = symbol
-
- self.amount = amount
-
-
-
- def __repr__(self):
-
- return '%s%.2f' % (self.symbol, self.amount)
-
-
-
- def convert(self, other):
-
- """ Convert other amount to our currency """
-
- new_amount = (
-
- other.amount / self.currency_rates[other.symbol]
-
- * self.currency_rates[self.symbol])
-
-
-
- return Money(self.symbol, new_amount)
-
-```
-
-The class defines a currency rate for a given symbol and exchange rate, specifies an initializer (also known as a constructor), and implements `__repr__`, so when we print out the class, we see a nice representation such as `$2.00` for an instance `Money('$', 2.00)` with the currency symbol and amount. Most importantly, it defines a method that allows you to convert between different currencies with different exchange rates.
-
-Using a Python shell, let's say we've defined the costs for two food items in different currencies, like so:
-```
->>> soda_cost = Money('$', 5.25)
-
->>> soda_cost
-
- $5.25
-
-
-
->>> pizza_cost = Money('€', 7.99)
-
->>> pizza_cost
-
- €7.99
-
-```
-
-We could use magic methods to help instances of this class interact with each other. Let's say we wanted to be able to add two instances of this class together, even if they were in different currencies. To make that a reality, we could implement the `__add__` magic method on our `Money` class:
-```
-class Money:
-
-
-
- # ... previously defined methods ...
-
-
-
- def __add__(self, other):
-
- """ Add 2 Money instances using '+' """
-
- new_amount = self.amount + self.convert(other).amount
-
- return Money(self.symbol, new_amount)
-
-```
-
-Now we can use this class in a very intuitive way:
-```
->>> soda_cost = Money('$', 5.25)
-
-
-
->>> pizza_cost = Money('€', 7.99)
-
-
-
->>> soda_cost + pizza_cost
-
- $14.33
-
-
-
->>> pizza_cost + soda_cost
-
- €12.61
-
-```
-
-When we add two instances together, we get a result in the first defined currency. All the conversion is done seamlessly under the hood. If we wanted to, we could also implement `__sub__` for subtraction, `__mul__` for multiplication, and many more. Read about [emulating numeric types][1], or read this [guide to magic methods][2] for others.
-
-We learned that `__add__` maps to the built-in operator `+`. Other magic methods can map to symbols like `[]`. For example, to access an item by index or key (in the case of a dictionary), use the `__getitem__` method:
-```
->>> d = {'one': 1, 'two': 2}
-
-
-
->>> d['two']
-
-2
-
->>> d.__getitem__('two')
-
-2
-
-```
-
-Some magic methods even map to built-in functions, such as `__len__()`, which maps to `len()`.
-```
-class Alphabet:
-
- letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-
-
-
- def __len__(self):
-
- return len(self.letters)
-
-
-
-
-
->>> my_alphabet = Alphabet()
-
->>> len(my_alphabet)
-
- 26
-
-```
-
-### Custom iterators
-
-Custom iterators are an incredibly powerful but unfortunately confusing topic to new and seasoned Pythonistas alike.
-
-Many built-in types, such as lists, sets, and dictionaries, already implement the protocol that allows them to be iterated over under the hood. This allows us to easily loop over them.
-```
->>> for food in ['Pizza', 'Fries']:
-
- print(food + '. Yum!')
-
-
-
-Pizza. Yum!
-
-Fries. Yum!
-
-```
-
-How can we iterate over our own custom classes? First, let's clear up some terminology.
-
- * To be iterable, a class needs to implement `__iter__()`
- * The `__iter__()` method needs to return an iterator
- * To be an iterator, a class needs to implement `__next__()` (or `next()` [in Python 2][3]), which must raise a `StopIteration` exception when there are no more items to iterate over.
-
-
-
-Whew! It sounds complicated, but once you remember these fundamental concepts, you'll be able to iterate in your sleep.
-
-When might we want to use a custom iterator? Let's imagine a scenario where we have a `Server` instance running different services such as `http` and `ssh` on different ports. Some of these services have an `active` state while others are `inactive`.
-```
-class Server:
-
-
-
- services = [
-
- {'active': False, 'protocol': 'ftp', 'port': 21},
-
- {'active': True, 'protocol': 'ssh', 'port': 22},
-
- {'active': True, 'protocol': 'http', 'port': 80},
-
- ]
-
-```
-
-When we loop over our `Server` instance, we only want to loop over `active` services. Let's create a new class, an `IterableServer`:
-```
-class IterableServer:
-
-
-
- def __init__(self):
-
- self.current_pos = 0
-
-
-
- def __next__(self):
-
- pass # TODO: Implement and remember to raise StopIteration
-
-```
-
-First, we initialize our current position to `0`. Then, we define a `__next__()` method, which will return the next item. We'll also ensure that we raise `StopIteration` when there are no more items to return. So far so good! Now, let's implement this `__next__()` method.
-```
-class IterableServer:
-
-
-
- def __init__(self):
-
- self.current_pos = 0. # we initialize our current position to zero
-
-
-
- def __iter__(self): # we can return self here, because __next__ is implemented
-
- return self
-
-
-
- def __next__(self):
-
- while self.current_pos < len(self.services):
-
- service = self.services[self.current_pos]
-
- self.current_pos += 1
-
- if service['active']:
-
- return service['protocol'], service['port']
-
- raise StopIteration
-
-
-
- next = __next__ # optional python2 compatibility
-
-```
-
-We keep looping over the services in our list while our current position is less than the length of the services but only returning if the service is active. Once we run out of services to iterate over, we raise a `StopIteration` exception.
-
-Because we implement a `__next__()` method that raises `StopIteration` when it is exhausted, we can return `self` from `__iter__()` because the `IterableServer` class adheres to the `iterable` protocol.
-
-Now we can loop over an instance of `IterableServer`, which will allow us to look at each active service, like so:
-```
->>> for protocol, port in IterableServer():
-
- print('service %s is running on port %d' % (protocol, port))
-
-
-
-service ssh is running on port 22
-
-service http is running on port 21
-
-```
-
-That's pretty great, but we can do better! In an instance like this, where our iterator doesn't need to maintain a lot of state, we can simplify our code and use a [generator][4] instead.
-```
-class Server:
-
-
-
- services = [
-
- {'active': False, 'protocol': 'ftp', 'port': 21},
-
- {'active': True, 'protocol': 'ssh', 'port': 22},
-
- {'active': True, 'protocol': 'http', 'port': 21},
-
- ]
-
-
-
- def __iter__(self):
-
- for service in self.services:
-
- if service['active']:
-
- yield service['protocol'], service['port']
-
-```
-
-What exactly is the `yield` keyword? Yield is used when defining a generator function. It's sort of like a `return`. While a `return` exits the function after returning the value, `yield` suspends execution until the next time it's called. This allows your generator function to maintain state until it resumes. Check out [yield's documentation][5] to learn more. With a generator, we don't have to manually maintain state by remembering our position. A generator knows only two things: what it needs to do right now and what it needs to do to calculate the next item. Once we reach a point of execution where `yield` isn't called again, we know to stop iterating.
-
-This works because of some built-in Python magic. In the [Python documentation for `__iter__()`][6] we can see that if `__iter__()` is implemented as a generator, it will automatically return an iterator object that supplies the `__iter__()` and `__next__()` methods. Read this great article for a deeper dive of [iterators, iterables, and generators][7].
-
-### Method magic
-
-Due to its unique aspects, Python provides some interesting method magic as part of the language.
-
-One example of this is aliasing functions. Since functions are just objects, we can assign them to multiple variables. For example:
-```
->>> def foo():
-
- return 'foo'
-
-
-
->>> foo()
-
-'foo'
-
-
-
->>> bar = foo
-
-
-
->>> bar()
-
-'foo'
-
-```
-
-We'll see later on how this can be useful.
-
-Python provides a handy built-in, [called `getattr()`][8], that takes the `object, name, default` parameters and returns the attribute `name` on `object`. This programmatically allows us to access instance variables and methods. For example:
-```
->>> class Dog:
-
- sound = 'Bark'
-
- def speak(self):
-
- print(self.sound + '!', self.sound + '!')
-
-
-
->>> fido = Dog()
-
-
-
->>> fido.sound
-
-'Bark'
-
->>> getattr(fido, 'sound')
-
-'Bark'
-
-
-
->>> fido.speak
-
->
-
->>> getattr(fido, 'speak')
-
->
-
-
-
-
-
->>> fido.speak()
-
-Bark! Bark!
-
->>> speak_method = getattr(fido, 'speak')
-
->>> speak_method()
-
-Bark! Bark!
-
-```
-
-Cool trick, but how could we practically use `getattr`? Let's look at an example that allows us to write a tiny command-line tool to dynamically process commands.
-```
-class Operations:
-
- def say_hi(self, name):
-
- print('Hello,', name)
-
-
-
- def say_bye(self, name):
-
- print ('Goodbye,', name)
-
-
-
- def default(self, arg):
-
- print ('This operation is not supported.')
-
-
-
-if __name__ == '__main__':
-
- operations = Operations()
-
-
-
- # let's assume we do error handling
-
- command, argument = input('> ').split()
-
- func_to_call = getattr(operations, command, operations.default)
-
- func_to_call(argument)
-
-```
-
-The output of our script is:
-```
-$ python getattr.py
-
-
-
-> say_hi Nina
-
-Hello, Nina
-
-
-
-> blah blah
-
-This operation is not supported.
-
-```
-
-Next, we'll look at `partial`. For example, **`functool.partial(func, *args, **kwargs)`** allows you to return a new [partial object][9] that behaves like `func` called with `args` and `kwargs`. If more `args` are passed in, they're appended to `args`. If more `kwargs` are passed in, they extend and override `kwargs`. Let's see it in action with a brief example:
-```
->>> from functools import partial
-
->>> basetwo = partial(int, base=2)
-
->>> basetwo
-
-
-
-
-
->>> basetwo('10010')
-
-18
-
-
-
-# This is the same as
-
->>> int('10010', base=2)
-
-```
-
-Let's see how this method magic ties together in some sample code from a library I enjoy using [called][10]`agithub`, which is a (poorly named) REST API client with transparent syntax that allows you to rapidly prototype any REST API (not just GitHub) with minimal configuration. I find this project interesting because it's incredibly powerful yet only about 400 lines of Python. You can add support for any REST API in about 30 lines of configuration code. `agithub` knows everything it needs to about protocol (`REST`, `HTTP`, `TCP`), but it assumes nothing about the upstream API. Let's dive into the implementation.
-
-Here's a simplified version of how we'd define an endpoint URL for the GitHub API and any other relevant connection properties. View the [full code][11] instead.
-```
-class GitHub(API):
-
-
-
- def __init__(self, token=None, *args, **kwargs):
-
- props = ConnectionProperties(api_url = kwargs.pop('api_url', 'api.github.com'))
-
- self.setClient(Client(*args, **kwargs))
-
- self.setConnectionProperties(props)
-
-```
-
-Then, once your [access token][12] is configured, you can start using the [GitHub API][13].
-```
->>> gh = GitHub('token')
-
->>> status, data = gh.user.repos.get(visibility='public', sort='created')
-
->>> # ^ Maps to GET /user/repos
-
->>> data
-
-... ['tweeter', 'snipey', '...']
-
-```
-
-Note that it's up to you to spell things correctly. There's no validation of the URL. If the URL doesn't exist or anything else goes wrong, the error thrown by the API will be returned. So, how does this all work? Let's figure it out. First, we'll check out a simplified example of the [`API` class][14]:
-```
-class API:
-
-
-
- # ... other methods ...
-
-
-
- def __getattr__(self, key):
-
- return IncompleteRequest(self.client).__getattr__(key)
-
- __getitem__ = __getattr__
-
-```
-
-Each call on the `API` class ferries the call to the [`IncompleteRequest` class][15] for the specified `key`.
-```
-class IncompleteRequest:
-
-
-
- # ... other methods ...
-
-
-
- def __getattr__(self, key):
-
- if key in self.client.http_methods:
-
- htmlMethod = getattr(self.client, key)
-
- return partial(htmlMethod, url=self.url)
-
- else:
-
- self.url += '/' + str(key)
-
- return self
-
- __getitem__ = __getattr__
-
-
-
-
-
-class Client:
-
- http_methods = ('get') # ... and post, put, patch, etc.
-
-
-
- def get(self, url, headers={}, **params):
-
- return self.request('GET', url, None, headers)
-
-```
-
-If the last call is not an HTTP method (like 'get', 'post', etc.), it returns an `IncompleteRequest` with an appended path. Otherwise, it gets the right function for the specified HTTP method from the [`Client` class][16] and returns a `partial` .
-
-What happens if we give a non-existent path?
-```
->>> status, data = this.path.doesnt.exist.get()
-
->>> status
-
-... 404
-
-```
-
-And because `__getitem__` is aliased to `__getattr__`:
-```
->>> owner, repo = 'nnja', 'tweeter'
-
->>> status, data = gh.repos[owner][repo].pulls.get()
-
->>> # ^ Maps to GET /repos/nnja/tweeter/pulls
-
->>> data
-
-.... # {....}
-
-```
-
-Now that's some serious method magic!
-
-### Learn more
-
-Python provides plenty of tools that allow you to make your code more elegant and easier to read and understand. The challenge is finding the right tool for the job, but I hope this article added some new ones to your toolbox. And, if you'd like to take this a step further, you can read about decorators, context managers, context generators, and `NamedTuple`s on my blog [nnja.io][17]. As you become a better Python developer, I encourage you to get out there and read some source code for well-architected projects. [Requests][18] and [Flask][19] are two great codebases to start with.
-
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/4/elegant-solutions-everyday-python-problems
-
-作者:[Nina Zakharenko][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/nnja
-[1]:https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
-[2]:https://rszalski.github.io/magicmethods/
-[3]:https://docs.python.org/2/library/stdtypes.html#iterator.next
-[4]:https://docs.python.org/3/library/stdtypes.html#generator-types
-[5]:https://docs.python.org/3/reference/expressions.html#yieldexpr
-[6]:https://docs.python.org/3/reference/datamodel.html#object.__iter__
-[7]:http://nvie.com/posts/iterators-vs-generators/
-[8]:https://docs.python.org/3/library/functions.html#getattr
-[9]:https://docs.python.org/3/library/functools.html#functools.partial
-[10]:https://github.com/mozilla/agithub
-[11]:https://github.com/mozilla/agithub/blob/master/agithub/GitHub.py
-[12]:https://github.com/settings/tokens
-[13]:https://developer.github.com/v3/repos/#list-your-repositories
-[14]:https://github.com/mozilla/agithub/blob/dbf7014e2504333c58a39153aa11bbbdd080f6ac/agithub/base.py#L30-L58
-[15]:https://github.com/mozilla/agithub/blob/dbf7014e2504333c58a39153aa11bbbdd080f6ac/agithub/base.py#L60-L100
-[16]:https://github.com/mozilla/agithub/blob/dbf7014e2504333c58a39153aa11bbbdd080f6ac/agithub/base.py#L102-L231
-[17]:http://nnja.io
-[18]:https://github.com/requests/requests
-[19]:https://github.com/pallets/flask
-[20]:https://us.pycon.org/2018/schedule/presentation/164/
-[21]:https://us.pycon.org/2018/
diff --git a/sources/tech/20180502 Customizing your text colors on the Linux command line.md b/sources/tech/20180502 Customizing your text colors on the Linux command line.md
deleted file mode 100644
index 381df0e53a..0000000000
--- a/sources/tech/20180502 Customizing your text colors on the Linux command line.md
+++ /dev/null
@@ -1,163 +0,0 @@
-Customizing your text colors on the Linux command line
-======
-
-
-If you spend much time on the Linux command line (and you probably wouldn't be reading this if you didn't), you've undoubtedly noticed that the ls command displays your files in a number of different colors. You've probably also come to recognize some of the distinctions — directories appearing in one color, executable files in another, etc.
-
-How that all happens and what options are available for you to change the color assignments might not be so obvious.
-
-One way to get a big dose of data showing how these colors are assigned is to run the **dircolors** command. It will show you something like this:
-```
-$ dircolors
-LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do
-=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg
-=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01
-;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01
-;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=0
-1;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31
-:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.
-xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.t
-bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.j
-ar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.a
-lz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.r
-z=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.
-mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:
-*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:
-*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;3
-5:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;
-35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01
-;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01
-;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01
-;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;3
-5:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;3
-5:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;3
-6:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;
-36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;
-36:*.spx=00;36:*.xspf=00;36:';
-export LS_COLORS
-
-```
-
-If you're good at parsing, you probably noticed that there's a pattern to this listing. Break it on the colons, and you'll see something like this:
-```
-$ dircolors | tr ":" "\n" | head -10
-LS_COLORS='rs=0
-di=01;34
-ln=01;36
-mh=00
-pi=40;33
-so=01;35
-do=01;35
-bd=40;33;01
-cd=40;33;01
-or=40;31;01
-
-```
-
-OK, so we have a pattern here — a series of definitions that have one to three numeric components. Let's hone in on one of definition.
-```
-pi=40;33
-
-```
-
-The first question someone is likely to ask is "What is pi?" We're working with colors and file types here, so this clearly isn't the intriguing number that starts with 3.14. No, this "pi" stands for "pipe" — a particular type of file on Linux systems that makes it possible to send data from one program to another. So, let's set one up.
-```
-$ mknod /tmp/mypipe p
-$ ls -l /tmp/mypipe
-prw-rw-r-- 1 shs shs 0 May 1 14:00 /tmp/mypipe
-
-```
-
-When we look at our pipe and a couple other files in a terminal window, the color differences are quite obvious.
-
-![font colors][1] Sandra Henry-Stocker
-
-The "40" in the definition of pi (shown above) makes the file show up in the terminal (or PuTTY) window with a black background. The 31 makes the font color red. Pipes are special files, and this special handling makes them stand out in a directory listing.
-
-The **bd** and **cd** definitions are identical to each other — 40;33;01 and have an extra setting. The settings cause block (bd) and character (cd) devices to be displayed with a black background, an orange font, and one other effect — the characters will be in bold.
-
-The following list shows the color and font assignments that are made by **file type** :
-```
-setting file type
-======= =========
-rs=0 reset to no color
-di=01;34 directory
-ln=01;36 link
-mh=00 multi-hard link
-pi=40;33 pipe
-so=01;35 socket
-do=01;35 door
-bd=40;33;01 block device
-cd=40;33;01 character device
-or=40;31;01 orphan
-mi=00 missing?
-su=37;41 setuid
-sg=30;43 setgid
-ca=30;41 file with capability
-tw=30;42 directory with sticky bit and world writable
-ow=34;42 directory that is world writable
-st=37;44 directory with sticky bit
-ex=01;93 executable
-
-```
-
-You may have noticed that in our **dircolors** command output, most of our definitions started with asterisks (e.g., *.wav=00;36). These define display attributes by **file extension** rather than file type. Here's a sampling:
-```
-$ dircolors | tr ":" "\n" | tail -10
-*.mpc=00;36
-*.ogg=00;36
-*.ra=00;36
-*.wav=00;36
-*.oga=00;36
-*.opus=00;36
-*.spx=00;36
-*.xspf=00;36
-';
-export LS_COLORS
-
-```
-
-These settings (all 00:36 in the listing above) would have these file names displaying in cyan. The available colors are shown below.
-
-![all colors][2] Sandra Henry-Stocker
-
-### How to change your settings
-
-The colors and font changes described require that you use an alias for ls that turns on the color feature. This is usually the default on Linux systems and will look like this:
-```
-alias ls='ls --color=auto'
-
-```
-
-If you wanted to turn off font colors, you could run the **unalias ls** command and your file listings would then show in only the default font color.
-
-You can alter your text colors by modifying your $LS_COLORS settings and exporting the modified setting:
-```
-$ export LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;...
-
-```
-
-NOTE: The command above is truncated.
-
-If you want your modified text colors to be permanent, you would need to add your modified LS_COLORS definition to one of your startup files (e.g., .bashrc).
-
-### More on command line text
-
-You can find additional information on text colors in this [November 2016][3] post on NetworkWorld.
-
-
---------------------------------------------------------------------------------
-
-via: https://www.networkworld.com/article/3269587/linux/customizing-your-text-colors-on-the-linux-command-line.html
-
-作者:[Sandra Henry-Stocker][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://www.networkworld.com/author/Sandra-Henry_Stocker/
-[1]:https://images.idgesg.net/images/article/2018/05/font-colors-100756483-large.jpg
-[2]:https://images.techhive.com/images/article/2016/11/all-colors-100691990-large.jpg
-[3]:https://www.networkworld.com/article/3138909/linux/coloring-your-world-with-ls-colors.html
diff --git a/sources/tech/20180508 How To Check Ubuntu Version and Other System Information Easily.md b/sources/tech/20180508 How To Check Ubuntu Version and Other System Information Easily.md
deleted file mode 100644
index 9395b7708a..0000000000
--- a/sources/tech/20180508 How To Check Ubuntu Version and Other System Information Easily.md
+++ /dev/null
@@ -1,127 +0,0 @@
-How To Check Ubuntu Version and Other System Information Easily
-======
-**Brief: Wondering which Ubuntu version are you using? Here’s how to check Ubuntu version, desktop environment and other relevant system information.**
-
-You can easily find the Ubuntu version you are using in the command line or via the graphical interface. Knowing the exact Ubuntu version, desktop environment and other system information helps a lot when you are trying to follow a tutorial from the web or seeking help in various forums.
-
-In this quick tip, I’ll show you various ways to check [Ubuntu][1] version and other common system information.
-
-### How to check Ubuntu version in terminal
-
-This is the best way to find Ubuntu version. I could have mentioned the graphical way first but then I chose this method because this one doesn’t depend on the [desktop environment][2] you are using. You can use it on any Ubuntu variant.
-
-Open a terminal (Ctrl+Alt+T) and type the following command:
-```
-lsb_release -a
-
-```
-
-The output of the above command should be like this:
-```
-No LSB modules are available.
-Distributor ID: Ubuntu
-Description: Ubuntu 16.04.4 LTS
-Release: 16.04
-Codename: xenial
-
-```
-
-![How to check Ubuntu version in command line][3]
-
-As you can see, the current Ubuntu installed in my system is Ubuntu 16.04 and its code name is Xenial.
-
-Wait! Why does it say Ubuntu 16.04.4 in Description and 16.04 in the Release? Which one is it, 16.04 or 16.04.4? What’s the difference between the two?
-
-The short answer is that you are using Ubuntu 16.04. That’s the base image. 16.04.4 signifies the fourth point release of 16.04. A point release can be thought of as a service pack in Windows era. Both 16.04 and 16.04.4 will be the correct answer here.
-
-What’s Xenial in the output? That’s the codename of the Ubuntu 16.04 release. You can read this [article to know about Ubuntu naming convention][4].
-
-#### Some alternate ways to find Ubuntu version
-
-Alternatively, you can use either of the following commands to find Ubuntu version:
-```
-cat /etc/lsb-release
-
-```
-
-The output of the above command would look like this:
-```
-DISTRIB_ID=Ubuntu
-DISTRIB_RELEASE=16.04
-DISTRIB_CODENAME=xenial
-DISTRIB_DESCRIPTION="Ubuntu 16.04.4 LTS"
-
-```
-
-![How to check Ubuntu version in command line][5]
-
-You can also use this command to know Ubuntu version
-```
-cat /etc/issue
-
-```
-
-The output of this command will be like this:
-```
-Ubuntu 16.04.4 LTS \n \l
-
-```
-
-Forget the \n \l. The Ubuntu version is 16.04.4 in this case or simply Ubuntu 16.04.
-
-### How to check Ubuntu version graphically
-
-Checking Ubuntu version graphically is no big deal either. I am going to use screenshots from Ubuntu 18.04 GNOME here. Things may look different if you are using Unity or some other desktop environment. This is why I recommend the command line version discussed in the previous sections because that doesn’t depend on the desktop environment.
-
-I’ll show you how to find the desktop environment in the next section.
-
-For now, go to System Settings and look under the Details segment.
-
-![Finding Ubuntu version graphically][6]
-
-You should see the Ubuntu version here along with the information about the desktop environment you are using, [GNOME][7] being the case here.
-
-![Finding Ubuntu version graphically][8]
-
-### How to know the desktop environment and other system information in Ubuntu
-
-So you just learned how to find Ubuntu version. What about the desktop environment in use? Which Linux kernel version is being used?
-
-Of course, there are various commands you can use to get all those information but I’ll recommend a command line utility called [Neofetch][9]. This will show you essential system information in the terminal beautifully with the logo of Ubuntu or any other Linux distribution you are using.
-
-Install Neofetch using the command below:
-```
-sudo apt install neofetch
-
-```
-
-Once installed, simply run the command `neofetch` in the terminal and see a beautiful display of system information.
-
-![System information in Linux terminal][10]
-
-As you can see, Neofetch shows you the Linux kernel version, Ubuntu version, desktop environment in use along with its version, themes and icons in use etc.
-
-I hope it helps you to find Ubuntu version and other system information. If you have suggestions to improve this article, feel free to drop it in the comment section. Ciao :)
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/how-to-know-ubuntu-unity-version/
-
-作者:[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://www.ubuntu.com/
-[2]:https://en.wikipedia.org/wiki/Desktop_environment
-[3]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2013/03/check-ubuntu-version-command-line-1-800x216.jpeg
-[4]:https://itsfoss.com/linux-code-names/
-[5]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2013/03/check-ubuntu-version-command-line-2-800x185.jpeg
-[6]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2013/03/ubuntu-version-system-settings.jpeg
-[7]:https://www.gnome.org/
-[8]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2013/03/checking-ubuntu-version-gui.jpeg
-[9]:https://itsfoss.com/display-linux-logo-in-ascii/
-[10]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2013/03/ubuntu-system-information-terminal-800x400.jpeg
diff --git a/sources/tech/20180510 Splicing the Cloud Native Stack, One Floor at a Time.md b/sources/tech/20180510 Splicing the Cloud Native Stack, One Floor at a Time.md
deleted file mode 100644
index 6515b3e193..0000000000
--- a/sources/tech/20180510 Splicing the Cloud Native Stack, One Floor at a Time.md
+++ /dev/null
@@ -1,174 +0,0 @@
-Splicing the Cloud Native Stack, One Floor at a Time
-======
-At Packet, our value (automated infrastructure) is super fundamental. As such, we spend an enormous amount of time looking up at the players and trends in all the ecosystems above us - as well as the very few below!
-
-It’s easy to get confused, or simply lose track, when swimming deep in the oceans of any ecosystem. I know this for a fact because when I started at Packet last year, my English degree from Bryn Mawr didn’t quite come with a Kubernetes certification. :)
-
-Due to its super fast evolution and massive impact, the cloud native ecosystem defies precedent. It seems that every time you blink, entirely new technologies (not to mention all of the associated logos) have become relevant...or at least interesting. Like many others, I’ve relied on the CNCF’s ubiquitous “[Cloud Native Landscape][1]” as a touchstone as I got to know the space. However, if there is one element that defines ecosystems, it is the people that contribute to and steer them.
-
-That’s why, when we were walking back to the office one cold December afternoon, we hit upon a creative way to explain “cloud native” to an investor, whose eyes were obviously glazing over as we talked about the nuances that distinguished Cilium from Aporeto, and why everything from CoreDNS and Spiffe to Digital Rebar and Fission were interesting in their own right.
-
-Looking up at our narrow 13 story office building in the shadow of the new World Trade Center, we hit on an idea that took us down an artistic rabbit hole: why not draw it?
-
-![][2]
-
-And thus began our journey to splice the Cloud Native Stack, one floor at a time. Let’s walk through it together and we can give you the “guaranteed to be outdated tomorrow” down low.
-
-[[View a High Resolution JPG][3]] or email us to request a copy.
-
-### Starting at the Very Bottom
-
-As we started to put pen to paper, we knew we wanted to shine a light on parts of the stack that we interact with on a daily basis, but that is largely invisible to users further up: hardware. And like any good secret lab investing in the next great (usually proprietary) thing, we thought the basement was the perfect spot.
-
-From the well established giants of the space like Intel, AMD and Huawei (rumor has it they employ nearly 80,000 engineers!), to more niche players like Mellanox, the hardware ecosystem is on fire. In fact, we may be entering a Golden Age of hardware, as billions of dollars are poured into upstarts hacking on new offloads, GPU’s, custom co-processors.
-
-The famous software trailblazer Alan Kay said over 25 years ago: “People who are really serious about software should make their own hardware.” Good call Alan!
-
-### The Cloud is About Capital
-
-As our CEO Zac Smith has told me many times: it’s all about the money. And not just about making it, but spending it! In the cloud, it takes billions of dollars of capital to make computers show up in data centers so that developers can consume them with software. In other words:
-
-
-![][4]
-
-We thought the best place for “The Bank” (e.g. the lenders and investors that make this cloud fly) was the ground floor. So we transformed our lobby into the Banker’s Cafe, complete with a wheel of fortune for all of us out there playing the startup game.
-
-![][5]
-
-### The Ping and Power
-
-If the money is the grease, then the engine that consumes much of the fuel is the datacenter providers and the networks that connect them. We call them “power” and “ping”.
-
-From top of mind names like Equinix and edge upstarts like Vapor.io, to the “pipes” that Verizon, Crown Castle and others literally put in the ground (or on the ocean floor), this is a part of the stack that we all rely upon but rarely see in person.
-
-Since we spend a lot of time looking at datacenters and connectivity, one thing to note is that this space is changing quite rapidly, especially as 5G arrives in earnest and certain workloads start to depend on less centralized infrastructure.
-
-The edge is coming y’all! :-)
-
-![][6]
-
-### Hey, It's Infrastructure!
-
-Sitting on top of “ping” and “power” is the floor we lovingly call “processors”. This is where our magic happens - we turn the innovation and physical investments from down below into something at the end of an API.
-
-Since this is a NYC building, we kept the cloud providers here fairly NYC centric. That’s why you see Sammy the Shark (of Digital Ocean lineage) and a nod to Google over in the “meet me” room.
-
-As you’ll see, this scene is pretty physical. Racking and stacking, as it were. While we love our facilities manager in EWR1 (Michael Pedrazzini), we are working hard to remove as much of this manual labor as possible. PhD’s in cabling are hard to come by, after all.
-
-![][7]
-
-### Provisioning
-
-One floor up, layered on top of infrastructure, is provisioning. This is one of our favorite spots, which years ago we might have called “config management.” But now it’s all about immutable infrastructure and automation from the start: Terraform, Ansible, Quay.io and the like. You can tell that software is working its way down the stack, eh?
-
-Kelsey Hightower noted recently “it’s an exciting time to be in boring infrastructure.” I don’t think he meant the physical part (although we think it’s pretty dope), but as software continues to hack on all layers of the stack, you can guarantee a wild ride.
-
-![][8]
-
-### Operating Systems
-
-With provisioning in place, we move to the operating system layer. This is where we get to start poking fun at some of our favorite folks as well: note Brian Redbeard’s above average yoga pose. :)
-
-Packet offers eleven major operating systems for our clients to choose from, including some that you see in this illustration: Ubuntu, CoreOS, FreeBSD, Suse, and various Red Hat offerings. More and more, we see folks putting their opinion on this layer: from custom kernels and golden images of their favorite distros for immutable deploys, to projects like NixOS and LinuxKit.
-
-![][9]
-
-### Run Time
-
-We had to have fun with this, so we placed the runtime in the gym, with a championship match between CoreOS-sponsored rkt and Docker’s containerd. Either way the CNCF wins!
-
-We felt the fast-evolving storage ecosystem deserved some lockers. What’s fun about the storage aspect is the number of new players trying to conquer the challenging issue of persistence, as well as performance and flexibility. As they say: storage is just plain hard.
-
-![][10]
-
-### Orchestration
-
-The orchestration layer has been all about Kubernetes this past year, so we took one of its most famous evangelists (Kelsey Hightower) and featured him in this rather odd meetup scene. We have some major Nomad fans on our team, and there is just no way to consider the cloud native space without the impact of Docker and its toolset.
-
-While workload orchestration applications are fairly high up our stack, we see all kinds of evidence for these powerful tools are starting to look way down the stack to help users take advantage of GPU’s and other specialty hardware. Stay tuned - we’re in the early days of the container revolution!
-
-![][11]
-
-### Platforms
-
-This is one of our favorite layers of the stack, because there is so much craft in how each platform helps users accomplish what they really want to do (which, by the way, isn’t run containers but run applications!). From Rancher and Kontena, to Tectonic and Redshift to totally different approaches like Cycle.io and Flynn.io - we’re always thrilled to see how each of these projects servers users differently.
-
-The main takeaway: these platforms are helping to translate all of the various, fast-moving parts of the cloud native ecosystem to users. It’s great watching what they each come up with!
-
-![][12]
-
-### Security
-
-When it comes to security, it’s been a busy year! We tried to represent some of the more famous attacks and illustrate how various tools are trying to help protect us as workloads become highly distributed and portable (while at the same time, attackers become ever more resourceful).
-
-We see a strong movement towards trustless environments (see Aporeto) and low level security (Cilium), as well as tried and true approaches at the network level like Tigera. No matter your approach, it’s good to remember: This is definitely not fine. :0
-
-![][13]
-
-### Apps
-
-How to represent the huge, vast, limitless ecosystem of applications? In this case, it was easy: stay close to NYC and pick our favorites. ;) From the Postgres “elephant in the room” and the Timescale clock, to the sneaky ScyllaDB trash and the chillin’ Travis dude - we had fun putting this slice together.
-
-One thing that surprised us: how few people noticed the guy taking a photocopy of his rear end. I guess it’s just not that common to have a photocopy machine anymore?!?
-
-![][14]
-
-### Observability
-
-As our workloads start moving all over the place, and the scale gets gigantic, there is nothing quite as comforting as a really good Grafana dashboard, or that handy Datadog agent. As complexity increases, the “SRE” generation are starting to rely ever more on alerting and other intelligence events to help us make sense of what’s going on, and work towards increasingly self-healing infrastructure and applications.
-
-It will be interesting to see what kind of logos make their way into this floor over the coming months and years...maybe some AI, blockchain, ML powered dashboards? :-)
-
-![][15]
-
-### Traffic Management
-
-People tend to think that the internet “just works” but in reality, we’re kind of surprised it works at all. I mean, a loose connection of disparate networks at massive scale - you have to be joking!?
-
-One reason it all sticks together is traffic management, DNS and the like. More and more, these players are helping to make the interest both faster and safer, as well as more resilient. We’re especially excited to see upstarts like Fly.io and NS1 competing against well established players, and watching the entire ecosystem improve as a result. Keep rockin’ it y’all!
-
-![][16]
-
-### Users
-
-What good is a technology stack if you don’t have fantastic users? Granted, they sit on top of a massive stack of innovation, but in the cloud native world they do more than just consume: they create and contribute. From massive contributions like Kubernetes to more incremental (but equally important) aspects, what we’re all a part of is really quite special.
-
-Many of the users lounging on our rooftop deck, like Ticketmaster and the New York Times, are not mere upstarts: these are organizations that have embraced a new way of deploying and managing their applications, and their own users are reaping the rewards.
-
-![][17]
-
-### Last but not Least, the Adult Supervision!
-
-In previous ecosystems, foundations have played a more passive “behind the scenes” role. Not the CNCF! Their goal of building a robust cloud native ecosystem has been supercharged by the incredible popularity of the movement - and they’ve not only caught up but led the way.
-
-From rock solid governance and a thoughtful group of projects, to outreach like the CNCF Landscape, CNCF Cross Cloud CI, Kubernetes Certification, and Speakers Bureau - the CNCF is way more than “just” the ever popular KubeCon + CloudNativeCon.
-
---------------------------------------------------------------------------------
-
-via: https://www.packet.net/blog/splicing-the-cloud-native-stack/
-
-作者:[Zoe Allen][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://www.packet.net/about/zoe-allen/
-[1]:https://landscape.cncf.io/landscape=cloud
-[2]:https://assets.packet.net/media/images/PIFg-30.vesey.street.ny.jpg
-[3]:https://www.dropbox.com/s/ujxk3mw6qyhmway/Packet_Cloud_Native_Building_Stack.jpg?dl=0
-[4]:https://assets.packet.net/media/images/3vVx-there.is.no.cloud.jpg
-[5]:https://assets.packet.net/media/images/X0b9-the.bank.jpg
-[6]:https://assets.packet.net/media/images/2Etm-ping.and.power.jpg
-[7]:https://assets.packet.net/media/images/C800-infrastructure.jpg
-[8]:https://assets.packet.net/media/images/0V4O-provisioning.jpg
-[9]:https://assets.packet.net/media/images/eMYp-operating.system.jpg
-[10]:https://assets.packet.net/media/images/9BII-run.time.jpg
-[11]:https://assets.packet.net/media/images/njak-orchestration.jpg
-[12]:https://assets.packet.net/media/images/1QUS-platforms.jpg
-[13]:https://assets.packet.net/media/images/TeS9-security.jpg
-[14]:https://assets.packet.net/media/images/SFgF-apps.jpg
-[15]:https://assets.packet.net/media/images/SXoj-observability.jpg
-[16]:https://assets.packet.net/media/images/tKhf-traffic.management.jpg
-[17]:https://assets.packet.net/media/images/7cpe-users.jpg
diff --git a/sources/tech/20180514 Tuptime - A Tool To Report The Historical Uptime Of Linux System.md b/sources/tech/20180514 Tuptime - A Tool To Report The Historical Uptime Of Linux System.md
new file mode 100644
index 0000000000..d079dd19af
--- /dev/null
+++ b/sources/tech/20180514 Tuptime - A Tool To Report The Historical Uptime Of Linux System.md
@@ -0,0 +1,330 @@
+Tuptime - A Tool To Report The Historical Uptime Of Linux System
+======
+Beginning of this month we written an article about system uptime that helps user to check how long your Linux system has been running without downtime? when the system is up and what date. This can be done using 11 methods.
+
+uptime is one of the very famous commands, which everyone use when there is a requirement to check the Linux server uptime.
+
+But it won’t shows historical and statistical running time of Linux system, that’s why tuptime is came to picture.
+
+server uptime is very important when the server running with critical applications such as online portals.
+
+**Suggested Read :** [11 Methods To Find System/Server Uptime In Linux][1]
+
+### What Is tuptime?
+
+[Tuptime][2] is a tool for report the historical and statistical running time of the system, keeping it between restarts. Like uptime command but with more interesting output.
+
+### tuptime Features
+
+ * Count system startups
+ * Register first boot time (a.k.a. installation time)
+ * Count nicely and accidentally shutdowns
+ * Uptime and downtime percentage since first boot time
+ * Accumulated system uptime, downtime and total
+ * Largest, shortest and average uptime and downtime
+ * Current uptime
+ * Print formatted table or list with most of the previous values
+ * Register used kernels
+ * Narrow reports since and/or until a given startup or timestamp
+ * Reports in csv
+
+
+
+### Prerequisites
+
+Make sure your system should have installed Python3 as a prerequisites. If no, install it using your distribution package manager.
+
+**Suggested Read :** [3 Methods To Install Latest Python3 Package On CentOS 6 System][3]
+
+### How To Install tuptime
+
+Few distributions offer tuptime package but it may be bit older version. I would advise you to install latest available version to avail all the features using the below method.
+
+Clone tuptime repository from github.
+```
+# git clone https://github.com/rfrail3/tuptime.git
+
+```
+
+Copy executable file from `tuptime/src/tuptime` to `/usr/bin/` and assign 755 permission.
+```
+# cp tuptime/src/tuptime /usr/bin/tuptime
+# chmod 755 /usr/bin/tuptime
+
+```
+
+All scripts, units and related files are provided inside this repo so, copy and past the necessary files in the appropriate location to get full functionality of tuptime utility.
+
+Add tuptime user because it doesn’t run as a daemon, at least, it only need execution when the init manager startup and shutdown the system.
+```
+# useradd -d /var/lib/tuptime -s /bin/sh tuptime
+
+```
+
+Change owner of the db file.
+```
+# chown -R tuptime:tuptime /var/lib/tuptime
+
+```
+
+Copy cron file from `tuptime/src/tuptime` to `/usr/bin/` and assign 644 permission.
+```
+# cp tuptime/src/cron.d/tuptime /etc/cron.d/tuptime
+# chmod 644 /etc/cron.d/tuptime
+
+```
+
+Add system service file based on your system initsystem. Use the below command to check if your system is running with systemd or init.
+```
+# ps -p 1
+ PID TTY TIME CMD
+ 1 ? 00:00:03 systemd
+
+# ps -p 1
+ PID TTY TIME CMD
+ 1 ? 00:00:00 init
+
+```
+
+If is a system with systemd, copy service file and enable it.
+```
+# cp tuptime/src/systemd/tuptime.service /lib/systemd/system/
+# chmod 644 /lib/systemd/system/tuptime.service
+# systemctl enable tuptime.service
+
+```
+
+If have upstart system, copy the file:
+```
+# cp tuptime/src/init.d/redhat/tuptime /etc/init.d/tuptime
+# chmod 755 /etc/init.d/tuptime
+# chkconfig --add tuptime
+# chkconfig tuptime on
+
+```
+
+If have init system, copy the file:
+```
+# cp tuptime/src/init.d/debian/tuptime /etc/init.d/tuptime
+# chmod 755 /etc/init.d/tuptime
+# update-rc.d tuptime defaults
+# /etc/init.d/tuptime start
+
+```
+
+### How To Use tuptime
+
+Make sure you should run the command with a privileged user. Intially you will get output similar to this.
+```
+# tuptime
+System startups: 1 since 02:48:00 AM 04/12/2018
+System shutdowns: 0 ok - 0 bad
+System uptime: 100.0 % - 26 days, 5 hours, 31 minutes and 52 seconds
+System downtime: 0.0 % - 0 seconds
+System life: 26 days, 5 hours, 31 minutes and 52 seconds
+
+Largest uptime: 26 days, 5 hours, 31 minutes and 52 seconds from 02:48:00 AM 04/12/2018
+Shortest uptime: 26 days, 5 hours, 31 minutes and 52 seconds from 02:48:00 AM 04/12/2018
+Average uptime: 26 days, 5 hours, 31 minutes and 52 seconds
+
+Largest downtime: 0 seconds
+Shortest downtime: 0 seconds
+Average downtime: 0 seconds
+
+Current uptime: 26 days, 5 hours, 31 minutes and 52 seconds since 02:48:00 AM 04/12/2018
+
+```
+
+### Details:
+
+ * **`System startups:`** Total number of system startups from since to until date. Until is joined if is used in a narrow range.
+ * **`System shutdowns:`** Total number of shutdowns done correctly or incorrectly. The separator usually points to the state of last shutdown () bad.
+ * **`System uptime:`** Percentage of uptime and time counter.
+ * **`System downtime:`** Percentage of downtime and time counter.
+ * **`System life:`** Time counter since first startup date until last.
+ * **`Largest/Shortest uptime:`** Time counter and date with the largest/shortest uptime register.
+ * **`Largest/Shortest downtime:`** Time counter and date with the largest/shortest downtime register.
+ * **`Average uptime/downtime:`** Time counter with the average time.
+ * **`Current uptime:`** Actual time counter and date since registered boot date.
+
+
+
+If you do the same a few days after some reboot, the output may will be more similar to this.
+```
+# tuptime
+System startups: 3 since 02:48:00 AM 04/12/2018
+System shutdowns: 0 ok -> 2 bad
+System uptime: 97.0 % - 28 days, 4 hours, 6 minutes and 0 seconds
+System downtime: 3.0 % - 20 hours, 54 minutes and 22 seconds
+System life: 29 days, 1 hour, 0 minutes and 23 seconds
+
+Largest uptime: 26 days, 5 hours, 32 minutes and 57 seconds from 02:48:00 AM 04/12/2018
+Shortest uptime: 1 hour, 31 minutes and 12 seconds from 02:17:11 AM 05/11/2018
+Average uptime: 9 days, 9 hours, 22 minutes and 0 seconds
+
+Largest downtime: 20 hours, 51 minutes and 58 seconds from 08:20:57 AM 05/08/2018
+Shortest downtime: 2 minutes and 24 seconds from 02:14:47 AM 05/11/2018
+Average downtime: 10 hours, 27 minutes and 11 seconds
+
+Current uptime: 1 hour, 31 minutes and 12 seconds since 02:17:11 AM 05/11/2018
+
+```
+
+Enumerate as table each startup number, startup date, uptime, shutdown date, end status and downtime. Multiple order options can be combined together.
+```
+# tuptime -t
+No. Startup Date Uptime Shutdown Date End Downtime
+
+1 02:48:00 AM 04/12/2018 26 days, 5 hours, 32 minutes and 57 seconds 08:20:57 AM 05/08/2018 BAD 20 hours, 51 minutes and 58 seconds
+2 05:12:55 AM 05/09/2018 1 day, 21 hours, 1 minute and 52 seconds 02:14:47 AM 05/11/2018 BAD 2 minutes and 24 seconds
+3 02:17:11 AM 05/11/2018 1 hour, 34 minutes and 33 seconds
+
+```
+
+Enumerate as list each startup number, startup date, uptime, shutdown date, end status and offtime. Multiple order options can be combined together.
+```
+# tuptime -l
+Startup: 1 at 02:48:00 AM 04/12/2018
+Uptime: 26 days, 5 hours, 32 minutes and 57 seconds
+Shutdown: BAD at 08:20:57 AM 05/08/2018
+Downtime: 20 hours, 51 minutes and 58 seconds
+
+Startup: 2 at 05:12:55 AM 05/09/2018
+Uptime: 1 day, 21 hours, 1 minute and 52 seconds
+Shutdown: BAD at 02:14:47 AM 05/11/2018
+Downtime: 2 minutes and 24 seconds
+
+Startup: 3 at 02:17:11 AM 05/11/2018
+Uptime: 1 hour, 34 minutes and 36 seconds
+
+```
+
+To print kernel information with tuptime output.
+```
+# tuptime -k
+System startups: 3 since 02:48:00 AM 04/12/2018
+System shutdowns: 0 ok -> 2 bad
+System uptime: 97.0 % - 28 days, 4 hours, 11 minutes and 25 seconds
+System downtime: 3.0 % - 20 hours, 54 minutes and 22 seconds
+System life: 29 days, 1 hour, 5 minutes and 47 seconds
+System kernels: 1
+
+Largest uptime: 26 days, 5 hours, 32 minutes and 57 seconds from 02:48:00 AM 04/12/2018
+...with kernel: Linux-2.6.32-696.23.1.el6.x86_64-x86_64-with-centos-6.9-Final
+Shortest uptime: 1 hour, 36 minutes and 36 seconds from 02:17:11 AM 05/11/2018
+...with kernel: Linux-2.6.32-696.23.1.el6.x86_64-x86_64-with-centos-6.9-Final
+Average uptime: 9 days, 9 hours, 23 minutes and 48 seconds
+
+Largest downtime: 20 hours, 51 minutes and 58 seconds from 08:20:57 AM 05/08/2018
+...with kernel: Linux-2.6.32-696.23.1.el6.x86_64-x86_64-with-centos-6.9-Final
+Shortest downtime: 2 minutes and 24 seconds from 02:14:47 AM 05/11/2018
+...with kernel: Linux-2.6.32-696.23.1.el6.x86_64-x86_64-with-centos-6.9-Final
+Average downtime: 10 hours, 27 minutes and 11 seconds
+
+Current uptime: 1 hour, 36 minutes and 36 seconds since 02:17:11 AM 05/11/2018
+...with kernel: Linux-2.6.32-696.23.1.el6.x86_64-x86_64-with-centos-6.9-Final
+
+```
+
+Change the date format. By default it’s printed based on system locales.
+```
+# tuptime -d %d/%m/%y %H:%M:%S
+System startups: 3 since 12/04/18
+System shutdowns: 0 ok -> 2 bad
+System uptime: 97.0 % - 28 days, 4 hours, 15 minutes and 18 seconds
+System downtime: 3.0 % - 20 hours, 54 minutes and 22 seconds
+System life: 29 days, 1 hour, 9 minutes and 41 seconds
+
+Largest uptime: 26 days, 5 hours, 32 minutes and 57 seconds from 12/04/18
+Shortest uptime: 1 hour, 40 minutes and 30 seconds from 11/05/18
+Average uptime: 9 days, 9 hours, 25 minutes and 6 seconds
+
+Largest downtime: 20 hours, 51 minutes and 58 seconds from 08/05/18
+Shortest downtime: 2 minutes and 24 seconds from 11/05/18
+Average downtime: 10 hours, 27 minutes and 11 seconds
+
+Current uptime: 1 hour, 40 minutes and 30 seconds since 11/05/18
+
+```
+
+Print information about the internals of tuptime. It’s good for debugging how it gets the variables.
+```
+# tuptime -v
+INFO:Arguments: {'endst': 0, 'seconds': None, 'table': False, 'csv': False, 'ts': None, 'silent': False, 'order': False, 'since': 0, 'kernel': False, 'reverse': False, 'until': 0, 'db_file': '/var/lib/tuptime/tuptime.db', 'lst': False, 'tu': None, 'date_format': '%X %x', 'update': True}
+INFO:Linux system
+INFO:uptime = 5773.54
+INFO:btime = 1526019431
+INFO:kernel = Linux-2.6.32-696.23.1.el6.x86_64-x86_64-with-centos-6.9-Final
+INFO:Execution user = 0
+INFO:Directory exists = /var/lib/tuptime
+INFO:DB file exists = /var/lib/tuptime/tuptime.db
+INFO:Last btime from db = 1526019431
+INFO:Last uptime from db = 5676.04
+INFO:Drift over btime = 0
+INFO:System wasn't restarted. Updating db values...
+System startups: 3 since 02:48:00 AM 04/12/2018
+System shutdowns: 0 ok -> 2 bad
+System uptime: 97.0 % - 28 days, 4 hours, 11 minutes and 2 seconds
+System downtime: 3.0 % - 20 hours, 54 minutes and 22 seconds
+System life: 29 days, 1 hour, 5 minutes and 25 seconds
+
+Largest uptime: 26 days, 5 hours, 32 minutes and 57 seconds from 02:48:00 AM 04/12/2018
+Shortest uptime: 1 hour, 36 minutes and 14 seconds from 02:17:11 AM 05/11/2018
+Average uptime: 9 days, 9 hours, 23 minutes and 41 seconds
+
+Largest downtime: 20 hours, 51 minutes and 58 seconds from 08:20:57 AM 05/08/2018
+Shortest downtime: 2 minutes and 24 seconds from 02:14:47 AM 05/11/2018
+Average downtime: 10 hours, 27 minutes and 11 seconds
+
+Current uptime: 1 hour, 36 minutes and 14 seconds since 02:17:11 AM 05/11/2018
+
+```
+
+Print a quick reference of the command line parameters.
+```
+# tuptime -h
+Usage: tuptime [options]
+
+Options:
+ -h, --help show this help message and exit
+ -c, --csv csv output
+ -d DATE_FORMAT, --date=DATE_FORMAT
+ date format output
+ -f FILE, --filedb=FILE
+ database file
+ -g, --graceful register a gracefully shutdown
+ -k, --kernel print kernel information
+ -l, --list enumerate system life as list
+ -n, --noup avoid update values
+ -o TYPE, --order=TYPE
+ order enumerate by []
+ -r, --reverse reverse order
+ -s, --seconds output time in seconds and epoch
+ -S SINCE, --since=SINCE
+ restric since this register number
+ -t, --table enumerate system life as table
+ --tsince=TIMESTAMP restrict since this epoch timestamp
+ --tuntil=TIMESTAMP restrict until this epoch timestamp
+ -U UNTIL, --until=UNTIL
+ restrict until this register number
+ -v, --verbose verbose output
+ -V, --version show version
+ -x, --silent update values into db without output
+
+```
+
+--------------------------------------------------------------------------------
+
+via: https://www.2daygeek.com/tuptime-a-tool-to-report-the-historical-and-statistical-running-time-of-linux-system/
+
+作者:[Prakash Subramanian][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://www.2daygeek.com/author/prakash/
+[1]:https://www.2daygeek.com/11-methods-to-find-check-system-server-uptime-in-linux/
+[2]:https://github.com/rfrail3/tuptime/
+[3]:https://www.2daygeek.com/3-methods-to-install-latest-python3-package-on-centos-6-system/
diff --git a/sources/tech/20180515 Give Your Linux Desktop a Stunning Makeover With Xenlism Themes.md b/sources/tech/20180515 Give Your Linux Desktop a Stunning Makeover With Xenlism Themes.md
deleted file mode 100644
index f76a483199..0000000000
--- a/sources/tech/20180515 Give Your Linux Desktop a Stunning Makeover With Xenlism Themes.md
+++ /dev/null
@@ -1,92 +0,0 @@
-Give Your Linux Desktop a Stunning Makeover With Xenlism Themes
-============================================================
-
-
- _Brief: Xenlism theme pack provides an aesthetically pleasing GTK theme, colorful icons, and minimalist wallpapers to transform your Linux desktop into an eye-catching setup._
-
-It’s not every day that I dedicate an entire article to a theme unless I find something really awesome. I used to cover themes and icons regularly. But lately, I preferred having lists of [best GTK themes][6] and icon themes. This is more convenient for me and for you as well as you get to see many beautiful themes in one place.
-
-After [Pop OS theme][7] suit, Xenlism is another theme that has left me awestruck by its look.
-
-
-
-Xenlism GTK theme is based on the Arc theme, an inspiration behind so many themes these days. The GTK theme provides Windows buttons similar to macOS which I neither like nor dislike. The GTK theme has a flat, minimalist layout and I like that.
-
-There are two icon themes in the Xenlism suite. Xenlism Wildfire is an old one and had already made to our list of [best icon themes][8].
-
-
-Xenlism Wildfire Icons
-
-Xenlsim Storm is the relatively new icon theme but is equally beautiful.
-
-
-Xenlism Storm Icons
-
-Xenlism themes are open source under GPL license.
-
-### How to install Xenlism theme pack on Ubuntu 18.04
-
-Xenlism dev provides an easier way of installing the theme pack through a PPA. Though the PPA is available for Ubuntu 16.04, I found the GTK theme wasn’t working with Unity. It works fine with the GNOME desktop in Ubuntu 18.04.
-
-Open a terminal (Ctrl+Alt+T) and use the following commands one by one:
-
-```
-sudo add-apt-repository ppa:xenatt/xenlism
-sudo apt update
-```
-
-This PPA offers four packages:
-
-* xenlism-finewalls: for a set of wallpapers that will be available directly in the wallpaper section of Ubuntu. One of the wallpapers has been used in the screenshot.
-
-* xenlism-minimalism-theme: GTK theme
-
-* xenlism-storm: an icon theme (see previous screenshots)
-
-* xenlism-wildfire-icon-theme: another icon theme with several color variants (folder colors get changed in the variants)
-
-You can decide on your own what theme component you want to install. Personally, I don’t see any harm in installing all the components.
-
-```
-sudo apt install xenlism-minimalism-theme xenlism-storm-icon-theme xenlism-wildfire-icon-theme xenlism-finewalls
-```
-
-You can use GNOME Tweaks for changing the theme and icons. If you are not familiar with the procedure already, I suggest reading this tutorial to learn [how to install themes in Ubuntu 18.04 GNOME][9].
-
-### Getting Xenlism themes in other Linux distributions
-
-You can install Xenlism themes on other Linux distributions as well. Installation instructions for various Linux distributions can be found on its website:
-
-[Install Xenlism Themes][10]
-
-### What do you think?
-
-I know not everyone would agree with me but I loved this theme. I think you are going to see the glimpse of Xenlism theme in the screenshots in future tutorials on It’s FOSS.
-
-Did you like Xenlism theme? If not, what theme do you like the most? Share your opinion in the comment section below.
-
-#### 关于作者
-
-I am a professional software developer, and founder of It's FOSS. I am an avid Linux lover and Open Source enthusiast. I use Ubuntu and believe in sharing knowledge. Apart from Linux, I love classic detective mysteries. I'm a huge fan of Agatha Christie's work.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/xenlism-theme/
-
-作者:[Abhishek Prakash ][a]
-译者:[译者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/author/abhishek/
-[2]:https://itsfoss.com/xenlism-theme/#comments
-[3]:https://itsfoss.com/category/desktop/
-[4]:https://itsfoss.com/tag/themes/
-[5]:https://itsfoss.com/tag/xenlism/
-[6]:https://itsfoss.com/best-gtk-themes/
-[7]:https://itsfoss.com/pop-icon-gtk-theme-ubuntu/
-[8]:https://itsfoss.com/best-icon-themes-ubuntu-16-04/
-[9]:https://itsfoss.com/install-themes-ubuntu/
-[10]:http://xenlism.github.io/minimalism/#install
diff --git a/sources/tech/20180516 Manipulating Directories in Linux.md b/sources/tech/20180516 Manipulating Directories in Linux.md
deleted file mode 100644
index 9c6df23e43..0000000000
--- a/sources/tech/20180516 Manipulating Directories in Linux.md
+++ /dev/null
@@ -1,182 +0,0 @@
-Manipulating Directories in Linux
-======
-
-
-
-If you are new to this series (and to Linux), [take a look at our first installment][1]. In that article, we worked our way through the tree-like structure of the Linux filesystem, or more precisely, the File Hierarchy Standard. I recommend reading through it to make sure you understand what you can and cannot safely touch. Because this time around, I’ll show how to get all touchy-feely with your directories.
-
-### Making Directories
-
-Let's get creative before getting destructive, though. To begin, open a terminal window and use `mkdir` to create a new directory like this:
-```
-mkdir
-
-```
-
-If you just put the directory name, the directory will appear hanging off the directory you are currently in. If you just opened a terminal, that will be your home directory. In a case like this, we say the directory will be created _relative_ to your current position:
-```
-$ pwd #This tells you where you are now -- see our first tutorial
-/home/
-$ mkdir newdirectory #Creates /home//newdirectory
-
-```
-
-(Note that you do not have to type the text following the `#`. Text following the pound symbol `#` is considered a comment and is used to explain what is going on. It is ignored by the shell).
-
-You can create a directory within an existing directory hanging off your current location by specifying it in the command line:
-```
-mkdir Documents/Letters
-
-```
-
-Will create the _Letters_ directory within the _Documents_ directory.
-
-You can also create a directory above where you are by using `..` in the path. Say you move into the _Documents/Letters/_ directory you just created and you want to create a _Documents/Memos/_ directory. You can do:
-```
-cd Documents/Letters # Move into your recently created Letters/ directory
-mkdir ../Memos
-
-```
-
-Again, all of the above is done relative to you current position. This is called using a _relative path_.
-
-You can also use an _absolute path_ to directories: This means telling `mkdir` where to put your directory in relation to the root (`/`) directory:
-```
-mkdir /home//Documents/Letters
-
-```
-
-Change `` to your user name in the command above and it will be equivalent to executing `mkdir Documents/Letters` from your home directory, except that it will work from wherever you are located in the directory tree.
-
-As a side note, regardless of whether you use a relative or an absolute path, if the command is successful, `mkdir` will create the directory silently, without any apparent feedback whatsoever. Only if there is some sort of trouble will `mkdir` print some feedback after you hit _[Enter]_.
-
-As with most other command-line tools, `mkdir` comes with several interesting options. The `-p` option is particularly useful, as it lets you create directories within directories within directories, even if none exist. To create, for example, a directory for letters to your Mom within _Documents/_ , you could do:
-```
-mkdir -p Documents/Letters/Family/Mom
-
-```
-
-And `mkdir` will create the whole branch of directories above _Mom/_ and also the directory _Mom/_ for you, regardless of whether any of the parent directories existed before you issued the command.
-
-You can also create several folders all at once by putting them one after another, separated by spaces:
-```
-mkdir Letters Memos Reports
-
-```
-
-will create the directories _Letters/_ , _Memos/_ and _Reports_ under the current directory.
-
-### In space nobody can hear you scream
-
-... Which brings us to the tricky question of spaces in directory names. Can you use spaces in directory names? Yes, you can. Is it advised you use spaces? No, absolutely not. Spaces make everything more complicated and, potentially, dangerous.
-
-Say you want to create a directory called _letters mom/_. If you didn't know any better, you could type:
-```
-mkdir letters mom
-
-```
-
-But this is WRONG! WRONG! WRONG! As we saw above, this will create two directories, _letters/_ and _mom/_ , but not _letters mom/_.
-
-Agreed that this is a minor annoyance: all you have to do is delete the two directories and start over. No big deal.
-
-But, wait! Deleting directories is where things get dangerous. Imagine you did create _letters mom/_ using a graphical tool, like, say [Dolphin][2] or [Nautilus][3]. If you suddenly decide to delete _letters mom/_ from a terminal, and you have another directory just called _letters/_ under the same directory, and said directory is full of important documents, and you tried this:
-```
-rmdir letters mom
-
-```
-
-You would risk removing _letters/_. I say "risk" because fortunately `rmdir`, the instruction used to remove directories, has a built in safeguard and will warn you if you try to delete a non-empty directory.
-
-However, this:
-```
-rm -Rf letters mom
-
-```
-
-(and this is a pretty standard way of getting rid of directories and their contents) will completely obliterate _letters/_ and will never even tell you what just happened.
-
-The `rm` command is used to delete files and directories. When you use it with the options `-R` (delete _recursively_ ) and `-f` ( _force_ deletion), it will burrow down into a directory and its subdirectories, deleting all the files they contain, then deleting the subdirectories themselves, then it will delete all the files in the top directory and then the directory itself.
-
-`rm -Rf` is an instruction you must handle with extreme care.
-
-My advice is, instead of spaces, use underscores (`_`), but if you still insist on spaces, there are two ways of getting them to work. You can use single or double quotes (`'` or `"`) like so:
-```
-mkdir 'letters mom'
-mkdir "letters dad"
-
-```
-
-Or, you can _escape_ the spaces. Some characters have a special meaning for the shell. Spaces, as you have seen, are used to separate options and arguments on the command line. "Separating options and arguments" falls under the category of "special meaning". When you want the shell to ignore the special meaning of a character, you need to _escape_ it and to escape a character, you put a backslash (`\`) in front of it:
-```
-mkdir letters\ mom
-mkdir letter\ dad
-
-```
-
-There are other special characters that would need escaping, like the apostrophe or single quote (`'`), double quotes (`"`), and the ampersand (`&`):
-```
-mkdir mom\ \&\ dad\'s\ letters
-
-```
-
-I know what you're thinking: If the backslash has a special meaning (to wit, telling the shell it has to escape the next character), that makes it a special character, too. Then, how would you escape the escape character which is `\`?
-
-Turns out, the exact way you escape any other special character:
-```
-mkdir special\\characters
-
-```
-
-will produce a directory called _special\characters_.
-
-Confusing? Of course. That's why you should avoid using special characters, including spaces, in directory names.
-
-For the record, here is a list of special characters you can refer to just in case.
-
-### Things to Remember
-
- * Use `mkdir ` to create a new directory.
- * Use `rmdir ` to delete a directory (only works if it is empty).
- * Use `rm -Rf ` to annihilate a directory -- use with extreme caution.
- * Use a relative path to create directories relative to your current directory: `mkdir newdir.`.
- * Use an absolute path to create directories relative to the root directory (`/`): `mkdir /home//newdir`
- * Use `..` to create a directory in the directory above the current directory: `mkdir ../newdir`
- * You can create several directories all in one go by separating them with spaces on the command line: `mkdir onedir twodir threedir`
- * You can mix and mash relative and absolute paths when creating several directories simultaneously: `mkdir onedir twodir /home//threedir`
- * Using spaces and special characters in directory names guarantees plenty of headaches and heartburn. Don't do it.
-
-
-
-For more information, you can look up the manuals of `mkdir`, `rmdir` and `rm`:
-```
-man mkdir
-man rmdir
-man rm
-
-```
-
-To exit the man pages, press _[q]_.
-
-### Next Time
-
-In the next installment, you'll learn about creating, modifying, and erasing files, as well as everything you need to know about permissions and privileges. See you then!
-
-Learn more about Linux through the free ["Introduction to Linux" ][4]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/learn/2018/5/manipulating-directories-linux
-
-作者:[Paul Brown][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://www.linux.com/users/bro66
-[1]:https://www.linux.com/blog/learn/intro-to-linux/2018/4/linux-filesystem-explained
-[2]:https://userbase.kde.org/Dolphin
-[3]:https://projects-old.gnome.org/nautilus/screenshots.html
-[4]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180522 Free Resources for Securing Your Open Source Code.md b/sources/tech/20180522 Free Resources for Securing Your Open Source Code.md
deleted file mode 100644
index 4a7522ff9f..0000000000
--- a/sources/tech/20180522 Free Resources for Securing Your Open Source Code.md
+++ /dev/null
@@ -1,83 +0,0 @@
-Free Resources for Securing Your Open Source Code
-======
-
-
-
-While the widespread adoption of open source continues at a healthy rate, the recent [2018 Open Source Security and Risk Analysis Report][1] from Black Duck and Synopsys reveals some common concerns and highlights the need for sound security practices. The report examines findings from the anonymized data of over 1,100 commercial codebases with represented Industries from automotive, Big Data, enterprise software, financial services, healthcare, IoT, manufacturing, and more.
-
-The report highlights a massive uptick in open source adoption, with 96 percent of the applications scanned containing open source components. However, the report also includes warnings about existing vulnerabilities. Among the [findings][2]:
-
- * “What is worrisome is that 78 percent of the codebases examined contained at least one open source vulnerability, with an average 64 vulnerabilities per codebase.”
-
- * “Over 54 percent of the vulnerabilities found in audited codebases are considered high-risk vulnerabilities.”
-
- * Seventeen percent of the codebases contained a highly publicized vulnerability such as Heartbleed, Logjam, Freak, Drown, or Poodle.
-
-
-
-
-"The report clearly demonstrates that with the growth in open source use, organizations need to ensure they have the tools to detect vulnerabilities in open source components and manage whatever license compliance their use of open source may require," said Tim Mackey, technical evangelist at Black Duck by Synopsys.
-
-Indeed, with ever more impactful security threats emerging,the need for fluency with security tools and practices has never been more pronounced. Most organizations are aware that network administrators and sysadmins need to have strong security skills, and, in many cases security certifications. [In this article,][3] we explored some of the tools, certifications and practices that many of them wisely embrace.
-
-The Linux Foundation has also made available many informational and educational resources on security. Likewise, the Linux community offers many free resources for specific platforms and tools. For example, The Linux Foundation has published a [Linux workstation security checklist][4] that covers a lot of good ground. Online publications ranging from the [Fedora security guide][5] to the[Securing Debian Manual][6] can also help users protect against vulnerabilities within specific platforms.
-
-The widespread use of cloud platforms such as OpenStack is also stepping up the need for cloud-centric security smarts. According to The Linux Foundation’s[Guide to the Open Cloud][7]: “Security is still a top concern among companies considering moving workloads to the public cloud, according to Gartner, despite a strong track record of security and increased transparency from cloud providers. Rather, security is still an issue largely due to companies’ inexperience and improper use of cloud services.”
-
-For both organizations and individuals, the smallest holes in implementation of routers, firewalls, VPNs, and virtual machines can leave room for big security problems. Here is a collection of free tools that can plug these kinds of holes:
-
- * [Wireshark][8], a packet analyzer
-
- * [KeePass Password Safe][9], a free open source password manager
-
- * [Malwarebytes][10], a free anti-malware and antivirus tool
-
- * [NMAP][11], a powerful security scanner
-
- * [NIKTO][12], an open source web server scanner
-
- * [Ansible][13], a tool for automating secure IT provisioning
-
- * [Metasploit][14], a tool for understanding attack vectors and doing penetration testing
-
-
-
-
-Instructional videos abound for these tools. You’ll find a whole[tutorial series][15] for Metasploit, and [video tutorials][16] for Wireshark. Quite a few free ebooks provide good guidance on security as well. For example, one of the common ways for security threats to invade open source platforms occurs in M&A scenarios, where technology platforms are merged—often without proper open source audits. In an ebook titled [Open Source Audits in Merger and Acquisition Transactions][17], from Ibrahim Haddad and The Linux Foundation, you’ll find an overview of the open source audit process and important considerations for code compliance, preparation, and documentation.
-
-Meanwhile, we’ve[previously covered][18] a free ebook from the editors at[The New Stack][19] called Networking, Security & Storage with Docker & Containers. It covers the latest approaches to secure container networking, as well as native efforts by Docker to create efficient and secure networking practices. The ebook is loaded with best practices for locking down security at scale.
-
-All of these tools and resources, and many more, can go a long way toward preventing security problems, and an ounce of prevention is, as they say, worth a pound of cure. With security breaches continuing, now is an excellent time to look into the many security and compliance resources for open source tools and platforms available. Learn more about security, compliance, and open source project health [here][20].
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/2018/5/free-resources-securing-your-open-source-code
-
-作者:[Sam Dean][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://www.linux.com/users/sam-dean
-[1]:https://www.blackducksoftware.com/open-source-security-risk-analysis-2018
-[2]:https://www.prnewswire.com/news-releases/synopsys-report-finds-majority-of-software-plagued-by-known-vulnerabilities-and-license-conflicts-as-open-source-adoption-soars-300648367.html
-[3]:https://www.linux.com/blog/sysadmin-ebook/2017/8/future-proof-your-sysadmin-career-locking-down-security
-[4]:http://go.linuxfoundation.org/ebook_workstation_security
-[5]:https://docs.fedoraproject.org/en-US/Fedora/19/html/Security_Guide/index.html
-[6]:https://www.debian.org/doc/manuals/securing-debian-howto/index.en.html
-[7]:https://www.linux.com/publications/2016-guide-open-cloud
-[8]:https://www.wireshark.org/
-[9]:http://keepass.info/
-[10]:https://www.malwarebytes.com/
-[11]:http://searchsecurity.techtarget.co.uk/tip/Nmap-tutorial-Nmap-scan-examples-for-vulnerability-discovery
-[12]:https://cirt.net/Nikto2
-[13]:https://www.ansible.com/
-[14]:https://www.metasploit.com/
-[15]:http://www.computerweekly.com/tutorial/The-Metasploit-Framework-Tutorial-PDF-compendium-Your-ready-reckoner
-[16]:https://www.youtube.com/watch?v=TkCSr30UojM
-[17]:https://www.linuxfoundation.org/resources/open-source-audits-merger-acquisition-transactions/
-[18]:https://www.linux.com/news/networking-security-storage-docker-containers-free-ebook-covers-essentials
-[19]:http://thenewstack.io/ebookseries/
-[20]:https://www.linuxfoundation.org/projects/security-compliance/
diff --git a/sources/tech/20180522 How to Run Your Own Git Server.md b/sources/tech/20180522 How to Run Your Own Git Server.md
deleted file mode 100644
index 9a1ee8509a..0000000000
--- a/sources/tech/20180522 How to Run Your Own Git Server.md
+++ /dev/null
@@ -1,233 +0,0 @@
-translating by wyxplus
-How to Run Your Own Git Server
-======
-**Learn how to set up your own Git server in this tutorial from our archives.**
-
-[Git ][1]is a versioning system [developed by Linus Torvalds][2], that is used by millions of users around the globe. Companies like GitHub offer code hosting services based on Git. [According to reports, GitHub, a code hosting site, is the world's largest code hosting service.][3] The company claims that there are 9.2M people collaborating right now across 21.8M repositories on GitHub. Big companies are now moving to GitHub. [Even Google, the search engine giant, is shutting it's own Google Code and moving to GitHub.][4]
-
-### Run your own Git server
-
-GitHub is a great service, however there are some limitations and restrictions, especially if you are an individual or a small player. One of the limitations of GitHub is that the free service doesn’t allow private hosting of the code. [You have to pay a monthly fee of $7 to host 5 private repositories][5], and the expenses go up with more repos.
-
-In cases like these or when you want more control, the best path is to run Git on your own server. Not only do you save costs, you also have more control over your server. In most cases a majority of advanced Linux users already have their own servers and pushing Git on those servers is like ‘free as in beer’.
-
-In this tutorial we are going to talk about two methods of managing your code on your own server. One is running a bare, basic Git server and and the second one is via a GUI tool called [GitLab][6]. For this tutorial I used a fully patched Ubuntu 14.04 LTS server running on a VPS.
-
-### Install Git on your server
-
-In this tutorial we are considering a use-case where we have a remote server and a local server and we will work between these machines. For the sake of simplicity we will call them remote-server and local-server.
-
-First, install Git on both machines. You can install Git from the packages already available via the repos or your distros, or you can do it manually. In this article we will use the simpler method:
-```
-sudo apt-get install git-core
-
-```
-
-Then add a user for Git.
-```
-sudo useradd git
-passwd git
-
-```
-
-In order to ease access to the server let's set-up a password-less ssh login. First create ssh keys on your local machine:
-```
-ssh-keygen -t rsa
-
-```
-
-It will ask you to provide the location for storing the key, just hit Enter to use the default location. The second question will be to provide it with a pass phrase which will be needed to access the remote server. It generates two keys - a public key and a private key. Note down the location of the public key which you will need in the next step.
-
-Now you have to copy these keys to the server so that the two machines can talk to each other. Run the following command on your local machine:
-```
-cat ~/.ssh/id_rsa.pub | ssh git@remote-server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
-
-```
-
-Now ssh into the server and create a project directory for Git. You can use the desired path for the repo.
-
-Then change to this directory:
-```
-cd /home/swapnil/project-1.git
-
-```
-
-Then create an empty repo:
-```
-git init --bare
-Initialized empty Git repository in /home/swapnil/project-1.git
-
-```
-
-We now need to create a Git repo on the local machine.
-```
-mkdir -p /home/swapnil/git/project
-
-```
-
-And change to this directory:
-```
-cd /home/swapnil/git/project
-
-```
-
-Now create the files that you need for the project in this directory. Stay in this directory and initiate git:
-```
-git init
-Initialized empty Git repository in /home/swapnil/git/project
-
-```
-
-Now add files to the repo:
-```
-git add .
-
-```
-
-Now every time you add a file or make changes you have to run the add command above. You also need to write a commit message with every change in a file. The commit message basically tells what changes were made.
-```
-git commit -m "message" -a
-[master (root-commit) 57331ee] message
- 2 files changed, 2 insertions(+)
- create mode 100644 GoT.txt
- create mode 100644 writing.txt
-
-```
-
-In this case I had a file called GoT (Game of Thrones review) and I made some changes, so when I ran the command it specified that changes were made to the file. In the above command '-a' option means commits for all files in the repo. If you made changes to only one you can specify the name of that file instead of using '-a'.
-
-An example:
-```
-git commit -m "message" GoT.txt
-[master e517b10] message
- 1 file changed, 1 insertion(+)
-
-```
-
-Until now we have been working on the local server. Now we have to push these changes to the server so the work is accessible over the Internet and you can collaborate with other team members.
-```
-git remote add origin ssh://git@remote-server/repo->path-on-server..git
-
-```
-
-Now you can push or pull changes between the server and local machine using the 'push' or 'pull' option:
-```
-git push origin master
-
-```
-
-If there are other team members who want to work with the project they need to clone the repo on the server to their local machine:
-```
-git clone git@remote-server:/home/swapnil/project.git
-
-```
-
-Here /home/swapnil/project.git is the project path on the remote server, exchange the values for your own server.
-
-Then change directory on the local machine (exchange project with the name of project on your server):
-```
-cd /project
-
-```
-
-Now they can edit files, write commit change messages and then push them to the server:
-```
-git commit -m 'corrections in GoT.txt story' -a
-And then push changes:
-
-git push origin master
-
-```
-
-I assume this is enough for a new user to get started with Git on their own servers. If you are looking for some GUI tools to manage changes on local machines, you can use GUI tools such as QGit or GitK for Linux.
-
-### Using GitLab
-
-This was a pure command line solution for project owner and collaborator. It's certainly not as easy as using GitHub. Unfortunately, while GitHub is the world's largest code hosting service; its own software is not available for others to use. It's not open source so you can't grab the source code and compile your own GitHub. Unlike WordPress or Drupal you can't download GitHub and run it on your own servers.
-
-As usual in the open source world there is no end to the options. GitLab is a nifty project which does exactly that. It's an open source project which allows users to run a project management system similar to GitHub on their own servers.
-
-You can use GitLab to run a service similar to GitHub for your team members or your company. You can use GitLab to work on private projects before releasing them for public contributions.
-
-GitLab employs the traditional Open Source business model. They have two products: free of cost open source software, which users can install on their own servers, and a hosted service similar to GitHub.
-
-The downloadable version has two editions - the free of cost community edition and the paid enterprise edition. The enterprise edition is based on the community edition but comes with additional features targeted at enterprise customers. It’s more or less similar to what WordPress.org or Wordpress.com offer.
-
-The community edition is highly scalable and can support 25,000 users on a single server or cluster. Some of the features of GitLab include: Git repository management, code reviews, issue tracking, activity feeds, and wikis. It comes with GitLab CI for continuous integration and delivery.
-
-Many VPS providers such as Digital Ocean offer GitLab droplets for users. If you want to run it on your own server, you can install it manually. GitLab offers an Omnibus package for different operating systems. Before we install GitLab, you may want to configure an SMTP email server so that GitLab can push emails as and when needed. They recommend Postfix. So, install Postfix on your server:
-```
-sudo apt-get install postfix
-
-```
-
-During installation of Postfix it will ask you some questions; don't skip them. If you did miss it you can always re-configure it using this command:
-```
-sudo dpkg-reconfigure postfix
-
-```
-
-When you run this command choose "Internet Site" and provide the email ID for the domain which will be used by Gitlab.
-
-In my case I provided it with:
-```
-This e-mail address is being protected from spambots. You need JavaScript enabled to view it
-
-
-```
-
-Use Tab and create a username for postfix. The Next page will ask you to provide a destination for mail.
-
-In the rest of the steps, use the default options. Once Postfix is installed and configured, let's move on to install GitLab.
-
-Download the packages using wget (replace the download link with the [latest packages from here][7]) :
-```
-wget https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.9.4-omnibus.1-1_amd64.deb
-
-```
-
-Then install the package:
-```
-sudo dpkg -i gitlab_7.9.4-omnibus.1-1_amd64.deb
-
-```
-
-Now it's time to configure and start GitLabs.
-```
-sudo gitlab-ctl reconfigure
-
-```
-
-You now need to configure the domain name in the configuration file so you can access GitLab. Open the file.
-```
-nano /etc/gitlab/gitlab.rb
-
-```
-
-In this file edit the 'external_url' and give the server domain. Save the file and then open the newly created GitLab site from a web browser.
-
-By default it creates 'root' as the system admin and uses '5iveL!fe' as the password. Log into the GitLab site and then change the password.
-
-Once the password is changed, log into the site and start managing your project.
-
-GitLab is overflowing with features and options. I will borrow popular lines from the movie, The Matrix: "Unfortunately, no one can be told what all GitLab can do. You have to try it for yourself."
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/learn/how-run-your-own-git-server
-
-作者:[Swapnil Bhartiya][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://www.linux.com/users/arnieswap
-[1]:https://github.com/git/git
-[2]:https://www.linuxfoundation.org/blog/10-years-of-git-an-interview-with-git-creator-linus-torvalds/
-[3]:https://github.com/about/press
-[4]:http://google-opensource.blogspot.com/2015/03/farewell-to-google-code.html
-[5]:https://github.com/pricing
-[6]:https://about.gitlab.com/
-[7]:https://about.gitlab.com/downloads/
diff --git a/sources/tech/20180523 A Set Of Useful Utilities For Debian And Ubuntu Users.md b/sources/tech/20180523 A Set Of Useful Utilities For Debian And Ubuntu Users.md
deleted file mode 100644
index e14f5ac850..0000000000
--- a/sources/tech/20180523 A Set Of Useful Utilities For Debian And Ubuntu Users.md
+++ /dev/null
@@ -1,287 +0,0 @@
-A Set Of Useful Utilities For Debian And Ubuntu Users
-======
-
-
-
-Are you using a Debian-based system? Great! I am here today with a good news for you. Say hello to **“Debian-goodies”** , a collection of useful utilities for Debian-based systems, like Ubuntu, Linux Mint. These set of utilities provides some additional useful commands which are not available by default in the Debian-based systems. Using these tools, the users can find which programs are consuming more disk space, which services need to be restarted after updating the system, search for a file matching a pattern in a package, list the installed packages based on the search string and a lot more. In this brief guide, we will be discussing some useful Debian goodies.
-
-### Debian-goodies – Useful Utilities For Debian And Ubuntu Users
-
-The debian-goodies package is available in the official repositories of Debian and its derivative Ubuntu and other Ubuntu variants such as Linux Mint. To install debian-goodies package, simply run:
-```
-$ sudo apt-get install debian-goodies
-
-```
-
-Debian-goodies has just been installed. Let us go ahead and see some useful utilities.
-
-#### **1. Checkrestart**
-
-Let me start from one of my favorite, the **“checkrestart”** utility. When installing security updates, some running applications might still use the old libraries. In order to apply the security updates completely, you need to find and restart all of them. This is where Checkrestart comes in handy. This utility will find which processes are still using the old versions of libs. You can then restart the services.
-
-To check which daemons need to be restarted after library upgrades, run:
-```
-$ sudo checkrestart
-[sudo] password for sk:
-Found 0 processes using old versions of upgraded files
-
-```
-
-Since I didn’t perform any security updates lately, it shows nothing.
-
-Please note that Checkrestart utility does work well. However, there is a new similar tool named “needrestart” available latest Debian systems. The needrestart is inspired by the checkrestart utility and it does exactly the same job. Needrestart is actively maintained and supports newer technologies such as containers (LXC, Docker).
-
-Here are the features of Needrestart:
-
- * supports (but does not require) systemd
- * binary blacklisting (i.e. display managers)
- * tries to detect pending kernel upgrades
- * tries to detect required restarts of interpreter based daemons (supports Perl, Python, Ruby)
- * fully integrated into apt/dpkg using hooks
-
-
-
-It is available in the default repositories too. so, you can install it using command:
-```
-$ sudo apt-get install needrestart
-
-```
-
-Now you can check the list of daemons need to be restarted after updating your system using command:
-```
-$ sudo needrestart
-Scanning processes...
-Scanning linux images...
-
-Running kernel seems to be up-to-date.
-
-Failed to check for processor microcode upgrades.
-
-No services need to be restarted.
-
-No containers need to be restarted.
-
-No user sessions are running outdated binaries.
-
-```
-
-The good thing is Needrestart works on other Linux distributions too. For example, you can install on Arch Linux and its variants from AUR using any AUR helper programs like below.
-```
-$ yaourt -S needrestart
-
-```
-
-On fedora:
-```
-$ sudo dnf install needrestart
-
-```
-
-#### 2. Check-enhancements
-
-The check-enhancements utility is used to find packages which enhance the installed packages. This utility will list all packages that enhances other packages but are not strictly necessary to run it. You can find enhancements for a single package or all installed installed packages using “-ip” or “–installed-packages” flag.
-
-For example, I am going to list the enhancements for gimp package.
-```
-$ check-enhancements gimp
-gimp => gimp-data: Installed: (none) Candidate: 2.8.22-1
-gimp => gimp-gmic: Installed: (none) Candidate: 1.7.9+zart-4build3
-gimp => gimp-gutenprint: Installed: (none) Candidate: 5.2.13-2
-gimp => gimp-help-ca: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-de: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-el: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-en: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-es: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-fr: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-it: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-ja: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-ko: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-nl: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-nn: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-pt: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-ru: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-sl: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-help-sv: Installed: (none) Candidate: 2.8.2-0.1
-gimp => gimp-plugin-registry: Installed: (none) Candidate: 7.20140602ubuntu3
-gimp => xcftools: Installed: (none) Candidate: 1.0.7-6
-
-```
-
-To list the enhancements for all installed packages, run:
-```
-$ check-enhancements -ip
-autoconf => autoconf-archive: Installed: (none) Candidate: 20170928-2
-btrfs-progs => snapper: Installed: (none) Candidate: 0.5.4-3
-ca-certificates => ca-cacert: Installed: (none) Candidate: 2011.0523-2
-cryptsetup => mandos-client: Installed: (none) Candidate: 1.7.19-1
-dpkg => debsig-verify: Installed: (none) Candidate: 0.18
-[...]
-
-```
-
-#### 3. dgrep
-
-As the name implies, dgrep is used to search all files in specified packages based on the given regex. For instance, I am going to search for files that contains the regex “text” in Vim package.
-```
-$ sudo dgrep "text" vim
-Binary file /usr/bin/vim.tiny matches
-/usr/share/doc/vim-tiny/copyright: that they must include this license text. You can also distribute
-/usr/share/doc/vim-tiny/copyright: include this license text. You are also allowed to include executables
-/usr/share/doc/vim-tiny/copyright: 1) This license text must be included unmodified.
-/usr/share/doc/vim-tiny/copyright: text under a) applies to those changes.
-/usr/share/doc/vim-tiny/copyright: context diff. You can choose what license to use for new code you
-/usr/share/doc/vim-tiny/copyright: context diff will do. The e-mail address to be used is
-/usr/share/doc/vim-tiny/copyright: On Debian systems, the complete text of the GPL version 2 license can be
-[...]
-
-```
-
-The dgrep supports most of grep’s options. Refer the following guide to learn grep commands.
-
-#### 4 dglob
-
-The dglob utility generates a list of package names which match a pattern. For example, find the list of packages that matches the string “vim”.
-```
-$ sudo dglob vim
-vim-tiny:amd64
-vim:amd64
-vim-common:all
-vim-runtime:all
-
-```
-
-By default, dglob will display only the installed packages. If you want to list all packages (installed and not installed), use **-a** flag.
-```
-$ sudo dglob vim -a
-
-```
-
-#### 5. debget
-
-The **debget** utility will download a .deb for a package in APT’s database. Please note that it will only download the given package, not the dependencies.
-```
-$ debget nano
-Get:1 http://in.archive.ubuntu.com/ubuntu bionic/main amd64 nano amd64 2.9.3-2 [231 kB]
-Fetched 231 kB in 2s (113 kB/s)
-
-```
-
-#### 6. dpigs
-
-This is another useful utility in this collection. The **dpigs** utility will find and show you which installed packages occupy the most disk space.
-```
-$ dpigs
-260644 linux-firmware
-167195 linux-modules-extra-4.15.0-20-generic
-75186 linux-headers-4.15.0-20
-64217 linux-modules-4.15.0-20-generic
-55620 snapd
-31376 git
-31070 libicu60
-28420 vim-runtime
-25971 gcc-7
-24349 g++-7
-
-```
-
-As you can see, the linux-firmware packages occupies the most disk space. By default, it will display the **top 10** packages that occupies the most disk space. If you want to display more packages, for example 20, run the following command:
-```
-$ dpigs -n 20
-
-```
-
-#### 7. debman
-
-The **debman** utility allows you to easily view man pages from a binary **.deb** without extracting it. You don’t even need to install the .deb package. The following command displays the man page of nano package.
-```
-$ debman -f nano_2.9.3-2_amd64.deb nano
-
-```
-
-If you don’t have a local copy of the .deb package, use **-p** flag to download and view package’s man page.
-```
-$ debman -p nano nano
-
-```
-
-**Suggested read:**
-
-#### 8. debmany
-
-An installed Debian package has not only a man page, but also includes other files such as acknowledgement, copy right, and read me etc. The **debmany** utility allows you to view and read those files.
-```
-$ debmany vim
-
-```
-
-![][1]
-
-Choose the file you want to view using arrow keys and hit ENTER to view the selected file. Press **q** to go back to the main menu.
-
-If the specified package is not installed, debmany will download it from the APT database and display the man pages. The **dialog** package should be installed to read the man pages.
-
-#### 9. popbugs
-
-If you’re a developer, the **popbugs** utility will be quite useful. It will display a customized release-critical bug list based on packages you use (using popularity-contest data). For those who don’t know, the popularity-contest package sets up a cron job that will periodically anonymously submit to the Debian developers statistics about the most used Debian packages on this system. This information helps Debian make decisions such as which packages should go on the first CD. It also lets Debian improve future versions of the distribution so that the most popular packages are the ones which are installed automatically for new users.
-
-To generate a list of critical bugs and display the result in your default web browser, run:
-```
-$ popbugs
-
-```
-
-Also, you can save the result in a file as shown below.
-```
-$ popbugs --output=bugs.txt
-
-```
-
-#### 10. which-pkg-broke
-
-This command will display all the dependencies of the given package and when each dependency was installed. By using this information, you can easily find which package might have broken another at what time after upgrading the system or a package.
-```
-$ which-pkg-broke vim
-Package has no install time info
-debconf Wed Apr 25 08:08:40 2018
-gcc-8-base:amd64 Wed Apr 25 08:08:41 2018
-libacl1:amd64 Wed Apr 25 08:08:41 2018
-libattr1:amd64 Wed Apr 25 08:08:41 2018
-dpkg Wed Apr 25 08:08:41 2018
-libbz2-1.0:amd64 Wed Apr 25 08:08:41 2018
-libc6:amd64 Wed Apr 25 08:08:42 2018
-libgcc1:amd64 Wed Apr 25 08:08:42 2018
-liblzma5:amd64 Wed Apr 25 08:08:42 2018
-libdb5.3:amd64 Wed Apr 25 08:08:42 2018
-[...]
-
-```
-
-#### 11. dhomepage
-
-The dhomepage utility will display the official website of the given package in your default web browser. For example, the following command will open Vim editor’s home page.
-```
-$ dhomepage vim
-
-```
-
-And, that’s all for now. Debian-goodies is a must-have tool in your arsenal. Even though, we don’t use all those utilities often, they are worth to learn and I am sure they will be really helpful at times.
-
-I hope this was useful. More good stuffs to come. Stay tuned!
-
-Cheers!
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/debian-goodies-a-set-of-useful-utilities-for-debian-and-ubuntu-users/
-
-作者:[SK][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://www.ostechnix.com/author/sk/
-[1]:http://www.ostechnix.com/wp-content/uploads/2018/05/debmany.png
diff --git a/sources/tech/20180524 How CERN Is Using Linux and Open Source.md b/sources/tech/20180524 How CERN Is Using Linux and Open Source.md
deleted file mode 100644
index 958a255997..0000000000
--- a/sources/tech/20180524 How CERN Is Using Linux and Open Source.md
+++ /dev/null
@@ -1,67 +0,0 @@
-How CERN Is Using Linux and Open Source
-============================================================
-
-
->CERN relies on open source technology to handle huge amounts of data generated by the Large Hadron Collider. The ATLAS (shown here) is a general-purpose detector that probes for fundamental particles. (Image courtesy: CERN)[Used with permission][2]
-
-[CERN][3]
-
-[CERN][6] really needs no introduction. Among other things, the European Organization for Nuclear Research created the World Wide Web and the Large Hadron Collider (LHC), the world’s largest particle accelerator, which was used in discovery of the [Higgs boson][7]. Tim Bell, who is responsible for the organization’s IT Operating Systems and Infrastructure group, says the goal of his team is “to provide the compute facility for 13,000 physicists around the world to analyze those collisions, understand what the universe is made of and how it works.”
-
-CERN is conducting hardcore science, especially with the LHC, which [generates massive amounts of data][8] when it’s operational. “CERN currently stores about 200 petabytes of data, with over 10 petabytes of data coming in each month when the accelerator is running. This certainly produces extreme challenges for the computing infrastructure, regarding storing this large amount of data, as well as the having the capability to process it in a reasonable timeframe. It puts pressure on the networking and storage technologies and the ability to deliver an efficient compute framework,” Bell said.
-
-### [tim-bell-cern.png][4]
-
-
-Tim Bell, CERN[Used with permission][1]Swapnil Bhartiya
-
-The scale at which LHC operates and the amount of data it generates pose some serious challenges. But CERN is not new to such problems. Founded in 1954, CERN has been around for about 60 years. “We've always been facing computing challenges that are difficult problems to solve, but we have been working with open source communities to solve them,” Bell said. “Even in the 90s, when we invented the World Wide Web, we were looking to share this with the rest of humanity in order to be able to benefit from the research done at CERN and open source was the right vehicle to do that.”
-
-### Using OpenStack and CentOS
-
-Today, CERN is a heavy user of OpenStack, and Bell is one of the Board Members of the OpenStack Foundation. But CERN predates OpenStack. For several years, they have been using various open source technologies to deliver services through Linux servers.
-
-“Over the past 10 years, we've found that rather than taking our problems ourselves, we find upstream open source communities with which we can work, who are facing similar challenges and then we contribute to those projects rather than inventing everything ourselves and then having to maintain it as well,” said Bell.
-
-A good example is Linux itself. CERN used to be a Red Hat Enterprise Linux customer. But, back in 2004, they worked with Fermilab to build their own Linux distribution called [Scientific Linux][9]. Eventually they realized that, because they were not modifying the kernel, there was no point in spending time spinning up their own distribution; so they migrated to CentOS. Because CentOS is a fully open source and community driven project, CERN could collaborate with the project and contribute to how CentOS is built and distributed.
-
-CERN helps CentOS with infrastructure and they also organize CentOS DoJo at CERN where engineers can get together to improve the CentOS packaging.
-
-In addition to OpenStack and CentOS, CERN is a heavy user of other open source projects, including Puppet for configuration management, Grafana and influxDB for monitoring, and is involved in many more.
-
-“We collaborate with around 170 labs around the world. So every time that we find an improvement in an open source project, other labs can easily take that and use it,” said Bell, “At the same time, we also learn from others. When large scale installations like eBay and Rackspace make changes to improve scalability of solutions, it benefits us and allows us to scale.”
-
-### Solving realistic problems
-
-Around 2012, CERN was looking at ways to scale computing for the LHC, but the challenge was people rather than technology. The number of staff that CERN employs is fixed. “We had to find ways in which we can scale the compute without requiring a large number of additional people in order to administer that,” Bell said. “OpenStack provided us with an automated API-driven, software-defined infrastructure.” OpenStack also allowed CERN to look at problems related to the delivery of services and then automate those, without having to scale the staff.
-
-“We're currently running about 280,000 cores and 7,000 servers across two data centers in Geneva and in Budapest. We are using software-defined infrastructure to automate everything, which allows us to continue to add additional servers while remaining within the same envelope of staff,” said Bell.
-
-As time progresses, CERN will be dealing with even bigger challenges. Large Hadron Collider has a roadmap out to 2035, including a number of significant upgrades. “We run the accelerator for three to four years and then have a period of 18 months or two years when we upgrade the infrastructure. This maintenance period allows us to also do some computing planning,” said Bell. CERN is also planning High Luminosity Large Hadron Collider upgrade, which will allow for beams with higher luminosity. The upgrade would mean about 60 times more compute requirement compared to what CERN has today.
-
-“With Moore's Law, we will maybe get one quarter of the way there, so we have to find ways under which we can be scaling the compute and the storage infrastructure correspondingly and finding automation and solutions such as OpenStack will help that,” said Bell.
-
-“When we started off the large Hadron collider and looked at how we would deliver the computing, it was clear that we couldn't put everything into the data center at CERN, so we devised a distributed grid structure, with tier zero at CERN and then a cascading structure around that,” said Bell. “There are around 12 large tier one centers and then 150 small universities and labs around the world. They receive samples at the data from the LHC in order to assist the physicists to understand and analyze the data.”
-
-That structure means CERN is collaborating internationally, with hundreds of countries contributing toward the analysis of that data. It boils down to the fundamental principle that open source is not just about sharing code, it’s about collaboration among people to share knowledge and achieve what no single individual, organization, or company can achieve alone. That’s the Higgs boson of the open source world.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/2018/5/how-cern-using-linux-open-source
-
-作者:[SWAPNIL BHARTIYA ][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://www.linux.com/users/arnieswap
-[1]:https://www.linux.com/licenses/category/used-permission
-[2]:https://www.linux.com/licenses/category/used-permission
-[3]:https://home.cern/about/experiments/atlas
-[4]:https://www.linux.com/files/images/tim-bell-cernpng
-[5]:https://www.linux.com/files/images/atlas-cernjpg
-[6]:https://home.cern/
-[7]:https://home.cern/topics/higgs-boson
-[8]:https://home.cern/about/computing
-[9]:https://www.scientificlinux.org/
diff --git a/sources/tech/20180525 Getting started with the Python debugger.md b/sources/tech/20180525 Getting started with the Python debugger.md
deleted file mode 100644
index 560440fd02..0000000000
--- a/sources/tech/20180525 Getting started with the Python debugger.md
+++ /dev/null
@@ -1,287 +0,0 @@
-Getting started with the Python debugger
-======
-
-
-
-The Python ecosystem is rich with many tools and libraries that improve developers’ lives. For example, the Magazine has previously covered how to [enhance your Python with a interactive shell][1]. This article focuses on another tool that saves you time and improves your Python skills: the Python debugger.
-
-### Python Debugger
-
-The Python standard library provides a debugger called pdb. This debugger provides most features needed for debugging such as breakpoints, single line stepping, inspection of stack frames, and so on.
-
-A basic knowledge of pdb is useful since it’s part of the standard library. You can use it in environments where you can’t install another enhanced debugger.
-
-#### Running pdb
-
-The easiest way to run pdb is from the command line, passing the program to debug as an argument. Considering the following script:
-```
-# pdb_test.py
-#!/usr/bin/python3
-
-from time import sleep
-
-def countdown(number):
- for i in range(number, 0, -1):
- print(i)
- sleep(1)
-
-
-if __name__ == "__main__":
- seconds = 10
- countdown(seconds)
-
-```
-
-You can run pdb from the command line like this:
-```
-$ python3 -m pdb pdb_test.py
-> /tmp/pdb_test.py(1)()
--> from time import sleep
-(Pdb)
-
-```
-
-Another way to use pdb is to set a breakpoint in the program. To do this, import the pdb module and use the set_trace function:
-```
-1 # pdb_test.py
-2 #!/usr/bin/python3
-3
-4 from time import sleep
-5
-6
-7 def countdown(number):
-8 for i in range(number, 0, -1):
-9 import pdb; pdb.set_trace()
-10 print(i)
-11 sleep(1)
-12
-13
-14 if __name__ == "__main__":
-15 seconds = 10
-16 countdown(seconds)
-
-$ python3 pdb_test.py
-> /tmp/pdb_test.py(6)countdown()
--> print(i)
-(Pdb)
-
-```
-
-The script stops at the breakpoint, and pdb displays the next line in the script. You can also execute the debugger after a failure. This is known as postmortem debugging.
-
-#### Navigate the execution stack
-
-A common use case in debugging is to navigate the execution stack. Once the Python debugger is running, the following commands are useful :
-
-+ w(here) : Shows which line is currently executed and where the execution stack is.
-
-
-```
-$ python3 test_pdb.py
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) w
-/tmp/test_pdb.py(16)()
--> countdown(seconds)
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb)
-
-```
-
-+ l(ist) : Shows more context (code) around the current the location.
-
-
-```
-$ python3 test_pdb.py
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) l
-5
-6
-7 def countdown(number):
-8 for i in range(number, 0, -1):
-9 import pdb; pdb.set_trace()
-10 -> print(i)
-11 sleep(1)
-12
-13
-14 if __name__ == "__main__":
-15 seconds = 10
-(Pdb)
-
-```
-
-+ u(p)/d(own) : Navigate the call stack up or down.
-
-
-```
-$ py3 test_pdb.py
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) up
-> /tmp/test_pdb.py(16)()
--> countdown(seconds)
-(Pdb) down
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb)
-
-```
-
-#### Stepping through a program
-
-pdb provides the following commands to execute and step through code:
-
-+ n(ext): Continue execution until the next line in the current function is reached, or it returns
-+ s(tep): Execute the current line and stop at the first possible occasion (either in a function that is called or in the current function)
-+ c(ontinue): Continue execution, only stopping at a breakpoint.
-
-
-```
-$ py3 test_pdb.py
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) n
-10
-> /tmp/test_pdb.py(11)countdown()
--> sleep(1)
-(Pdb) n
-> /tmp/test_pdb.py(8)countdown()
--> for i in range(number, 0, -1):
-(Pdb) n
-> /tmp/test_pdb.py(9)countdown()
--> import pdb; pdb.set_trace()
-(Pdb) s
---Call--
-> /usr/lib64/python3.6/pdb.py(1584)set_trace()
--> def set_trace():
-(Pdb) c
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) c
-9
-> /tmp/test_pdb.py(9)countdown()
--> import pdb; pdb.set_trace()
-(Pdb)
-
-```
-
-The example shows the difference between next and step. Indeed, when using step the debugger stepped into the pdb module source code, whereas next would have just executed the set_trace function.
-
-#### Examine variables content
-
-Where pdb is really useful is examining the content of variables stored in the execution stack. For example, the a(rgs) command prints the variables of the current function, as shown below:
-```
-py3 test_pdb.py
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) where
-/tmp/test_pdb.py(16)()
--> countdown(seconds)
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) args
-number = 10
-(Pdb)
-
-```
-
-pdb prints the value of the variable number, in this case 10.
-
-Another command that can be used to print variables value is p(rint).
-```
-$ py3 test_pdb.py
-> /tmp/test_pdb.py(10)countdown()
--> print(i)
-(Pdb) list
-5
-6
-7 def countdown(number):
-8 for i in range(number, 0, -1):
-9 import pdb; pdb.set_trace()
-10 -> print(i)
-11 sleep(1)
-12
-13
-14 if __name__ == "__main__":
-15 seconds = 10
-(Pdb) print(seconds)
-10
-(Pdb) p i
-10
-(Pdb) p number - i
-0
-(Pdb)
-
-```
-
-As shown in the example’s last command, print can evaluate an expression before displaying the result.
-
-The [Python documentation][2] contains the reference and examples for each of the pdb commands. This is a useful read for someone starting with the Python debugger.
-
-### Enhanced debugger
-
-Some enhanced debuggers provide a better user experience. Most add useful extra features to pdb, such as syntax highlighting, better tracebacks, and introspection. Popular choices of enhanced debuggers include [IPython’s ipdb][3] and [pdb++][4].
-
-These examples show you how to install these two debuggers in a virtual environment. These examples use a new virtual environment, but in the case of debugging an application, the application’s virtual environment should be used.
-
-#### Install IPython’s ipdb
-
-To install the IPython ipdb, use pip in the virtual environment:
-```
-$ python3 -m venv .test_pdb
-$ source .test_pdb/bin/activate
-(test_pdb)$ pip install ipdb
-
-```
-
-To call ipdb inside a script, you must use the following command. Note that the module is called ipdb instead of pdb:
-```
-import ipdb; ipdb.set_trace()
-
-```
-
-IPython’s ipdb is also available in Fedora packages, so you can install it using Fedora’s package manager dnf:
-```
-$ sudo dnf install python3-ipdb
-
-```
-
-#### Install pdb++
-
-You can install pdb++ similarly:
-```
-$ python3 -m venv .test_pdb
-$ source .test_pdb/bin/activate
-(test_pdb)$ pip install pdbp
-
-```
-
-pdb++ overrides the pdb module, and therefore you can use the same syntax to add a breakpoint inside a program:
-```
-import pdb; pdb.set_trace()
-
-```
-
-### Conclusion
-
-Learning how to use the Python debugger saves you time when investigating problems with an application. It can also be useful to understand how a complex part of an application or some libraries work, and thereby improve your Python developer skills.
-
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/getting-started-python-debugger/
-
-作者:[Clément Verna][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://fedoramagazine.org
-[1]:https://fedoramagazine.org/enhance-python-interactive-shell
-[2]:https://docs.python.org/3/library/pdb.html
-[3]:https://github.com/gotcha/ipdb
-[4]:https://github.com/antocuni/pdb
diff --git a/sources/tech/20180528 What is behavior-driven Python.md b/sources/tech/20180528 What is behavior-driven Python.md
deleted file mode 100644
index 5931b0b5f7..0000000000
--- a/sources/tech/20180528 What is behavior-driven Python.md
+++ /dev/null
@@ -1,307 +0,0 @@
-What is behavior-driven Python?
-======
-
-Have you heard about [behavior-driven development][1] (BDD) and wondered what all the buzz is about? Maybe you've caught team members talking in "gherkin" and felt left out of the conversation. Or perhaps you're a Pythonista looking for a better way to test your code. Whatever the circumstance, learning about BDD can help you and your team achieve better collaboration and test automation, and Python's `behave` framework is a great place to start.
-
-### What is BDD?
-
- * Submitting forms on a website
- * Searching for desired results
- * Saving a document
- * Making REST API calls
- * Running command-line interface commands
-
-
-
-In software, a behavior is how a feature operates within a well-defined scenario of inputs, actions, and outcomes. Products can exhibit countless behaviors, such as:
-
-Defining a product's features based on its behaviors makes it easier to describe them, develop them, and test them. This is the heart of BDD: making behaviors the focal point of software development. Behaviors are defined early in development using a [specification by example][2] language. One of the most common behavior spec languages is [Gherkin][3], the Given-When-Then scenario format from the [Cucumber][4] project. Behavior specs are basically plain-language descriptions of how a behavior works, with a little bit of formal structure for consistency and focus. Test frameworks can easily automate these behavior specs by "gluing" step texts to code implementations.
-
-Below is an example of a behavior spec written in Gherkin:
-```
-Scenario: Basic DuckDuckGo Search
-
- Given the DuckDuckGo home page is displayed
-
- When the user searches for "panda"
-
- Then results are shown for "panda"
-
-```
-
-At a quick glance, the behavior is intuitive to understand. Except for a few keywords, the language is freeform. The scenario is concise yet meaningful. A real-world example illustrates the behavior. Steps declaratively indicate what should happen—without getting bogged down in the details of how.
-
-The [main benefits of BDD][5] are good collaboration and automation. Everyone can contribute to behavior development, not just programmers. Expected behaviors are defined and understood from the beginning of the process. Tests can be automated together with the features they cover. Each test covers a singular, unique behavior in order to avoid duplication. And, finally, existing steps can be reused by new behavior specs, creating a snowball effect.
-
-### Python's behave framework
-
-`behave` is one of the most popular BDD frameworks in Python. It is very similar to other Gherkin-based Cucumber frameworks despite not holding the official Cucumber designation. `behave` has two primary layers:
-
- 1. Behavior specs written in Gherkin `.feature` files
- 2. Step definitions and hooks written in Python modules that implement Gherkin steps
-
-
-
-As shown in the example above, Gherkin scenarios use a three-part format:
-
- 1. Given some initial state
- 2. When an action is taken
- 3. Then verify the outcome
-
-
-
-Each step is "glued" by decorator to a Python function when `behave` runs tests.
-
-### Installation
-
-As a prerequisite, make sure you have Python and `pip` installed on your machine. I strongly recommend using Python 3. (I also recommend using [`pipenv`][6], but the following example commands use the more basic `pip`.)
-
-Only one package is required for `behave`:
-```
-pip install behave
-
-```
-
-Other packages may also be useful, such as:
-```
-pip install requests # for REST API calls
-
-pip install selenium # for Web browser interactions
-
-```
-
-The [behavior-driven-Python][7] project on GitHub contains the examples used in this article.
-
-### Gherkin features
-
-The Gherkin syntax that `behave` uses is practically compliant with the official Cucumber Gherkin standard. A `.feature` file has Feature sections, which in turn have Scenario sections with Given-When-Then steps. Below is an example:
-```
-Feature: Cucumber Basket
-
- As a gardener,
-
- I want to carry many cucumbers in a basket,
-
- So that I don’t drop them all.
-
-
-
- @cucumber-basket
-
- Scenario: Add and remove cucumbers
-
- Given the basket is empty
-
- When "4" cucumbers are added to the basket
-
- And "6" more cucumbers are added to the basket
-
- But "3" cucumbers are removed from the basket
-
- Then the basket contains "7" cucumbers
-
-```
-
-There are a few important things to note here:
-
- * Both the Feature and Scenario sections have [short, descriptive titles][8].
- * The lines immediately following the Feature title are comments ignored by `behave`. It is a good practice to put the user story there.
- * Scenarios and Features can have tags (notice the `@cucumber-basket` mark) for hooks and filtering (explained below).
- * Steps follow a [strict Given-When-Then order][9].
- * Additional steps can be added for any type using `And` and `But`.
- * Steps can be parametrized with inputs—notice the values in double quotes.
-
-
-
-Scenarios can also be written as templates with multiple input combinations by using a Scenario Outline:
-```
-Feature: Cucumber Basket
-
-
-
- @cucumber-basket
-
- Scenario Outline: Add cucumbers
-
- Given the basket has “” cucumbers
-
- When "" cucumbers are added to the basket
-
- Then the basket contains "" cucumbers
-
-
-
- Examples: Cucumber Counts
-
- | initial | more | total |
-
- | 0 | 1 | 1 |
-
- | 1 | 2 | 3 |
-
- | 5 | 4 | 9 |
-
-```
-
-Scenario Outlines always have an Examples table, in which the first row gives column titles and each subsequent row gives an input combo. The row values are substituted wherever a column title appears in a step surrounded by angle brackets. In the example above, the scenario will be run three times because there are three rows of input combos. Scenario Outlines are a great way to avoid duplicate scenarios.
-
-There are other elements of the Gherkin language, but these are the main mechanics. To learn more, read the Automation Panda articles [Gherkin by Example][10] and [Writing Good Gherkin][11].
-
-### Python mechanics
-
-Every Gherkin step must be "glued" to a step definition, a Python function that provides the implementation. Each function has a step type decorator with the matching string. It also receives a shared context and any step parameters. Feature files must be placed in a directory named `features/`, while step definition modules must be placed in a directory named `features/steps/`. Any feature file can use step definitions from any module—they do not need to have the same names. Below is an example Python module with step definitions for the cucumber basket features.
-```
-from behave import *
-
-from cucumbers.basket import CucumberBasket
-
-
-
-@given('the basket has "{initial:d}" cucumbers')
-
-def step_impl(context, initial):
-
- context.basket = CucumberBasket(initial_count=initial)
-
-
-
-@when('"{some:d}" cucumbers are added to the basket')
-
-def step_impl(context, some):
-
- context.basket.add(some)
-
-
-
-@then('the basket contains "{total:d}" cucumbers')
-
-def step_impl(context, total):
-
- assert context.basket.count == total
-
-```
-
-Three [step matchers][12] are available: `parse`, `cfparse`, and `re`. The default and simplest marcher is `parse`, which is shown in the example above. Notice how parametrized values are parsed and passed into the functions as input arguments. A common best practice is to put double quotes around parameters in steps.
-
-Each step definition function also receives a [context][13] variable that holds data specific to the current scenario being run, such as `feature`, `scenario`, and `tags` fields. Custom fields may be added, too, to share data between steps. Always use context to share data—never use global variables!
-
-`behave` also supports [hooks][14] to handle automation concerns outside of Gherkin steps. A hook is a function that will be run before or after a step, scenario, feature, or whole test suite. Hooks are reminiscent of [aspect-oriented programming][15]. They should be placed in a special `environment.py` file under the `features/` directory. Hook functions can check the current scenario's tags, as well, so logic can be selectively applied. The example below shows how to use hooks to set up and tear down a Selenium WebDriver instance for any scenario tagged as `@web`.
-```
-from selenium import webdriver
-
-
-
-def before_scenario(context, scenario):
-
- if 'web' in context.tags:
-
- context.browser = webdriver.Firefox()
-
- context.browser.implicitly_wait(10)
-
-
-
-def after_scenario(context, scenario):
-
- if 'web' in context.tags:
-
- context.browser.quit()
-
-```
-
-Note: Setup and cleanup can also be done with [fixtures][16] in `behave`.
-
-To offer an idea of what a `behave` project should look like, here's the example project's directory structure:
-
-
-
-Any Python packages and custom modules can be used with `behave`. Use good design patterns to build a scalable test automation solution. Step definition code should be concise.
-
-### Running tests
-
-To run tests from the command line, change to the project's root directory and run the `behave` command. Use the `–help` option to see all available options.
-
-Below are a few common use cases:
-```
-# run all tests
-
-behave
-
-
-
-# run the scenarios in a feature file
-
-behave features/web.feature
-
-
-
-# run all tests that have the @duckduckgo tag
-
-behave --tags @duckduckgo
-
-
-
-# run all tests that do not have the @unit tag
-
-behave --tags ~@unit
-
-
-
-# run all tests that have @basket and either @add or @remove
-
-behave --tags @basket --tags @add,@remove
-
-```
-
-For convenience, options may be saved in [config][17] files.
-
-### Other options
-
-`behave` is not the only BDD test framework in Python. Other good frameworks include:
-
- * `pytest-bdd` , a plugin for `pytest``behave`, it uses Gherkin feature files and step definition modules, but it also leverages all the features and plugins of `pytest`. For example, it can run Gherkin scenarios in parallel using `pytest-xdist`. BDD and non-BDD tests can also be executed together with the same filters. `pytest-bdd` also offers a more flexible directory layout.
-
- * `radish` is a "Gherkin-plus" framework—it adds Scenario Loops and Preconditions to the standard Gherkin language, which makes it more friendly to programmers. It also offers rich command line options like `behave`.
-
- * `lettuce` is an older BDD framework very similar to `behave`, with minor differences in framework mechanics. However, GitHub shows little recent activity in the project (as of May 2018).
-
-
-
-Any of these frameworks would be good choices.
-
-Also, remember that Python test frameworks can be used for any black box testing, even for non-Python products! BDD frameworks are great for web and service testing because their tests are declarative, and Python is a [great language for test automation][18].
-
-This article is based on the author's [PyCon Cleveland 2018][19] talk, [Behavior-Driven Python][20].
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/5/behavior-driven-python
-
-作者:[Andrew Knight][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/andylpk247
-[1]:https://automationpanda.com/bdd/
-[2]:https://en.wikipedia.org/wiki/Specification_by_example
-[3]:https://automationpanda.com/2017/01/26/bdd-101-the-gherkin-language/
-[4]:https://cucumber.io/
-[5]:https://automationpanda.com/2017/02/13/12-awesome-benefits-of-bdd/
-[6]:https://docs.pipenv.org/
-[7]:https://github.com/AndyLPK247/behavior-driven-python
-[8]:https://automationpanda.com/2018/01/31/good-gherkin-scenario-titles/
-[9]:https://automationpanda.com/2018/02/03/are-gherkin-scenarios-with-multiple-when-then-pairs-okay/
-[10]:https://automationpanda.com/2017/01/27/bdd-101-gherkin-by-example/
-[11]:https://automationpanda.com/2017/01/30/bdd-101-writing-good-gherkin/
-[12]:http://behave.readthedocs.io/en/latest/api.html#step-parameters
-[13]:http://behave.readthedocs.io/en/latest/api.html#detecting-that-user-code-overwrites-behave-context-attributes
-[14]:http://behave.readthedocs.io/en/latest/api.html#environment-file-functions
-[15]:https://en.wikipedia.org/wiki/Aspect-oriented_programming
-[16]:http://behave.readthedocs.io/en/latest/api.html#fixtures
-[17]:http://behave.readthedocs.io/en/latest/behave.html#configuration-files
-[18]:https://automationpanda.com/2017/01/21/the-best-programming-language-for-test-automation/
-[19]:https://us.pycon.org/2018/
-[20]:https://us.pycon.org/2018/schedule/presentation/87/
diff --git a/sources/tech/20180531 How to Build an Amazon Echo with Raspberry Pi.md b/sources/tech/20180531 How to Build an Amazon Echo with Raspberry Pi.md
index 0bf792f769..a5d4767706 100644
--- a/sources/tech/20180531 How to Build an Amazon Echo with Raspberry Pi.md
+++ b/sources/tech/20180531 How to Build an Amazon Echo with Raspberry Pi.md
@@ -1,5 +1,3 @@
-heart4lor translating
-
How to Build an Amazon Echo with Raspberry Pi
======
diff --git a/sources/tech/20180531 How to create shortcuts in vi.md b/sources/tech/20180531 How to create shortcuts in vi.md
index 0e9772e402..ba856e745a 100644
--- a/sources/tech/20180531 How to create shortcuts in vi.md
+++ b/sources/tech/20180531 How to create shortcuts in vi.md
@@ -1,4 +1,4 @@
-How to create shortcuts in vi
+【sd886393认领翻译中】How to create shortcuts in vi
======

diff --git a/sources/tech/20180531 You don-t know Bash- An introduction to Bash arrays.md b/sources/tech/20180531 You don-t know Bash- An introduction to Bash arrays.md
deleted file mode 100644
index 10a1ecf526..0000000000
--- a/sources/tech/20180531 You don-t know Bash- An introduction to Bash arrays.md
+++ /dev/null
@@ -1,268 +0,0 @@
-You don't know Bash: An introduction to Bash arrays
-======
-
-
-
-Although software engineers regularly use the command line for many aspects of development, arrays are likely one of the more obscure features of the command line (although not as obscure as the regex operator `=~`). But obscurity and questionable syntax aside, [Bash][1] arrays can be very powerful.
-
-### Wait, but why?
-
-Writing about Bash is challenging because it's remarkably easy for an article to devolve into a manual that focuses on syntax oddities. Rest assured, however, the intent of this article is to avoid having you RTFM.
-
-#### A real (actually useful) example
-
-To that end, let's consider a real-world scenario and how Bash can help: You are leading a new effort at your company to evaluate and optimize the runtime of your internal data pipeline. As a first step, you want to do a parameter sweep to evaluate how well the pipeline makes use of threads. For the sake of simplicity, we'll treat the pipeline as a compiled C++ black box where the only parameter we can tweak is the number of threads reserved for data processing: `./pipeline --threads 4`.
-
-### The basics
-
-`--threads` parameter that we want to test:
-```
-allThreads=(1 2 4 8 16 32 64 128)
-
-```
-
-The first thing we'll do is define an array containing the values of theparameter that we want to test:
-
-In this example, all the elements are numbers, but it need not be the case—arrays in Bash can contain both numbers and strings, e.g., `myArray=(1 2 "three" 4 "five")` is a valid expression. And just as with any other Bash variable, make sure to leave no spaces around the equal sign. Otherwise, Bash will treat the variable name as a program to execute, and the `=` as its first parameter!
-
-Now that we've initialized the array, let's retrieve a few of its elements. You'll notice that simply doing `echo $allThreads` will output only the first element.
-
-To understand why that is, let's take a step back and revisit how we usually output variables in Bash. Consider the following scenario:
-```
-type="article"
-
-echo "Found 42 $type"
-
-```
-
-Say the variable `$type` is given to us as a singular noun and we want to add an `s` at the end of our sentence. We can't simply add an `s` to `$type` since that would turn it into a different variable, `$types`. And although we could utilize code contortions such as `echo "Found 42 "$type"s"`, the best way to solve this problem is to use curly braces: `echo "Found 42 ${type}s"`, which allows us to tell Bash where the name of a variable starts and ends (interestingly, this is the same syntax used in JavaScript/ES6 to inject variables and expressions in [template literals][2]).
-
-So as it turns out, although Bash variables don't generally require curly brackets, they are required for arrays. In turn, this allows us to specify the index to access, e.g., `echo ${allThreads[1]}` returns the second element of the array. Not including brackets, e.g.,`echo $allThreads[1]`, leads Bash to treat `[1]` as a string and output it as such.
-
-Yes, Bash arrays have odd syntax, but at least they are zero-indexed, unlike some other languages (I'm looking at you, `R`).
-
-### Looping through arrays
-
-Although in the examples above we used integer indices in our arrays, let's consider two occasions when that won't be the case: First, if we wanted the `$i`-th element of the array, where `$i` is a variable containing the index of interest, we can retrieve that element using: `echo ${allThreads[$i]}`. Second, to output all the elements of an array, we replace the numeric index with the `@` symbol (you can think of `@` as standing for `all`): `echo ${allThreads[@]}`.
-
-#### Looping through array elements
-
-With that in mind, let's loop through `$allThreads` and launch the pipeline for each value of `--threads`:
-```
-for t in ${allThreads[@]}; do
-
- ./pipeline --threads $t
-
-done
-
-```
-
-#### Looping through array indices
-
-Next, let's consider a slightly different approach. Rather than looping over array elements, we can loop over array indices:
-```
-for i in ${!allThreads[@]}; do
-
- ./pipeline --threads ${allThreads[$i]}
-
-done
-
-```
-
-Let's break that down: As we saw above, `${allThreads[@]}` represents all the elements in our array. Adding an exclamation mark to make it `${!allThreads[@]}` will return the list of all array indices (in our case 0 to 7). In other words, the `for` loop is looping through all indices `$i` and reading the `$i`-th element from `$allThreads` to set the value of the `--threads` parameter.
-
-This is much harsher on the eyes, so you may be wondering why I bother introducing it in the first place. That's because there are times where you need to know both the index and the value within a loop, e.g., if you want to ignore the first element of an array, using indices saves you from creating an additional variable that you then increment inside the loop.
-
-### Populating arrays
-
-So far, we've been able to launch the pipeline for each `--threads` of interest. Now, let's assume the output to our pipeline is the runtime in seconds. We would like to capture that output at each iteration and save it in another array so we can do various manipulations with it at the end.
-
-#### Some useful syntax
-
-But before diving into the code, we need to introduce some more syntax. First, we need to be able to retrieve the output of a Bash command. To do so, use the following syntax: `output=$( ./my_script.sh )`, which will store the output of our commands into the variable `$output`.
-
-The second bit of syntax we need is how to append the value we just retrieved to an array. The syntax to do that will look familiar:
-```
-myArray+=( "newElement1" "newElement2" )
-
-```
-
-#### The parameter sweep
-
-Putting everything together, here is our script for launching our parameter sweep:
-```
-allThreads=(1 2 4 8 16 32 64 128)
-
-allRuntimes=()
-
-for t in ${allThreads[@]}; do
-
- runtime=$(./pipeline --threads $t)
-
- allRuntimes+=( $runtime )
-
-done
-
-```
-
-And voilà!
-
-### What else you got?
-
-In this article, we covered the scenario of using arrays for parameter sweeps. But I promise there are more reasons to use Bash arrays—here are two more examples.
-
-#### Log alerting
-
-In this scenario, your app is divided into modules, each with its own log file. We can write a cron job script to email the right person when there are signs of trouble in certain modules:``
-```
-# List of logs and who should be notified of issues
-
-logPaths=("api.log" "auth.log" "jenkins.log" "data.log")
-
-logEmails=("jay@email" "emma@email" "jon@email" "sophia@email")
-
-
-
-# Look for signs of trouble in each log
-
-for i in ${!logPaths[@]};
-
-do
-
- log=${logPaths[$i]}
-
- stakeholder=${logEmails[$i]}
-
- numErrors=$( tail -n 100 "$log" | grep "ERROR" | wc -l )
-
-
-
- # Warn stakeholders if recently saw > 5 errors
-
- if [[ "$numErrors" -gt 5 ]];
-
- then
-
- emailRecipient="$stakeholder"
-
- emailSubject="WARNING: ${log} showing unusual levels of errors"
-
- emailBody="${numErrors} errors found in log ${log}"
-
- echo "$emailBody" | mailx -s "$emailSubject" "$emailRecipient"
-
- fi
-
-done
-
-```
-
-#### API queries
-
-Say you want to generate some analytics about which users comment the most on your Medium posts. Since we don't have direct database access, SQL is out of the question, but we can use APIs!
-
-To avoid getting into a long discussion about API authentication and tokens, we'll instead use [JSONPlaceholder][3], a public-facing API testing service, as our endpoint. Once we query each post and retrieve the emails of everyone who commented, we can append those emails to our results array:
-```
-endpoint="https://jsonplaceholder.typicode.com/comments"
-
-allEmails=()
-
-
-
-# Query first 10 posts
-
-for postId in {1..10};
-
-do
-
- # Make API call to fetch emails of this posts's commenters
-
- response=$(curl "${endpoint}?postId=${postId}")
-
-
-
- # Use jq to parse the JSON response into an array
-
- allEmails+=( $( jq '.[].email' <<< "$response" ) )
-
-done
-
-```
-
-Note here that I'm using the [`jq` tool][4] to parse JSON from the command line. The syntax of `jq` is beyond the scope of this article, but I highly recommend you look into it.
-
-As you might imagine, there are countless other scenarios in which using Bash arrays can help, and I hope the examples outlined in this article have given you some food for thought. If you have other examples to share from your own work, please leave a comment below.
-
-### But wait, there's more!
-
-Since we covered quite a bit of array syntax in this article, here's a summary of what we covered, along with some more advanced tricks we did not cover:
-
-Syntax Result `arr=()` Create an empty array `arr=(1 2 3)` Initialize array `${arr[2]}` Retrieve third element `${arr[@]}` Retrieve all elements `${!arr[@]}` Retrieve array indices `${#arr[@]}` Calculate array size `arr[0]=3` Overwrite 1st element `arr+=(4)` Append value(s) `str=$(ls)` Save `ls` output as a string `arr=( $(ls) )` Save `ls` output as an array of files `${arr[@]:s:n}` Retrieve elements at indices `n` to `s+n`
-
-### One last thought
-
-As we've discovered, Bash arrays sure have strange syntax, but I hope this article convinced you that they are extremely powerful. Once you get the hang of the syntax, you'll find yourself using Bash arrays quite often.
-
-#### Bash or Python?
-
-Which begs the question: When should you use Bash arrays instead of other scripting languages such as Python?
-
-To me, it all boils down to dependencies—if you can solve the problem at hand using only calls to command-line tools, you might as well use Bash. But for times when your script is part of a larger Python project, you might as well use Python.
-
-For example, we could have turned to Python to implement the parameter sweep, but we would have ended up just writing a wrapper around Bash:
-```
-import subprocess
-
-
-
-all_threads = [1, 2, 4, 8, 16, 32, 64, 128]
-
-all_runtimes = []
-
-
-
-# Launch pipeline on each number of threads
-
-for t in all_threads:
-
- cmd = './pipeline --threads {}'.format(t)
-
-
-
- # Use the subprocess module to fetch the return output
-
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
-
- output = p.communicate()[0]
-
- all_runtimes.append(output)
-
-```
-
-Since there's no getting around the command line in this example, using Bash directly is preferable.
-
-#### Time for a shameless plug
-
-If you enjoyed this article, there's more where that came from! [Register here to attend OSCON][5], where I'll be presenting the live-coding workshop [You Don't Know Bash][6] on July 17, 2018. No slides, no clickers—just you and me typing away at the command line, exploring the wondrous world of Bash.
-
-This article originally appeared on [Medium][7] and is republished with permission.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays
-
-作者:[Robert Aboukhalil][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/robertaboukhalil
-[1]:https://opensource.com/article/17/7/bash-prompt-tips-and-tricks
-[2]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
-[3]:https://github.com/typicode/jsonplaceholder
-[4]:https://stedolan.github.io/jq/
-[5]:https://conferences.oreilly.com/oscon/oscon-or
-[6]:https://conferences.oreilly.com/oscon/oscon-or/public/schedule/detail/67166
-[7]:https://medium.com/@robaboukhalil/the-weird-wondrous-world-of-bash-arrays-a86e5adf2c69
diff --git a/sources/tech/20180604 4 cool new projects to try in COPR for June 2018.md b/sources/tech/20180604 4 cool new projects to try in COPR for June 2018.md
deleted file mode 100644
index 8f030028b7..0000000000
--- a/sources/tech/20180604 4 cool new projects to try in COPR for June 2018.md
+++ /dev/null
@@ -1,80 +0,0 @@
-4 cool new projects to try in COPR for June 2018
-======
-COPR is a [collection][1] of personal repositories for software that isn’t carried in Fedora. Some software doesn’t conform to standards that allow easy packaging. Or it may not meet other Fedora standards, despite being free and open source. COPR can offer these projects outside the Fedora set of packages. Software in COPR isn’t supported by Fedora infrastructure or signed by the project. However, it can be a neat way to try new or experimental software.
-
-Here’s a set of new and interesting projects in COPR.
-
-### Ghostwriter
-
-[Ghostwriter][2] is a text editor for [Markdown][3] format with a minimal interface. It provides a preview of the document in HTML and syntax highlighting for Markdown. It offers the option to highlight only the paragraph or sentence currently being written. In addition, Ghostwriter can export documents to several formats, including PDF and HTML. Finally, it has the so-called “Hemingway” mode, in which erasing is disabled, forcing the user to write now and edit later.![][4]
-
-#### Installation instructions
-
-The repo currently provides Ghostwriter for Fedora 26, 27, 28, and Rawhide, and EPEL 7. To install Ghostwriter, use these commands:
-```
-sudo dnf copr enable scx/ghostwriter
-sudo dnf install ghostwriter
-
-```
-
-### Lector
-
-[Lector][5] is a simple ebook reader application. Lector supports most common ebook formats, such as EPUB, MOBI, and AZW, as well as comic book archives CBZ and CBR. It’s easy to setup — just specify the directory containing your ebooks. You can browse books in Lector’s library using either a table or book covers. Among Lector’s features are bookmarks, user-defined tags, and a built-in dictionary.![][6]
-
-#### Installation instructions
-
-The repo currently provides Lector for Fedora 26, 27, 28, and Rawhide. To install Lector, use these commands:
-```
-sudo dnf copr enable bugzy/lector
-sudo dnf install lector
-
-```
-
-### Ranger
-
-Ranerger is a text-based file manager with Vim key bindings. It displays the directory structure in three columns. The left one shows the parent directory, the middle the contents of the current directory, and the right a preview of the selected file or directory. In the case of text files, Ranger shows actual contents of the file as a preview.![][7]
-
-#### Installation instructions
-
-The repo currently provides Ranger for Fedora 27, 28, and Rawhide. To install Ranger, use these commands:
-```
-sudo dnf copr enable fszymanski/ranger
-sudo dnf install ranger
-
-```
-
-### PrestoPalette
-
-PrestoPeralette is a tool that helps create balanced color palettes. A nice feature of PrestoPalette is the ability to use lighting to affect both lightness and saturation of the palette. You can export created palettes either as PNG or JSON.
-![][8]
-
-#### Installation instructions
-
-The repo currently provides PrestoPalette for Fedora 26, 27, 28, and Rawhide, and EPEL 7. To install PrestoPalette, use these commands:
-```
-sudo dnf copr enable dagostinelli/prestopalette
-sudo dnf install prestopalette
-
-```
-
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/4-try-copr-june-2018/
-
-作者:[Dominik Turecek][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://fedoramagazine.org
-[1]:https://copr.fedorainfracloud.org/
-[2]:http://wereturtle.github.io/ghostwriter/
-[3]:https://daringfireball.net/
-[4]:https://fedoramagazine.org/wp-content/uploads/2018/05/ghostwriter.png
-[5]:https://github.com/BasioMeusPuga/Lector
-[6]:https://fedoramagazine.org/wp-content/uploads/2018/05/lector.png
-[7]:https://fedoramagazine.org/wp-content/uploads/2018/05/ranger.png
-[8]:https://fedoramagazine.org/wp-content/uploads/2018/05/prestopalette.png
diff --git a/sources/tech/20180604 BootISO - A Simple Bash Script To Securely Create A Bootable USB Device From ISO File.md b/sources/tech/20180604 BootISO - A Simple Bash Script To Securely Create A Bootable USB Device From ISO File.md
new file mode 100644
index 0000000000..f716a164a5
--- /dev/null
+++ b/sources/tech/20180604 BootISO - A Simple Bash Script To Securely Create A Bootable USB Device From ISO File.md
@@ -0,0 +1,172 @@
+BootISO – A Simple Bash Script To Securely Create A Bootable USB Device From ISO File
+======
+Most of us (including me) very often create a bootable USB device from ISO file for OS installation.
+
+There are many applications freely available in Linux for this purpose. Even we wrote few of the utility in the past.
+
+Every one uses different application and each application has their own features and functionality.
+
+In that few of applications are belongs to CLI and few of them associated with GUI.
+
+Today we are going to discuss about similar kind of utility called BootISO. It’s a simple bash script, which allow users to create a USB device from ISO file.
+
+Many of the Linux admin uses dd command to create bootable ISO, which is one of the native and famous method but the same time, it’s one of the very dangerous command. So, be careful, when you performing any action with dd command.
+
+**Suggested Read :**
+**(#)** [Etcher – Easy way to Create a bootable USB drive & SD card from an ISO image][1]
+**(#)** [Create a bootable USB drive from an ISO image using dd command on Linux][2]
+
+### What IS BootISO
+
+[BootIOS][3] is a simple bash script, which allow users to securely create a bootable USB device from one ISO file. It’s written in bash.
+
+It doesn’t offer any GUI but in the same time it has vast of options, which allow newbies to create a bootable USB device in Linux without any issues. Since it’s a intelligent tool that automatically choose if any USB device is connected on the system.
+
+It will print the list when the system has more than one USB device connected. When you choose manually another hard disk manually instead of USB, this will safely exit without writing anything on it.
+
+This script will also check for dependencies and prompt user for installation, it works with all package managers such as apt-get, yum, dnf, pacman and zypper.
+
+### BootISO Features
+
+ * It checks whether the selected ISO has the correct mime-type or not. If no then it exit.
+ * BootISO will exit automatically, if you selected any other disks (local hard drive) except USB drives.
+ * BootISO allow users to select the desired USB drives when you have more than one.
+ * BootISO prompts the user for confirmation before erasing and paritioning USB device.
+ * BootISO will handle any failure from a command properly and exit.
+ * BootISO will call a cleanup routine on exit with trap.
+
+
+
+### How To Install BootISO In Linux
+
+There are few ways are available to install BootISO in Linux but i would advise users to install using the following method.
+```
+$ curl -L https://git.io/bootiso -O
+$ chmod +x bootiso
+$ sudo mv bootiso /usr/local/bin/
+
+```
+
+Once BootISO installed, run the following command to list the available USB devices.
+```
+$ bootiso -l
+
+Listing USB drives available in your system:
+NAME HOTPLUG SIZE STATE TYPE
+sdd 1 32G running disk
+
+```
+
+If you have only one USB device, then simple run the following command to create a bootable USB device from ISO file.
+```
+$ bootiso /path/to/iso file
+
+$ bootiso /opt/iso_images/archlinux-2018.05.01-x86_64.iso
+Granting root privileges for bootiso.
+Listing USB drives available in your system:
+NAME HOTPLUG SIZE STATE TYPE
+sdd 1 32G running disk
+Autoselecting `sdd' (only USB device candidate)
+The selected device `/dev/sdd' is connected through USB.
+Created ISO mount point at `/tmp/iso.vXo'
+`bootiso' is about to wipe out the content of device `/dev/sdd'.
+Are you sure you want to proceed? (y/n)>y
+Erasing contents of /dev/sdd...
+Creating FAT32 partition on `/dev/sdd1'...
+Created USB device mount point at `/tmp/usb.0j5'
+Copying files from ISO to USB device with `rsync'
+Synchronizing writes on device `/dev/sdd'
+`bootiso' took 250 seconds to write ISO to USB device with `rsync' method.
+ISO succesfully unmounted.
+USB device succesfully unmounted.
+USB device succesfully ejected.
+You can safely remove it !
+
+```
+
+Mention your device name, when you have more than one USB device using `--device` option.
+```
+$ bootiso -d /dev/sde /opt/iso_images/archlinux-2018.05.01-x86_64.iso
+
+```
+
+By default bootios uses `rsync` command to perform all the action and if you want to use `dd` command instead of, use the following format.
+```
+$ bootiso --dd -d /dev/sde /opt/iso_images/archlinux-2018.05.01-x86_64.iso
+
+```
+
+If you want to skip `mime-type` check, include the following option with bootios utility.
+```
+$ bootiso --no-mime-check -d /dev/sde /opt/iso_images/archlinux-2018.05.01-x86_64.iso
+
+```
+
+Add the below option with bootios to skip user for confirmation before erasing and partitioning USB device.
+```
+$ bootiso -y -d /dev/sde /opt/iso_images/archlinux-2018.05.01-x86_64.iso
+
+```
+
+Enable autoselecting USB devices in conjunction with -y option.
+```
+$ bootiso -y -a /opt/iso_images/archlinux-2018.05.01-x86_64.iso
+
+```
+
+To know more all the available option for bootiso, run the following command.
+```
+$ bootiso -h
+Create a bootable USB from any ISO securely.
+Usage: bootiso [...]
+
+Options
+
+-h, --help, help Display this help message and exit.
+-v, --version Display version and exit.
+-d, --device Select block file as USB device.
+ If is not connected through USB, `bootiso' will fail and exit.
+ Device block files are usually situated in /dev/sXX or /dev/hXX.
+ You will be prompted to select a device if you don't use this option.
+-b, --bootloader Install a bootloader with syslinux (safe mode) for non-hybrid ISOs. Does not work with `--dd' option.
+-y, --assume-yes `bootiso' won't prompt the user for confirmation before erasing and partitioning USB device.
+ Use at your own risks.
+-a, --autoselect Enable autoselecting USB devices in conjunction with -y option.
+ Autoselect will automatically select a USB drive device if there is exactly one connected to the system.
+ Enabled by default when neither -d nor --no-usb-check options are given.
+-J, --no-eject Do not eject device after unmounting.
+-l, --list-usb-drives List available USB drives.
+-M, --no-mime-check `bootiso' won't assert that selected ISO file has the right mime-type.
+-s, --strict-mime-check Disallow loose application/octet-stream mime type in ISO file.
+-- POSIX end of options.
+--dd Use `dd' utility instead of mounting + `rsync'.
+ Does not allow bootloader installation with syslinux.
+--no-usb-check `bootiso' won't assert that selected device is a USB (connected through USB bus).
+ Use at your own risks.
+
+Readme
+
+ Bootiso v2.5.2.
+ Author: Jules Samuel Randolph
+ Bugs and new features: https://github.com/jsamr/bootiso/issues
+ If you like bootiso, please help the community by making it visible:
+ * star the project at https://github.com/jsamr/bootiso
+ * upvote those SE post: https://goo.gl/BNRmvm https://goo.gl/YDBvFe
+
+```
+
+--------------------------------------------------------------------------------
+
+via: https://www.2daygeek.com/bootiso-a-simple-bash-script-to-securely-create-a-bootable-usb-device-in-linux-from-iso-file/
+
+作者:[Prakash Subramanian][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://www.2daygeek.com/author/prakash/
+[1]:https://www.2daygeek.com/etcher-easy-way-to-create-a-bootable-usb-drive-sd-card-from-an-iso-image-on-linux/
+[2]:https://www.2daygeek.com/create-a-bootable-usb-drive-from-an-iso-image-using-dd-command-on-linux/
+[3]:https://github.com/jsamr/bootiso
diff --git a/sources/tech/20180606 6 Open Source AI Tools to Know.md b/sources/tech/20180606 6 Open Source AI Tools to Know.md
deleted file mode 100644
index 3aacd9b7d7..0000000000
--- a/sources/tech/20180606 6 Open Source AI Tools to Know.md
+++ /dev/null
@@ -1,55 +0,0 @@
-6 Open Source AI Tools to Know
-======
-
-
-
-In open source, no matter how original your own idea seems, it is always wise to see if someone else has already executed the concept. For organizations and individuals interested in leveraging the growing power of artificial intelligence (AI), many of the best tools are not only free and open source, but, in many cases, have already been hardened and tested.
-
-At leading companies and non-profit organizations, AI is a huge priority, and many of these companies and organizations are open sourcing valuable tools. Here is a sampling of free, open source AI tools available to anyone.
-
-**Acumos.** [Acumos AI][1] is a platform and open source framework that makes it easy to build, share, and deploy AI apps. It standardizes the infrastructure stack and components required to run an out-of-the-box general AI environment. This frees data scientists and model trainers to focus on their core competencies rather than endlessly customizing, modeling, and training an AI implementation.
-
-Acumos is part of the[LF Deep Learning Foundation][2], an organization within The Linux Foundation that supports open source innovation in artificial intelligence, machine learning, and deep learning. The goal is to make these critical new technologies available to developers and data scientists, including those who may have limited experience with deep learning and AI. The LF Deep Learning Foundation just [recently approved a project lifecycle and contribution process][3] and is now accepting proposals for the contribution of projects.
-
-**Facebook’s Framework.** Facebook[has open sourced][4] its central machine learning system designed for artificial intelligence tasks at large scale, and a series of other AI technologies. The tools are part of a proven platform in use at the company. Facebook has also open sourced a framework for deep learning and AI [called Caffe2][5].
-
-**Speaking of Caffe.** Yahoo also released its key AI software under an open source license. The[CaffeOnSpark tool][6] is based on deep learning, a branch of artificial intelligence particularly useful in helping machines recognize human speech or the contents of a photo or video. Similarly, IBM’s machine learning program known as [SystemML][7] is freely available to share and modify through the Apache Software Foundation.
-
-**Google’s Tools.** Google spent years developing its [TensorFlow][8] software framework to support its AI software and other predictive and analytics programs. TensorFlow is the engine behind several Google tools you may already use, including Google Photos and the speech recognition found in the Google app.
-
-Two [AIY kits][9] open sourced by Google let individuals easily get hands-on with artificial intelligence. Focused on computer vision and voice assistants, the two kits come as small self-assembly cardboard boxes with all the components needed for use. The kits are currently available at Target in the United States, and are based on the open source Raspberry Pi platform — more evidence of how much is happening at the intersection of open source and AI.
-
-**H2O.ai.** **** I[previously covered][10] H2O.ai, which has carved out a niche in the machine learning and artificial intelligence arena because its primary tools are free and open source. You can get the main H2O platform and Sparkling Water, which works with Apache Spark, simply by[downloading][11] them. These tools operate under the Apache 2.0 license, one of the most flexible open source licenses available, and you can even run them on clusters powered by Amazon Web Services (AWS) and others for just a few hundred dollars.
-
-**Microsoft Onboard.** “Our goal is to democratize AI to empower every person and every organization to achieve more,” Microsoft CEO Satya Nadella[has said][12]. With that in mind, Microsoft is continuing to iterate its[Microsoft Cognitive Toolkit][13]. It’s an open source software framework that competes with tools such as TensorFlow and Caffe. Cognitive Toolkit works with both Windows and Linux on 64-bit platforms.
-
-“Cognitive Toolkit enables enterprise-ready, production-grade AI by allowing users to create, train, and evaluate their own neural networks that can then scale efficiently across multiple GPUs and multiple machines on massive data sets,” reports the Cognitive Toolkit Team.
-
-Learn more about AI in this new ebook from The Linux Foundation. [Open Source AI: Projects, Insights, and Trends by Ibrahim Haddad][14] surveys 16 popular open source AI projects – looking in depth at their histories, codebases, and GitHub contributions. [Download the free ebook now.][14]
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/2018/6/6-open-source-ai-tools-know
-
-作者:[Sam Dean][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://www.linux.com/users/sam-dean
-[1]:https://www.acumos.org/
-[2]:https://www.linuxfoundation.org/projects/deep-learning/
-[3]:https://www.linuxfoundation.org/blog/lf-deep-learning-foundation-announces-project-contribution-process/
-[4]:https://code.facebook.com/posts/1687861518126048/facebook-to-open-source-ai-hardware-design/
-[5]:https://venturebeat.com/2017/04/18/facebook-open-sources-caffe2-a-new-deep-learning-framework/
-[6]:http://yahoohadoop.tumblr.com/post/139916563586/caffeonspark-open-sourced-for-distributed-deep
-[7]:https://systemml.apache.org/
-[8]:https://www.tensorflow.org/
-[9]:https://www.techradar.com/news/google-assistant-sweetens-raspberry-pi-with-ai-voice-control
-[10]:https://www.linux.com/news/sparkling-water-bridging-open-source-machine-learning-and-apache-spark
-[11]:http://www.h2o.ai/download
-[12]:https://blogs.msdn.microsoft.com/uk_faculty_connection/2017/02/10/microsoft-cognitive-toolkit-cntk/
-[13]:https://www.microsoft.com/en-us/cognitive-toolkit/
-[14]:https://www.linuxfoundation.org/publications/open-source-ai-projects-insights-and-trends/
diff --git a/sources/tech/20180606 Getting started with Buildah.md b/sources/tech/20180606 Getting started with Buildah.md
deleted file mode 100644
index 8d72b92fed..0000000000
--- a/sources/tech/20180606 Getting started with Buildah.md
+++ /dev/null
@@ -1,343 +0,0 @@
-pinewall translating
-
-Getting started with Buildah
-======
-
-
-[Buildah][1] is a command-line tool for building [Open Container Initiative][2]-compatible (that means Docker- and Kubernetes-compatible, too) images quickly and easily. It can act as a drop-in replacement for the Docker daemon’s `docker build` command (i.e., building images with a traditional Dockerfile) but is flexible enough to allow you to build images with whatever tools you prefer to use. Buildah is easy to incorporate into scripts and build pipelines, and best of all, it doesn’t require a running container daemon to build its image.
-
-### A drop-in replacement for docker build
-
-You can get started with Buildah immediately, dropping it into place where images are currently built using a Dockerfile and `docker build`. Buildah’s `build-using-dockerfile`, or `bud` argument makes it behave just like `docker build` does, so it's easy to incorporate into existing scripts or build pipelines.
-
-As with [previous articles I’ve written about Buildah][3], I like to use the example of installing "GNU Hello" from source. Consider this Dockerfile:
-```
-FROM fedora:28
-
-LABEL maintainer Chris Collins
-
-
-
-RUN dnf install -y tar gzip gcc make \
-
- && dnf clean all
-
-
-
-ADD http://ftpmirror.gnu.org/hello/hello-2.10.tar.gz /tmp/hello-2.10.tar.gz
-
-
-
-RUN tar xvzf /tmp/hello-2.10.tar.gz -C /opt
-
-
-
-WORKDIR /opt/hello-2.10
-
-
-
-RUN ./configure
-
-RUN make
-
-RUN make install
-
-RUN hello -v
-
-ENTRYPOINT "/usr/local/bin/hello"
-
-```
-
-Buildah can create an image from this Dockerfile as easily as `buildah bud -t hello .`, replacing `docker build -t hello .`:
-```
-[chris@krang] $ sudo buildah bud -t hello .
-
-STEP 1: FROM fedora:28
-
-Getting image source signatures
-
-Copying blob sha256:e06fd16225608e5b92ebe226185edb7422c3f581755deadf1312c6b14041fe73
-
- 81.48 MiB / 81.48 MiB [====================================================] 8s
-
-Copying config sha256:30190780b56e33521971b0213810005a69051d720b73154c6e473c1a07ebd609
-
- 2.29 KiB / 2.29 KiB [======================================================] 0s
-
-Writing manifest to image destination
-
-Storing signatures
-
-STEP 2: LABEL maintainer Chris Collins
-
-STEP 3: RUN dnf install -y tar gzip gcc make && dnf clean all
-
-
-
-
-
-```
-
-Once the build is complete, you can see the new image with the `buildah images` command:
-```
-[chris@krang] $ sudo buildah images
-
-IMAGE ID IMAGE NAME CREATED AT SIZE
-
-30190780b56e docker.io/library/fedora:28 Mar 7, 2018 16:53 247 MB
-
-6d54bef73e63 docker.io/library/hello:latest May 3, 2018 15:24 391.8 MB
-
-```
-
-The new image, tagged `hello:latest`, can be pushed to a remote image registry or run using [CRI-O][4] or other Kubernetes CRI-compatible runtimes, or pushed to a remote registry. If you’re testing it as a replacement for Docker build, you will probably want to copy the image to the docker daemon’s local image storage so it can be run by Docker. This is easily accomplished with the `buildah push` command:
-```
-[chris@krang] $ sudo buildah push hello:latest docker-daemon:hello:latest
-
-Getting image source signatures
-
-Copying blob sha256:72fcdba8cff9f105a61370d930d7f184702eeea634ac986da0105d8422a17028
-
- 247.02 MiB / 247.02 MiB [==================================================] 2s
-
-Copying blob sha256:e567905cf805891b514af250400cc75db3cb47d61219750e0db047c5308bd916
-
- 144.75 MiB / 144.75 MiB [==================================================] 1s
-
-Copying config sha256:6d54bef73e638f2e2dd8b7bf1c4dfa26e7ed1188f1113ee787893e23151ff3ff
-
- 1.59 KiB / 1.59 KiB [======================================================] 0s
-
-Writing manifest to image destination
-
-Storing signatures
-
-
-
-[chris@krang] $ sudo docker images | head -n2
-
-REPOSITORY TAG IMAGE ID CREATED SIZE
-
-docker.io/hello latest 6d54bef73e63 2 minutes ago 398 MB
-
-
-
-[chris@krang] $ sudo docker run -t hello:latest
-
-Hello, world!
-
-```
-
-### A few differences
-
-Unlike Docker build, Buildah doesn’t commit changes to a layer automatically for every instruction in the Dockerfile—it builds everything from top to bottom, every time. On the positive side, this means non-cached builds (for example, those you would do with automation or build pipelines) end up being somewhat faster than their Docker build counterparts, especially if there are a lot of instructions. This is great for getting new changes into production quickly from an automated deployment or continuous delivery standpoint.
-
-Practically speaking, however, the lack of caching may not be quite as useful for image development, where caching layers can save significant time when doing builds over and over again. This applies only to the `build-using-dockerfile` command, however. When using Buildah native commands, as we’ll see below, you can choose when to commit your changes to disk, allowing for more flexible development.
-
-### Buildah native commands
-
-Where Buildah _really_ shines is in its native commands, which you can use to interact with container builds. Rather than using `build-using-dockerfile/bud` for each build, Buildah has commands to actually interact with the temporary container created during the build process. (Docker uses temporary, or _intermediate_ containers, too, but you don’t really interact with them while the image is being built.)
-
-Using the "GNU Hello" example again, consider this image build using Buildah commands:
-```
-#!/usr/bin/env bash
-
-
-
-set -o errexit
-
-
-
-# Create a container
-
-container=$(buildah from fedora:28)
-
-
-
-# Labels are part of the "buildah config" command
-
-buildah config --label maintainer="Chris Collins " $container
-
-
-
-# Grab the source code outside of the container
-
-curl -sSL http://ftpmirror.gnu.org/hello/hello-2.10.tar.gz -o hello-2.10.tar.gz
-
-
-
-buildah copy $container hello-2.10.tar.gz /tmp/hello-2.10.tar.gz
-
-
-
-buildah run $container dnf install -y tar gzip gcc make
-
-Buildah run $container dnf clean all
-
-buildah run $container tar xvzf /tmp/hello-2.10.tar.gz -C /opt
-
-
-
-# Workingdir is also a "buildah config" command
-
-buildah config --workingdir /opt/hello-2.10 $container
-
-
-
-buildah run $container ./configure
-
-buildah run $container make
-
-buildah run $container make install
-
-buildah run $container hello -v
-
-
-
-# Entrypoint, too, is a “buildah config” command
-
-buildah config --entrypoint /usr/local/bin/hello $container
-
-
-
-# Finally saves the running container to an image
-
-buildah commit --format docker $container hello:latest
-
-```
-
-One thing that should be immediately obvious is the fact that this is a Bash script rather than a Dockerfile. Using Buildah’s native commands makes it easy to script, in whatever language or automation context you like to use. This could be a makefile, a Python script, or whatever tools you like to use.
-
-So what is going on here? The first Buildah command `container=$(buildah from fedora:28)`, creates a running container from the fedora:28 image, and stores the container name (the output of the command) as a variable for later use. All the rest of the Buildah commands use the `$container` variable to say what container to act upon. For the most part those commands are self-explanatory: `buildah copy` moves a file into the container, `buildah run` executes a command in the container. It is easy to match them to their Dockerfile equivalents.
-
-The final command, `buildah commit`, commits the container to an image on disk. When building images with Buildah commands rather than from a Dockerfile, you can use the `commit` command to decide when to save your changes. In the example above, all of the changes are committed at once, but intermediate commits could be included too, allowing you to choose cache points from which to start. (For example, it would be particularly useful to cache to disk after the `dnf install`, as that can take a long time, but is also reliably the same each time.)
-
-### Mountpoints, install directories, and chroots
-
-Another useful Buildah command opens the door to a lot of flexibility in building images. `buildah mount` mounts the root directory of a container to a mountpoint on your host. For example:
-```
-[chris@krang] $ container=$(sudo buildah from fedora:28)
-
-[chris@krang] $ mountpoint=$(sudo buildah mount ${container})
-
-[chris@krang] $ echo $mountpoint
-
-/var/lib/containers/storage/overlay2/463eda71ec74713d8cebbe41ee07da5f6df41c636f65139a7bd17b24a0e845e3/merged
-
-[chris@krang] $ cat ${mountpoint}/etc/redhat-release
-
-Fedora release 28 (Twenty Eight)
-
-[chris@krang] $ ls ${mountpoint}
-
-bin dev home lib64 media opt root sbin sys usr
-
-boot etc lib lost+found mnt proc run srv tmp var
-
-```
-
-This is great because now you can interact with the mountpoint to make changes to your container image. This allows you to use tools on your host to build and install software, rather than including those tools in the container image itself. For example, in the Bash script above, we needed to install the tar, Gzip, GCC, and make packages to compile "GNU Hello" inside the container. Using a mountpoint, we can build an image with the same software, but the downloaded tarball and tar, Gzip, etc., RPMs are all on the host machine rather than in the container and resulting image:
-```
-#!/usr/bin/env bash
-
-
-
-set -o errexit
-
-
-
-# Create a container
-
-container=$(buildah from fedora:28)
-
-mountpoint=$(buildah mount $container)
-
-
-
-buildah config --label maintainer="Chris Collins " $container
-
-
-
-curl -sSL http://ftpmirror.gnu.org/hello/hello-2.10.tar.gz \
-
- -o /tmp/hello-2.10.tar.gz
-
-tar xvzf src/hello-2.10.tar.gz -C ${mountpoint}/opt
-
-
-
-pushd ${mountpoint}/opt/hello-2.10
-
-./configure
-
-make
-
-make install DESTDIR=${mountpoint}
-
-popd
-
-
-
-chroot $mountpoint bash -c "/usr/local/bin/hello -v"
-
-
-
-buildah config --entrypoint "/usr/local/bin/hello" $container
-
-buildah commit --format docker $container hello
-
-buildah unmount $container
-
-```
-
-Take note of a few things in the script above:
-
- 1. The `curl` command downloads the tarball to the host, not the image
-
- 2. The `tar` command (running from the host itself) extracts the source code from the tarball into `/opt` inside the container.
-
- 3. `Configure`, `make`, and `make install` are all running from a directory inside the mountpoint, mounted to the host rather than running inside the container itself.
-
- 4. The `chroot` command here is used to change root into the mountpoint itself and test that "hello" is working, similar to the `buildah run` command used in the previous example.
-
-
-
-
-This script is shorter, it uses tools most Linux folks are already familiar with, and the resulting image is smaller (no tarball, no extra packages, etc). You could even use the package manager for the host system to install software into the container. For example, let’s say you wanted to install [NGINX][5] into the container with GNU Hello (for whatever reason):
-```
-[chris@krang] $ mountpoint=$(sudo buildah mount ${container})
-
-[chris@krang] $ sudo dnf install nginx --installroot $mountpoint
-
-[chris@krang] $ sudo chroot $mountpoint nginx -v
-
-nginx version: nginx/1.12.1
-
-```
-
-In the example above, DNF is used with the `--installroot` flag to install NGINX into the container, which can be verified with chroot.
-
-### Try it out!
-
-Buildah is a lightweight and flexible way to create container images without running a full Docker daemon on your host. In addition to offering out-of-the-box support for building from Dockerfiles, Buildah is easy to use with scripts or build tools of your choice and can help build container images using existing tools on the build host. The result is leaner images that use less bandwidth to ship around, require less storage space, and have a smaller surface area for potential attackers. Give it a try!
-
-**[See our related story,[Creating small containers with Buildah][6]]**
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/6/getting-started-buildah
-
-作者:[Chris Collins][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/clcollins
-[1]:https://github.com/projectatomic/buildah
-[2]:https://www.opencontainers.org/
-[3]:http://chris.collins.is/2017/08/17/buildah-a-new-way-to-build-container-images/
-[4]:http://cri-o.io/
-[5]:https://www.nginx.com/
-[6]:https://opensource.com/article/18/5/containers-buildah
diff --git a/sources/tech/20180607 Find If A Package Is Available For Your Linux Distribution.md b/sources/tech/20180607 Find If A Package Is Available For Your Linux Distribution.md
deleted file mode 100644
index b1bc538ff5..0000000000
--- a/sources/tech/20180607 Find If A Package Is Available For Your Linux Distribution.md
+++ /dev/null
@@ -1,152 +0,0 @@
-Find If A Package Is Available For Your Linux Distribution
-======
-
-
-
-Some times, you might wonder how to find if a package is available for your Linux distribution. Or, you simply wanted to know what version of package is available for your distribution. If so, well, it’s your lucky day. I know a tool that can get you such information. Meet **“Whohas”** – a command line tool that allows querying several package lists at once. Currently, it supports Arch, Debian, Fedora, Gentoo, Mandriva, openSUSE, Slackware, Source Mage, Ubuntu, FreeBSD, NetBSD, OpenBSD, Fink, MacPorts and Cygwin. Using this little tool, the package maintainers can easily find ebuilds, pkgbuilds and similar package definitions from other distributions. Whohas is free, open source and written in Perl programming language.
-
-### Find If A Package Is Available For Your Linux Distribution
-
-**Installing Whohas**
-
-Whohas is available in the default repositories of Debian, Ubuntu, Linux Mint. If you’re using any one of the DEB-based system, you can install it using command:
-```
-$ sudo apt-get install whohas
-
-```
-
-For Arch-based systems, it is available in [**AUR**][1]. You can use any AUR helper programs to install it.
-
-Using [**Packer**][2]:
-```
-$ packer -S whohas
-
-```
-
-Using [**Trizen**][3]:
-```
-$ trizen -S whohas
-
-```
-
-Using [**Yay**][4]:
-```
-$ yay -S whohas
-
-```
-
-Using [**Yaourt**][5]:
-```
-$ yaourt -S whohas
-
-```
-
-In other Linux distributions, download Whohas utility source from [**here**][6] and manually compile and install it.
-
-**Usage**
-
-The main objective of Whohas tool is to let you know:
-
- * Which distribution provides packages on which the user depends.
- * What version of a given package is in use in each distribution, or in each release of a distribution.
-
-
-
-Let us find which distributions contains a specific package, for example **vim**. To do so, run:
-```
-$ whohas vim
-
-```
-
-This command will show all distributions that contains the vim package with the available version of the given package, its size, repository and the download URL.
-
-![][8]
-
-You can even sort the results in alphabetical order by distribution using by piping the output to “sort” command like below.
-```
-$ whohas vim | sort
-
-```
-
-Please note that the above commands will display all packages that starts with name **vim** , for example vim-spell, vimcommander, vimpager etc. You can narrow down the search to the exact package by using grep command and space before or after or on both sides of your package like below.
-```
-$ whohas vim | sort | grep " vim"
-
-$ whohas vim | sort | grep "vim "
-
-$ whohas vim | sort | grep " vim "
-
-```
-
-The space before the package name will display all packages that ends with search term. The space after the package name will display all packages whose names begin with your search term. The space on both sides of the search will display the exact match.
-
-Alternatively, you could simply use “–strict” option like below.
-```
-$ whohas --strict vim
-
-```
-
-Sometimes, you want to know if a package is available for a specific distribution only. For example, to find if vim package is available in Arch Linux, run:
-```
-$ whohas vim | grep "^Arch"
-
-```
-
-The distribution names are abbreviated as “archlinux”, “cygwin”, “debian”, “fedora”, “fink”, “freebsd”, “gentoo”, “mandriva”, “macports”, “netbsd”, “openbsd”, “opensuse”, “slackware”, “sourcemage”, and “ubuntu”.
-
-You can also get the same results by using **-d** option like below.
-```
-$ whohas -d archlinux vim
-
-```
-
-This command will search vim packages for Arch Linux distribution only.
-
-To search for multiple distributions, for example arch linux, ubuntu, use the following command instead.
-```
-$ whohas -d archlinux,ubuntu vim
-
-```
-
-You can even find which distributions have “whohas” package.
-```
-$ whohas whohas
-
-```
-
-For more details, refer the man pages.
-```
-$ man whohas
-
-```
-
-**Also read:**
-
-All package managers can easily find the available package versions in the repositories.. However, Whohas can help you to get the comparison of available versions of packages across different distributions and which even has it available now. Give it a try, you won’t be disappointed.
-
-And, that’s all for now. Hope this was useful. More good stuffs to come. Stay tuned!
-
-Cheers!
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/find-if-a-package-is-available-for-your-linux-distribution/
-
-作者:[SK][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://www.ostechnix.com/author/sk/
-[1]:https://aur.archlinux.org/packages/whohas/
-[2]:https://www.ostechnix.com/install-packer-arch-linux-2/
-[3]:https://www.ostechnix.com/trizen-lightweight-aur-package-manager-arch-based-systems/
-[4]:https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
-[5]:https://www.ostechnix.com/install-yaourt-arch-linux/
-[6]:http://www.philippwesche.org/200811/whohas/intro.html
-[7]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[8]:http://www.ostechnix.com/wp-content/uploads/2018/06/whohas-1.png
diff --git a/sources/tech/20180607 GitLab-s Ultimate - Gold Plans Are Now Free For Open-Source Projects.md b/sources/tech/20180607 GitLab-s Ultimate - Gold Plans Are Now Free For Open-Source Projects.md
deleted file mode 100644
index 1a7e3ca5e6..0000000000
--- a/sources/tech/20180607 GitLab-s Ultimate - Gold Plans Are Now Free For Open-Source Projects.md
+++ /dev/null
@@ -1,77 +0,0 @@
-GitLab’s Ultimate & Gold Plans Are Now Free For Open-Source Projects
-======
-A lot has happened in the open-source community recently. First, [Microsoft acquired GitHub][1] and then people started to look for [GitHub alternatives][2] without even taking a second to think about it while Linus Torvalds released the [Linux Kernel 4.17][3]. Well, if you’ve been following us, I assume that you know all that.
-
-But, today, GitLab made a smart move by making some of its high-tier plans free for educational institutes and open-source projects. There couldn’t be a better time to offer something like this when a lot of developers are interested in migrating their open-source projects to GitLab.
-
-### GitLab’s premium plans are now free for open source projects and educational institutes
-
-![GitLab Logo][4]
-
-In a [blog post][5] today, GitLab announced that the **Ultimate** and Gold plans are now free for educational institutes and open-source projects. While we already know why GitLab made this move (a darn perfect timing!), they did explain their motive to make it free:
-
-> We make GitLab free for education because we want students to use our most advanced features. Many universities already run GitLab. If the students use the advanced features of GitLab Ultimate and Gold they will take their experiences with these advanced features to their workplaces.
->
-> We would love to have more open source projects use GitLab. Public projects on GitLab.com already have all the features of GitLab Ultimate. And projects like [Gnome][6] and [Debian][7] already run their own server with the open source version of GitLab. With today’s announcement, open source projects that are comfortable running on proprietary software can use all the features GitLab has to offer while allowing us to have a sustainable business model by charging non-open-source organizations.
-
-### What are these ‘free’ plans offered by GitLab?
-
-![GitLab Pricing][8]
-
-GitLab has two categories of offerings. One is the software that you could host on your own cloud hosting service like [Digital Ocean][9]. The other is providing GitLab software as a service where the hosting is managed by GitLab itself and you get an account on GitLab.com.
-
-![GitLab Pricing for hosted service][10]
-
-Gold is the highest offering in the hosted category while Ultimate is the highest offering in the self-hosted category.
-
-You can get more details about their features on GitLab pricing page. Do note that the support is not included in this offer. You have to purchase it separately.
-
-### You have to match certain criteria to avail this offer
-
-GitLab also mentioned – to whom the offer will be valid for. Here’s what they wrote in their blog post:
-
-> 1. **Educational institutions:** any institution whose purposes directly relate to learning, teaching, and/or training by a qualified educational institution, faculty, or student. Educational purposes do not include commercial, professional, or any other for-profit purposes.
->
-> 2. **Open source projects:** any project that uses a [standard open source license][11] and is non-commercial. It should not have paid support or paid contributors.
->
->
-
-
-Although the free plan does not include support, you can still pay an additional fee of 4.95 USD per user per month – which is a very fair price, when you are in the dire need of an expert to help resolve an issue.
-
-GitLab also added a note for the students:
-
-> To reduce the administrative burden for GitLab, only educational institutions can apply on behalf of their students. If you’re a student and your educational institution does not apply, you can use public projects on GitLab.com with all functionality, use private projects with the free functionality, or pay yourself.
-
-### Wrapping Up
-
-Now that GitLab is stepping up its game, what do you think about it?
-
-Do you have a project hosted on [GitHub][12]? Will you be switching over? Or, luckily, you already happen to use GitLab from the start?
-
-Let us know your thoughts in the comments section below.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/gitlab-free-open-source/
-
-作者:[Ankush Das][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/ankush/
-[1]:https://itsfoss.com/microsoft-github/
-[2]:https://itsfoss.com/github-alternatives/
-[3]:https://itsfoss.com/linux-kernel-4-17/
-[4]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/06/GitLab-logo-800x450.png
-[5]:https://about.gitlab.com/2018/06/05/gitlab-ultimate-and-gold-free-for-education-and-open-source/
-[6]:https://www.gnome.org/news/2018/05/gnome-moves-to-gitlab-2/
-[7]:https://salsa.debian.org/public
-[8]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/06/gitlab-pricing.jpeg
-[9]:https://m.do.co/c/d58840562553
-[10]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/06/gitlab-hosted-service-800x273.jpeg
-[11]:https://itsfoss.com/open-source-licenses-explained/
-[12]:https://github.com/
diff --git a/sources/tech/20180607 Mesos and Kubernetes- It-s Not a Competition.md b/sources/tech/20180607 Mesos and Kubernetes- It-s Not a Competition.md
deleted file mode 100644
index a168ac9f4a..0000000000
--- a/sources/tech/20180607 Mesos and Kubernetes- It-s Not a Competition.md
+++ /dev/null
@@ -1,66 +0,0 @@
-Mesos and Kubernetes: It's Not a Competition
-======
-
-
-
-The roots of Mesos can be traced back to 2009 when Ben Hindman was a PhD student at the University of California, Berkeley working on parallel programming. They were doing massive parallel computations on 128-core chips, trying to solve multiple problems such as making software and libraries run more efficiently on those chips. He started talking with fellow students so see if they could borrow ideas from parallel processing and multiple threads and apply them to cluster management.
-
-“Initially, our focus was on Big Data,” said Hindman. Back then, Big Data was really hot and Hadoop was one of the hottest technologies. “We recognized that the way people were running things like Hadoop on clusters was similar to the way that people were running multiple threaded applications and parallel applications,” said Hindman.
-
-However, it was not very efficient, so they started thinking how it could be done better through cluster management and resource management. “We looked at many different technologies at that time,” Hindman recalled.
-
-Hindman and his colleagues, however, decided to adopt a novel approach. “We decided to create a lower level of abstraction for resource management, and run other services on top to that to do scheduling and other things,” said Hindman, “That’s essentially the essence of Mesos -- to separate out the resource management part from the scheduling part.”
-
-It worked, and Mesos has been going strong ever since.
-
-### The project goes to Apache
-
-The project was founded in 2009. In 2010 the team decided to donate the project to the Apache Software Foundation (ASF). It was incubated at Apache and in 2013, it became a Top-Level Project (TLP).
-
-There were many reasons why the Mesos community chose Apache Software Foundation, such as the permissiveness of Apache licensing, and the fact that they already had a vibrant community of other such projects.
-
-It was also about influence. A lot of people working on Mesos were also involved with Apache, and many people were working on projects like Hadoop. At the same time, many folks from the Mesos community were working on other Big Data projects like Spark. This cross-pollination led all three projects -- Hadoop, Mesos, and Spark -- to become ASF projects.
-
-It was also about commerce. Many companies were interested in Mesos, and the developers wanted it to be maintained by a neutral body instead of being a privately owned project.
-
-### Who is using Mesos?
-
-A better question would be, who isn’t? Everyone from Apple to Netflix is using Mesos. However, Mesos had its share of challenges that any technology faces in its early days. “Initially, I had to convince people that there was this new technology called ‘containers’ that could be interesting as there is no need to use virtual machines,” said Hindman.
-
-The industry has changed a great deal since then, and now every conversation around infrastructure starts with ‘containers’ -- thanks to the work done by Docker. Today convincing is not needed, but even in the early days of Mesos, companies like Apple, Netflix, and PayPal saw the potential. They knew they could take advantage of containerization technologies in lieu of virtual machines. “These companies understood the value of containers before it became a phenomenon,” said Hindman.
-
-These companies saw that they could have a bunch of containers, instead of virtual machines. All they needed was something to manage and run these containers, and they embraced Mesos. Some of the early users of Mesos included Apple, Netflix, PayPal, Yelp, OpenTable, and Groupon.
-
-“Most of these organizations are using Mesos for just running arbitrary services,” said Hindman, “But there are many that are using it for doing interesting things with data processing, streaming data, analytics workloads and applications.”
-
-One of the reasons these companies adopted Mesos was the clear separation between the resource management layers. Mesos offers the flexibility that companies need when dealing with containerization.
-
-“One of the things we tried to do with Mesos was to create a layering so that people could take advantage of our layer, but also build whatever they wanted to on top,” said Hindman. “I think that's worked really well for the big organizations like Netflix and Apple.”
-
-However, not every company is a tech company; not every company has or should have this expertise. To help those organizations, Hindman co-founded Mesosphere to offer services and solutions around Mesos. “We ultimately decided to build DC/OS for those organizations which didn’t have the technical expertise or didn't want to spend their time building something like that on top.”
-
-### Mesos vs. Kubernetes?
-
-People often think in terms of x versus y, but it’s not always a question of one technology versus another. Most technologies overlap in some areas, and they can also be complementary. “I don't tend to see all these things as competition. I think some of them actually can work in complementary ways with one another,” said Hindman.
-
-“In fact the name Mesos stands for ‘middle’; it’s kind of a middle OS,” said Hindman, “We have the notion of a container scheduler that can be run on top of something like Mesos. When Kubernetes first came out, we actually embraced it in the Mesos ecosystem and saw it as another way of running containers in DC/OS on top of Mesos.”
-
-Mesos also resurrected a project called [Marathon][1](a container orchestrator for Mesos and DC/OS), which they have made a first-class citizen in the Mesos ecosystem. However, Marathon does not really compare with Kubernetes. “Kubernetes does a lot more than what Marathon does, so you can’t swap them with each other,” said Hindman, “At the same time, we have done many things in Mesos that are not in Kubernetes. So, these technologies are complementary to each other.”
-
-Instead of viewing such technologies as adversarial, they should be seen as beneficial to the industry. It’s not duplication of technologies; it’s diversity. According to Hindman, “it could be confusing for the end user in the open source space because it's hard to know which technologies are suitable for what kind of workload, but that’s the nature of the beast called Open Source.”
-
-That just means there are more choices, and everybody wins.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/2018/6/mesos-and-kubernetes-its-not-competition
-
-作者:[Swapnil Bhartiya][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://www.linux.com/users/arnieswap
-[1]:https://mesosphere.github.io/marathon/
diff --git a/sources/tech/20180607 Using MQTT to send and receive data for your next project.md b/sources/tech/20180607 Using MQTT to send and receive data for your next project.md
deleted file mode 100644
index 7005aee93f..0000000000
--- a/sources/tech/20180607 Using MQTT to send and receive data for your next project.md
+++ /dev/null
@@ -1,311 +0,0 @@
-pinewall translating
-
-Using MQTT to send and receive data for your next project
-======
-
-
-
-Last November we bought an electric car, and it raised an interesting question: When should we charge it? I was concerned about having the lowest emissions for the electricity used to charge the car, so this is a specific question: What is the rate of CO2 emissions per kWh at any given time, and when during the day is it at its lowest?
-
-### Finding the data
-
-I live in New York State. About 80% of our electricity comes from in-state generation, mostly through natural gas, hydro dams (much of it from Niagara Falls), nuclear, and a bit of wind, solar, and other fossil fuels. The entire system is managed by the [New York Independent System Operator][1] (NYISO), a not-for-profit entity that was set up to balance the needs of power generators, consumers, and regulatory bodies to keep the lights on in New York.
-
-Although there is no official public API, as part of its mission, NYISO makes [a lot of open data][2] available for public consumption. This includes reporting on what fuels are being consumed to generate power, at five-minute intervals, throughout the state. These are published as CSV files on a public archive and updated throughout the day. If you know the number of megawatts coming from different kinds of fuels, you can make a reasonable approximation of how much CO2 is being emitted at any given time.
-
-We should always be kind when building tools to collect and process open data to avoid overloading those systems. Instead of sending everyone to their archive service to download the files all the time, we can do better. We can create a low-overhead event stream that people can subscribe to and get updates as they happen. We can do that with [MQTT][3]. The target for my project ([ny-power.org][4]) was inclusion in the [Home Assistant][5] project, an open source home automation platform that has hundreds of thousands of users. If all of these users were hitting this CSV server all the time, NYISO might need to restrict access to it.
-
-### What is MQTT?
-
-MQTT is a publish/subscribe (pubsub) wire protocol designed with small devices in mind. Pubsub systems work like a message bus. You send a message to a topic, and any software with a subscription for that topic gets a copy of your message. As a sender, you never really know who is listening; you just provide your information to a set of topics and listen for any other topics you might care about. It's like walking into a party and listening for interesting conversations to join.
-
-This can make for extremely efficient applications. Clients subscribe to a narrow selection of topics and only receive the information they are looking for. This saves both processing time and network bandwidth.
-
-As an open standard, MQTT has many open source implementations of both clients and servers. There are client libraries for every language you could imagine, even a library you can embed in Arduino for making sensor networks. There are many servers to choose from. My go-to is the [Mosquitto][6] server from Eclipse, as it's small, written in C, and can handle tens of thousands of subscribers without breaking a sweat.
-
-### Why I like MQTT
-
-Over the past two decades, we've come up with tried and true models for software applications to ask questions of services. Do I have more email? What is the current weather? Should I buy this thing now? This pattern of "ask/receive" works well much of the time; however, in a world awash with data, there are other patterns we need. The MQTT pubsub model is powerful where lots of data is published inbound to the system. Clients can subscribe to narrow slices of data and receive updates instantly when that data comes in.
-
-MQTT also has additional interesting features, such as "last-will-and-testament" messages, which make it possible to distinguish between silence because there is no relevant data and silence because your data collectors have crashed. MQTT also has retained messages, which provide the last message on a topic to clients when they first connect. This is extremely useful for topics that update slowly.
-
-In my work with the Home Assistant project, I've found this message bus model works extremely well for heterogeneous systems. If you dive into the Internet of Things space, you'll quickly run into MQTT everywhere.
-
-### Our first MQTT stream
-
-One of NYSO's CSV files is the real-time fuel mix. Every five minutes, it's updated with the fuel sources and power generated (in megawatts) during that time period.
-
-The CSV file looks something like this:
-
-| Time Stamp | Time Zone | Fuel Category | Gen MW |
-| 05/09/2018 00:05:00 | EDT | Dual Fuel | 1400 |
-| 05/09/2018 00:05:00 | EDT | Natural Gas | 2144 |
-| 05/09/2018 00:05:00 | EDT | Nuclear | 4114 |
-| 05/09/2018 00:05:00 | EDT | Other Fossil Fuels | 4 |
-| 05/09/2018 00:05:00 | EDT | Other Renewables | 226 |
-| 05/09/2018 00:05:00 | EDT | Wind | 1 |
-| 05/09/2018 00:05:00 | EDT | Hydro | 3229 |
-| 05/09/2018 00:10:00 | EDT | Dual Fuel | 1307 |
-| 05/09/2018 00:10:00 | EDT | Natural Gas | 2092 |
-| 05/09/2018 00:10:00 | EDT | Nuclear | 4115 |
-| 05/09/2018 00:10:00 | EDT | Other Fossil Fuels | 4 |
-| 05/09/2018 00:10:00 | EDT | Other Renewables | 224 |
-| 05/09/2018 00:10:00 | EDT | Wind | 40 |
-| 05/09/2018 00:10:00 | EDT | Hydro | 3166 |
-
-The only odd thing in the table is the dual-fuel category. Most natural gas plants in New York can also burn other fossil fuel to generate power. During cold snaps in the winter, the natural gas supply gets constrained, and its use for home heating is prioritized over power generation. This happens at a low enough frequency that we can consider dual fuel to be natural gas (for our calculations).
-
-The file is updated throughout the day. I created a simple data pump that polls for the file every minute and looks for updates. It publishes any new entries out to the MQTT server into a set of topics that largely mirror this CSV file. The payload is turned into a JSON object that is easy to parse from nearly any programming language.
-```
-ny-power/upstream/fuel-mix/Hydro {"units": "MW", "value": 3229, "ts": "05/09/2018 00:05:00"}
-
-ny-power/upstream/fuel-mix/Dual Fuel {"units": "MW", "value": 1400, "ts": "05/09/2018 00:05:00"}
-
-ny-power/upstream/fuel-mix/Natural Gas {"units": "MW", "value": 2144, "ts": "05/09/2018 00:05:00"}
-
-ny-power/upstream/fuel-mix/Other Fossil Fuels {"units": "MW", "value": 4, "ts": "05/09/2018 00:05:00"}
-
-ny-power/upstream/fuel-mix/Wind {"units": "MW", "value": 41, "ts": "05/09/2018 00:05:00"}
-
-ny-power/upstream/fuel-mix/Other Renewables {"units": "MW", "value": 226, "ts": "05/09/2018 00:05:00"}
-
-ny-power/upstream/fuel-mix/Nuclear {"units": "MW", "value": 4114, "ts": "05/09/2018 00:05:00"}
-
-```
-
-This direct reflection is a good first step in turning open data into open events. We'll be converting this into a CO2 intensity, but other applications might want these raw feeds to do other calculations with them.
-
-### MQTT topics
-
-Topics and topic structures are one of MQTT's major design points. Unlike more "enterprisey" message buses, in MQTT topics are not preregistered. A sender can create topics on the fly, the only limit being that they are less than 220 characters. The `/` character is special; it's used to create topic hierarchies. As we'll soon see, you can subscribe to slices of data in these hierarchies.
-
-Out of the box with Mosquitto, every client can publish to any topic. While it's great for prototyping, before going to production you'll want to add an access control list (ACL) to restrict writing to authorized applications. For example, my app's tree is accessible to everyone in read-only format, but only clients with specific credentials can publish to it.
-
-There is no automatic schema around topics nor a way to discover all the possible topics that clients will publish to. You'll have to encode that understanding directly into any application that consumes the MQTT bus.
-
-So how should you design your topics? The best practice is to start with an application-specific root name, in our case, `ny-power`. After that, build a hierarchy as deep as you need for efficient subscription. The `upstream` tree will contain data that comes directly from an upstream source without any processing. Our `fuel-mix` category is a specific type of data. We may add others later.
-
-### Subscribing to topics
-
-Subscriptions in MQTT are simple string matches. For processing efficiency, only two wildcards are allowed:
-
- * `#` matches everything recursively to the end
- * `+` matches only until the next `/` character
-
-
-
-It's easiest to explain this with some examples:
-```
-ny-power/# - match everything published by the ny-power app
-
-ny-power/upstream/# - match all raw data
-
-ny-power/upstream/fuel-mix/+ - match all fuel types
-
-ny-power/+/+/Hydro - match everything about Hydro power that's
-
- nested 2 deep (even if it's not in the upstream tree)
-
-```
-
-A wide subscription like `ny-power/#` is common for low-volume applications. Just get everything over the network and handle it in your own application. This works poorly for high-volume applications, as most of the network bandwidth will be wasted as you drop most of the messages on the floor.
-
-To stay performant at higher volumes, applications will do some clever topic slides like `ny-power/+/+/Hydro` to get exactly the cross-section of data they need.
-
-### Adding our next layer of data
-
-From this point forward, everything in the application will work off existing MQTT streams. The first additional layer of data is computing the power's CO2 intensity.
-
-Using the 2016 [U.S. Energy Information Administration][7] numbers for total emissions and total power by fuel type in New York, we can come up with an [average emissions rate][8] per megawatt hour of power.
-
-This is encapsulated in a dedicated microservice. This has a subscription on `ny-power/upstream/fuel-mix/+`, which matches all upstream fuel-mix entries from the data pump. It then performs the calculation and publishes out to a new topic tree:
-```
-ny-power/computed/co2 {"units": "g / kWh", "value": 152.9486, "ts": "05/09/2018 00:05:00"}
-
-```
-
-In turn, there is another process that subscribes to this topic tree and archives that data into an [InfluxDB][9] instance. It then publishes a 24-hour time series to `ny-power/archive/co2/24h`, which makes it easy to graph the recent changes.
-
-This layer model works well, as the logic for each of these programs can be distinct from each other. In a more complicated system, they may not even be in the same programming language. We don't care, because the interchange format is MQTT messages, with well-known topics and JSON payloads.
-
-### Consuming from the command line
-
-To get a feel for MQTT in action, it's useful to just attach it to a bus and see the messages flow. The `mosquitto_sub` program included in the `mosquitto-clients` package is a simple way to do that.
-
-After you've installed it, you need to provide a server hostname and the topic you'd like to listen to. The `-v` flag is important if you want to see the topics being posted to. Without that, you'll see only the payloads.
-```
-mosquitto_sub -h mqtt.ny-power.org -t ny-power/# -v
-
-```
-
-Whenever I'm writing or debugging an MQTT application, I always have a terminal with `mosquitto_sub` running.
-
-### Accessing MQTT directly from the web
-
-We now have an application providing an open event stream. We can connect to it with our microservices and, with some command-line tooling, it's on the internet for all to see. But the web is still king, so it's important to get it directly into a user's browser.
-
-The MQTT folks thought about this one. The protocol specification is designed to work over three transport protocols: [TCP][10], [UDP][11], and [WebSockets][12]. WebSockets are supported by all major browsers as a way to retain persistent connections for real-time applications.
-
-The Eclipse project has a JavaScript implementation of MQTT called [Paho][13], which can be included in your application. The pattern is to connect to the host, set up some subscriptions, and then react to messages as they are received.
-```
-// ny-power web console application
-
-var client = new Paho.MQTT.Client(mqttHost, Number("80"), "client-" + Math.random());
-
-
-
-// set callback handlers
-
-client.onMessageArrived = onMessageArrived;
-
-
-
-// connect the client
-
-client.reconnect = true;
-
-client.connect({onSuccess: onConnect});
-
-
-
-// called when the client connects
-
-function onConnect() {
-
- // Once a connection has been made, make a subscription and send a message.
-
- console.log("onConnect");
-
- client.subscribe("ny-power/computed/co2");
-
- client.subscribe("ny-power/archive/co2/24h");
-
- client.subscribe("ny-power/upstream/fuel-mix/#");
-
-}
-
-
-
-// called when a message arrives
-
-function onMessageArrived(message) {
-
- console.log("onMessageArrived:"+message.destinationName + message.payloadString);
-
- if (message.destinationName == "ny-power/computed/co2") {
-
- var data = JSON.parse(message.payloadString);
-
- $("#co2-per-kwh").html(Math.round(data.value));
-
- $("#co2-units").html(data.units);
-
- $("#co2-updated").html(data.ts);
-
- }
-
- if (message.destinationName.startsWith("ny-power/upstream/fuel-mix")) {
-
- fuel_mix_graph(message);
-
- }
-
- if (message.destinationName == "ny-power/archive/co2/24h") {
-
- var data = JSON.parse(message.payloadString);
-
- var plot = [
-
- {
-
- x: data.ts,
-
- y: data.values,
-
- type: 'scatter'
-
- }
-
- ];
-
- var layout = {
-
- yaxis: {
-
- title: "g CO2 / kWh",
-
- }
-
- };
-
- Plotly.newPlot('co2_graph', plot, layout);
-
- }
-
-```
-
-This application subscribes to a number of topics because we're going to display a few different kinds of data. The `ny-power/computed/co2` topic provides us a topline number of current intensity. Whenever we receive that topic, we replace the related contents on the site.
-
-
-![NY ISO Grid CO2 Intensity][15]
-
-NY ISO Grid CO2 Intensity graph from [ny-power.org][4].
-
-The `ny-power/archive/co2/24h` topic provides a time series that can be loaded into a [Plotly][16] line graph. And `ny-power/upstream/fuel-mix` provides the data needed to provide a nice bar graph of the current fuel mix.
-
-
-![Fuel mix on NYISO grid][18]
-
-Fuel mix on NYISO grid, [ny-power.org][4].
-
-This is a dynamic website that is not polling the server. It is attached to the MQTT bus and listening on its open WebSocket. The webpage is a pub/sub client just like the data pump and the archiver. This one just happens to be executing in your browser instead of a microservice in the cloud.
-
-You can see the page in action at . That includes both the graphics and a real-time MQTT console to see the messages as they come in.
-
-### Diving deeper
-
-The entire ny-power.org application is [available as open source on GitHub][19]. You can also check out [this architecture overview][20] to see how it was built as a set of Kubernetes microservices deployed with [Helm][21]. You can see another interesting MQTT application example with [this code pattern][22] using MQTT and OpenWhisk to translate text messages in real time.
-
-MQTT is used extensively in the Internet of Things space, and many more examples of MQTT use can be found at the [Home Assistant][23] project.
-
-And if you want to dive deep into the protocol, [mqtt.org][3] has all the details for this open standard.
-
-To learn more, attend Sean Dague's talk, [Adding MQTT to your toolkit][24], at [OSCON][25], which will be held July 16-19 in Portland, Oregon.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/6/mqtt
-
-作者:[Sean Dague][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/sdague
-[1]:http://www.nyiso.com/public/index.jsp
-[2]:http://www.nyiso.com/public/markets_operations/market_data/reports_info/index.jsp
-[3]:http://mqtt.org/
-[4]:http://ny-power.org/#
-[5]:https://www.home-assistant.io
-[6]:https://mosquitto.org/
-[7]:https://www.eia.gov/
-[8]:https://github.com/IBM/ny-power/blob/master/src/nypower/calc.py#L1-L60
-[9]:https://www.influxdata.com/
-[10]:https://en.wikipedia.org/wiki/Transmission_Control_Protocol
-[11]:https://en.wikipedia.org/wiki/User_Datagram_Protocol
-[12]:https://en.wikipedia.org/wiki/WebSocket
-[13]:https://www.eclipse.org/paho/
-[14]:/file/400041
-[15]:https://opensource.com/sites/default/files/uploads/mqtt_nyiso-co2intensity.png (NY ISO Grid CO2 Intensity)
-[16]:https://plot.ly/
-[17]:/file/400046
-[18]:https://opensource.com/sites/default/files/uploads/mqtt_nyiso_fuel-mix.png (Fuel mix on NYISO grid)
-[19]:https://github.com/IBM/ny-power
-[20]:https://developer.ibm.com/code/patterns/use-mqtt-stream-real-time-data/
-[21]:https://helm.sh/
-[22]:https://developer.ibm.com/code/patterns/deploy-serverless-multilingual-conference-room/
-[23]:https://www.home-assistant.io/
-[24]:https://conferences.oreilly.com/oscon/oscon-or/public/schedule/speaker/77317
-[25]:https://conferences.oreilly.com/oscon/oscon-or
diff --git a/sources/tech/20180612 Using Ledger for YNAB-like envelope budgeting.md b/sources/tech/20180612 Using Ledger for YNAB-like envelope budgeting.md
new file mode 100644
index 0000000000..47fc4eaed9
--- /dev/null
+++ b/sources/tech/20180612 Using Ledger for YNAB-like envelope budgeting.md
@@ -0,0 +1,143 @@
+Using Ledger for YNAB-like envelope budgeting
+======
+### Bye bye Elbank
+
+I have to start this post with this: I will not be actively maintaining [Elbank][1] anymore, simply because I switched back to [Ledger][2]. If someone wants to take over, please contact me!
+
+The main reason for switching is budgeting. While Elbank was a cool experiment, it is not an accounting software, and inherently lacks support for powerful budgeting.
+
+When I started working on Elbank as a replacement for Ledger, I was looking for a reporting tool within Emacs that would fetch bank transactions automatically, so I wouldn’t have to enter transactions by hand (this is a seriously tedious task, and I grew tired of doing it after roughly two years, and finally gave up).
+
+Since then, I learned about ledger-autosync and boobank, which I use to sync my bank statements with Ledger (more about that in another post).
+
+### YNAB’s way of budgeting
+
+I only came across [YNAB][3] recently. While I won’t use their software (being a non-free web application, and, you know… there’s no `M-x ynab`), I think that the principles behind it are really appealing for personal budgeting. I encourage you to [read more about it][4] (or grab a [copy of the book][5], it’s great), but here’s the idea.
+
+ 1. **Budget every euro** : Quite simple once you get it. Every single Euro you have should be in a budget envelope. You should assign a job to every Euro you earn (that’s called [zero-based][6], [envelope system][7]).
+
+ 2. **Embrace your true expenses** : Plan for larger and less frequent expenses, so when a yearly bill arrives, or your car breaks down, you’ll be covered.
+
+ 3. **Roll with the punches** : Address overspending as it happens by taking money overspent from another envelope. As long as you keep budgeting, you’re succeeding.
+
+ 4. **Age your money** : Spend less than you earn, so your money stays in the bank account longer. As you do that, the age of your money will grow, and once you reach the goal of spending money that is at least one month old, you won’t worry about that next bill.
+
+
+
+
+### Implementation in Ledger
+
+I assume that you are familiar with Ledger, but if not I recommend reading its great [introduction][8] and [tutorial][9].
+
+The implementation in Ledger uses plain double-entry accounting. I took most of it from [Sacha][10], with some minor differences.
+
+#### Budgeting new money
+
+After each income transaction, I budget the new money:
+```
+2018-06-12 Employer
+ Assets:Bank:Checking 1600.00 EUR
+ Income:Salary -1600.00 EUR
+
+2018-06-12 Budget
+ [Assets:Budget:Food] 400.00 EUR
+ [Assets:Budget:Rent] 600.00 EUR
+ [Assets:Budget:Utilities] 600.00 EUR
+ [Equity:Budget] -1600.00 EUR
+
+```
+
+Did you notice the square brackets around the accounts of the budget transaction? It’s a feature Ledger calls [virtual postings][11]. These postings are not considered real, and won’t be present in any report that uses the `--real` flag. This is exactly what we want, since it’s a budget allocation and not a “real” transaction. Therefore we’ll use the `--real` flag for all reports except for our budget report.
+
+#### Automatically crediting budget accounts when spending money
+
+Next, we need to credit the budget accounts each time we spend money. Ledger has another neat feature called [automated transactions][12] for this:
+```
+= /Expenses/
+ [Assets:Budget:Unbudgeted] -1.0
+ [Equity:Budget] 1.0
+
+= /Expenses:Food/
+ [Assets:Budget:Food] -1.0
+ [Assets:Budget:Unbudgeted] 1.0
+
+= /Expenses:Rent/
+ [Assets:Budget:Rent] -1.0
+ [Assets:Budget:Unbudgeted] 1.0
+
+= /Expenses:Utilities/
+ [Assets:Budget:Utilities] -1.0
+ [Assets:Budget:Unbudgeted] 1.0
+
+```
+
+Every expense is taken out of the `Assets:Budget:Unbudgeted` account by default.
+
+This forces me to budget properly, as `Assets:Budget:Unbudgeted` should always be 0 (if it is not the case I immediately know that there is something wrong going on).
+
+All other automatic transactions take money out of the `Assets:Budget:Unbudgeted` account instead of `Equity:Budget` account.
+
+#### A Budget report
+
+This is the final piece of the puzzle. Here’s the budget report command:
+```
+ledger --empty -S -T -f ledger.dat bal ^assets:budget
+
+```
+
+If we have the following transactions:
+```
+2018/06/12 Groceries store
+ Expenses:Food 123.00 EUR
+ Assets:Bank:Checking
+
+2018/06/12 Landlord
+ Expenses:Rent 600.00 EUR
+ Assets:Bank:Checking
+
+2018/06/12 Internet provider
+ Expenses:Utilities:Internet 40.00 EUR
+ Assets:Bank:Checking
+
+```
+
+Here’s what the report looks like:
+```
+ 837.00 EUR Assets:Budget
+ 560.00 EUR Utilities
+ 277.00 EUR Food
+ 0 Rent
+ 0 Unbudgeted
+--------------------
+ 837.00 EUR
+
+```
+
+### Conclusion
+
+Ledger is amazingly powerful, and provides a great framework for YNAB-like budgeting. In a future post I’ll explain how I automatically import my bank transactions using a mix of `ledger-autosync` and `weboob`.
+
+--------------------------------------------------------------------------------
+
+via: https://emacs.cafe/ledger/emacs/ynab/budgeting/2018/06/12/elbank-ynab.html
+
+作者:[Nicolas Petton][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://emacs.cafe/l
+[1]:https://github.com/NicolasPetton/elbank
+[2]:https://www.ledger-cli.org/
+[3]:https://ynab.com
+[4]:https://www.youneedabudget.com/method/
+[5]:https://www.youneedabudget.com/book-order-now/
+[6]:https://en.wikipedia.org/wiki/Zero-based_budgeting
+[7]:https://en.wikipedia.org/wiki/Envelope_system
+[8]:https://www.ledger-cli.org/3.0/doc/ledger3.html#Introduction-to-Ledger
+[9]:https://www.ledger-cli.org/3.0/doc/ledger3.html#Ledger-Tutorial
+[10]:http://sachachua.com/blog/2014/11/keeping-financial-score-ledger/
+[11]:https://www.ledger-cli.org/3.0/doc/ledger3.html#Virtual-postings
+[12]:https://www.ledger-cli.org/3.0/doc/ledger3.html#Automated-Transactions
diff --git a/sources/tech/20180615 5 Commands for Checking Memory Usage in Linux.md b/sources/tech/20180615 5 Commands for Checking Memory Usage in Linux.md
deleted file mode 100644
index 05c3da4f6c..0000000000
--- a/sources/tech/20180615 5 Commands for Checking Memory Usage in Linux.md
+++ /dev/null
@@ -1,195 +0,0 @@
-5 Commands for Checking Memory Usage in Linux
-======
-
-
-The Linux operating system includes a plethora of tools, all of which are ready to help you administer your systems. From simple file and directory tools to very complex security commands, there’s not much you can’t do on Linux. And, although regular desktop users may not need to become familiar with these tools at the command line, they’re mandatory for Linux admins. Why? First, you will have to work with a GUI-less Linux server at some point. Second, command-line tools often offer far more power and flexibility than their GUI alternative.
-
-Determining memory usage is a skill you might need should a particular app go rogue and commandeer system memory. When that happens, it’s handy to know you have a variety of tools available to help you troubleshoot. Or, maybe you need to gather information about a Linux swap partition or detailed information about your installed RAM? There are commands for that as well. Let’s dig into the various Linux command-line tools to help you check into system memory usage. These tools aren’t terribly hard to use, and in this article, I’ll show you five different ways to approach the problem.
-
-I’ll be demonstrating on the [Ubuntu Server 18.04 platform][1]. You should, however, find all of these commands available on your distribution of choice. Even better, you shouldn’t need to install a single thing (as most of these tools are included).
-
-With that said, let’s get to work.
-
-### top
-
-I want to start out with the most obvious tool. The top command provides a dynamic, real-time view of a running system. Included in that system summary is the ability to check memory usage on a per-process basis. That’s very important, as you could easily have multiple iterations of the same command consuming different amounts of memory. Although you won’t find this on a headless server, say you’ve opened Chrome and noticed your system slowing down. Issue the top command to see that Chrome has numerous processes running (one per tab - Figure 1).
-
-![top][3]
-
-Figure 1: Multiple instances of Chrome appearing in the top command.
-
-[Used with permission][4]
-
-Chrome isn’t the only app to show multiple processes. You see the Firefox entry in Figure 1? That’s the primary process for Firefox, whereas the Web Content processes are the open tabs. At the top of the output, you’ll see the system statistics. On my machine (a [System76 Leopard Extreme][5]), I have a total of 16GB of RAM available, of which just over 10GB is in use. You can then comb through the list and see what percentage of memory each process is using.
-
-One of the things top is very good for is discovering Process ID (PID) numbers of services that might have gotten out of hand. With those PIDs, you can then set about to troubleshoot (or kill) the offending tasks.
-
-If you want to make top a bit more memory-friendly, issue the command top -o %MEM, which will cause top to sort all processes by memory used (Figure 2).
-
-![top][7]
-
-Figure 2: Sorting process by memory used in top.
-
-[Used with permission][4]
-
-The top command also gives you a real-time update on how much of your swap space is being used.
-
-### free
-
-Sometimes, however, top can be a bit much for your needs. You may only need to see the amount of free and used memory on your system. For that, there is the free command. The free command displays:
-
- * Total amount of free and used physical memory
-
- * Total amount of swap memory in the system
-
- * Buffers and caches used by the kernel
-
-
-
-
-From your terminal window, issue the command free. The output of this command is not in real time. Instead, what you’ll get is an instant snapshot of the free and used memory in that moment (Figure 3).
-
-![free][9]
-
-Figure 3: The output of the free command is simple and clear.
-
-[Used with permission][4]
-
-You can, of course, make free a bit more user-friendly by adding the -m option, like so: free -m. This will report the memory usage in MB (Figure 4).
-
-![free][11]
-
-Figure 4: The output of the free command in a more human-readable form.
-
-[Used with permission][4]
-
-Of course, if your system is even remotely modern, you’ll want to use the -g option (gigabytes), as in free -g.
-
-If you need memory totals, you can add the t option like so: free -mt. This will simply total the amount of memory in columns (Figure 5).
-
-![total][13]
-
-Figure 5: Having free total your memory columns for you.
-
-[Used with permission][4]
-
-### vmstat
-
-Another very handy tool to have at your disposal is vmstat. This particular command is a one-trick pony that reports virtual memory statistics. The vmstat command will report stats on:
-
- * Processes
-
- * Memory
-
- * Paging
-
- * Block IO
-
- * Traps
-
- * Disks
-
- * CPU
-
-
-
-
-The best way to issue vmstat is by using the -s switch, like vmstat -s. This will report your stats in a single column (which is so much easier to read than the default report). The vmstat command will give you more information than you need (Figure 6), but more is always better (in such cases).
-
-![vmstat][15]
-
-Figure 6: Using the vmstat command to check memory usage.
-
-[Used with permission][4]
-
-### dmidecode
-
-What if you want to find out detailed information about your installed system RAM? For that, you could use the dmidecode command. This particular tool is the DMI table decoder, which dumps a system’s DMI table contents into a human-readable format. If you’re unsure as to what the DMI table is, it’s a means to describe what a system is made of (as well as possible evolutions for a system).
-
-To run the dmidecode command, you do need sudo privileges. So issue the command sudo dmidecode -t 17. The output of the command (Figure 7) can be lengthy, as it displays information for all memory-type devices. So if you don’t have the ability to scroll, you might want to send the output of that command to a file, like so: sudo dmidecode -t 17 > dmi_infoI, or pipe it to the less command, as in sudo dmidecode | less.
-
-![dmidecode][17]
-
-Figure 7: The output of the dmidecode command.
-
-[Used with permission][4]
-
-### /proc/meminfo
-
-You might be asking yourself, “Where do these commands get this information from?”. In some cases, they get it from the /proc/meminfo file. Guess what? You can read that file directly with the command less /proc/meminfo. By using the less command, you can scroll up and down through that lengthy output to find exactly what you need (Figure 8).
-
-![/proc/meminfo][19]
-
-Figure 8: The output of the less /proc/meminfo command.
-
-[Used with permission][4]
-
-One thing you should know about /proc/meminfo: This is not a real file. Instead /pro/meminfo is a virtual file that contains real-time, dynamic information about the system. In particular, you’ll want to check the values for:
-
- * MemTotal
-
- * MemFree
-
- * MemAvailable
-
- * Buffers
-
- * Cached
-
- * SwapCached
-
- * SwapTotal
-
- * SwapFree
-
-
-
-
-If you want to get fancy with /proc/meminfo you can use it in conjunction with the egrep command like so: egrep --color 'Mem|Cache|Swap' /proc/meminfo. This will produce an easy to read listing of all entries that contain Mem, Cache, and Swap ... with a splash of color (Figure 9).
-
-![/proc/meminfo][21]
-
-Figure 9: Making /proc/meminfo easier to read.
-
-[Used with permission][4]
-
-### Keep learning
-
-One of the first things you should do is read the manual pages for each of these commands (so man top, man free, man vmstat, man dmidecode). Starting with the man pages for commands is always a great way to learn so much more about how a tool works on Linux.
-
-Learn more about Linux through the free ["Introduction to Linux" ][22]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/learn/5-commands-checking-memory-usage-linux
-
-作者:[Jack Wallen][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://www.linux.com/users/jlwallen
-[1]:https://www.ubuntu.com/download/server
-[2]:/files/images/memory1jpg
-[3]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_1.jpg?itok=fhhhUL_l (top)
-[4]:/licenses/category/used-permission
-[5]:https://system76.com/desktops/leopard
-[6]:/files/images/memory2jpg
-[7]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_2.jpg?itok=zuVkQfvv (top)
-[8]:/files/images/memory3jpg
-[9]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_3.jpg?itok=rvuQp3t0 (free)
-[10]:/files/images/memory4jpg
-[11]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_4.jpg?itok=K_luLLPt (free)
-[12]:/files/images/memory5jpg
-[13]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_5.jpg?itok=q50atcsX (total)
-[14]:/files/images/memory6jpg
-[15]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_6.jpg?itok=bwFnUVmy (vmstat)
-[16]:/files/images/memory7jpg
-[17]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_7.jpg?itok=UNHIT_P6 (dmidecode)
-[18]:/files/images/memory8jpg
-[19]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_8.jpg?itok=t87jvmJJ (/proc/meminfo)
-[20]:/files/images/memory9jpg
-[21]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/memory_9.jpg?itok=t-iSMEKq (/proc/meminfo)
-[22]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180615 Complete Sed Command Guide [Explained with Practical Examples].md b/sources/tech/20180615 Complete Sed Command Guide [Explained with Practical Examples].md
index a1d721ae3c..e548213483 100644
--- a/sources/tech/20180615 Complete Sed Command Guide [Explained with Practical Examples].md
+++ b/sources/tech/20180615 Complete Sed Command Guide [Explained with Practical Examples].md
@@ -1,4 +1,3 @@
-translating by amwps290
Complete Sed Command Guide [Explained with Practical Examples]
======
In a previous article, I showed the [basic usage of Sed][1], the stream editor, on a practical use case. Today, be prepared to gain more insight about Sed as we will take an in-depth tour of the sed execution model. This will be also an opportunity to make an exhaustive review of all Sed commands and to dive into their details and subtleties. So, if you are ready, launch a terminal, [download the test files][2] and sit comfortably before your keyboard: we will start our exploration right now!
diff --git a/sources/tech/20180618 5 open source alternatives to Dropbox.md b/sources/tech/20180618 5 open source alternatives to Dropbox.md
deleted file mode 100644
index d94b4537aa..0000000000
--- a/sources/tech/20180618 5 open source alternatives to Dropbox.md
+++ /dev/null
@@ -1,122 +0,0 @@
-5 open source alternatives to Dropbox
-======
-
-
-
-Dropbox is the 800-pound gorilla of filesharing applications. Even though it's a massively popular tool, you may choose to use an alternative.
-
-Maybe that's because you're dedicated to the [open source way][1] for all the good reasons, including security and freedom, or possibly you've been spooked by data breaches. Or perhaps the pricing plan doesn't work out in your favor for the amount of storage you actually need.
-
-Fortunately, there are a variety of open source filesharing applications out there that give you more storage, security, and control over your data at a far lower price than Dropbox charges. How much lower? Try free, if you're a bit tech savvy and have a Linux server to use.
-
-Here are five of the best open source alternatives to Dropbox, plus a few others that you might want to consider.
-
-### ownCloud
-
-
-
-[ownCloud][2], launched in 2010, is the oldest application on this list, but don't let that fool you: It's still very popular (with over 1.5 million users, according to the company) and actively maintained by a community of 1,100 contributors, with updates released regularly.
-
-Its primary features—file and folding sharing, document collaboration—are similar to Dropbox's. Its primary difference (aside from its [open source license][3]) is that your files are hosted on your private Linux server or cloud, giving users complete control over your data. (Self-hosting is a common thread among the apps on this list.)
-
-With ownCloud, you can sync and access files through clients for Linux, MacOS, or Windows computers or mobile apps for Android and iOS devices, and provide password-protected links to others for collaboration or file upload/download. Data transfers are secured by end-to-end encryption (E2EE) and SSL encryption. You can also expand its functionality with a wide variety of third-party apps available in its [marketplace][4], and there is also a paid, commercially licensed enterprise edition.
-
-ownCloud offers comprehensive [documentation][5], including an installation guide and manuals for users, admins, and developers, and you can access its [source code][6] in its GitHub repository.
-
-### NextCloud
-
-
-
-[NextCloud][7] spun out of ownCloud in 2016 and shares much of the same functionality. Nextcloud [touts][8] its high security and regulatory compliance as a distinguishing feature. It has HIPAA (healthcare) and GDPR (privacy) compliance features and offers extensive data-policy enforcement, encryption, user management, and auditing capabilities. It also encrypts data during transfer and at rest and integrates with mobile device management and authentication mechanisms (including LDAP/AD, single-sign-on, two-factor authentication, etc.).
-
-Like the other solutions on this list, NextCloud is self-hosted, but if you don't want to roll your own NextCloud server on Linux, the company partners with several [providers][9] for setup and hosting and sells servers, appliances, and support. A [marketplace][10] offers numerous apps to extend its features.
-
-NextCloud's [documentation][11] page offers thorough information for users, admins, and developers as well as links to its forums, IRC channel, and social media pages for community-based support. If you'd like to contribute, access its source code, report a bug, check out its (AGPLv3) license, or just learn more, visit the project's [GitHub repository][12].
-
-### Seafile
-
-
-
-[Seafile][13] may not have the bells and whistles (or app ecosystem) of ownCloud or Nextcloud, but it gets the job done. Essentially, it acts as a virtual drive on your Linux server to extend your desktop storage and allow you to share files selectively with password protection and various levels of permission (i.e., read-only or read/write).
-
-Its collaboration features include per-folder access control, password-protected download links, and Git-like version control and retention. Files are secured with two-factor authentication, file encryption, and AD/LDAP integration, and they're accessible from Windows, MacOS, Linux, iOS, or Android devices.
-
-For more information, visit Seafile's [GitHub repository][14], [server manual][15], [wiki][16], and [forums][17]. Note that Seafile's community edition is licensed under [GPLv2][18], but its professional edition is not open source.
-
-### OnionShare
-
-
-
-[OnionShare][19] is a cool app that does one thing: It allows you to share individual files or folders securely and, if you want, anonymously. There's no server to set up or maintain—all you need to do is [download and install][20] the app on MacOS, Windows, or Linux. Files are always hosted on your own computer; when you share a file, OnionShare creates a web server, makes it accessible as a Tor Onion service, and generates an unguessable .onion URL that allows the recipient to access the file via [Tor browser][21].
-
-You can set limits on your fileshare, such as limiting the number of times it can be downloaded or using an auto-stop timer, which sets a strict expiration date/time after which the file is inaccessible (even if it hasn't been accessed yet).
-
-OnionShare is licensed under [GPLv3][22]; for more information, check out its GitHub [repository][22], which also includes [documentation][23] that covers the features in this easy-to-use filesharing application.
-
-### Pydio Cells
-
-
-
-[Pydio Cells][24], which achieved stability in May 2018, is a complete overhaul of the Pydio filesharing application's core server code. Due to limitations with Pydio's PHP-based backend, the developers decided to rewrite the backend in the Go server language with a microservices architecture. (The frontend is still based on PHP.)
-
-Pydio Cells includes the usual filesharing and version control features, as well as in-app messaging, mobile apps (Android and iOS), and a social network-style approach to collaboration. Security includes OpenID Connect-based authentication, encryption at rest, security policies, and more. Advanced features are included in the enterprise distribution, but there's plenty of power for most small and midsize businesses and home users in the community (or "Home") version.
-
-You can [download][25] Pydio Cells for Linux and MacOS. For more information, check out the [documentation FAQ][26], [source code][27] repository, and [AGPLv3 license][28].
-
-### Others to consider
-
-If these choices don't meet your needs, you may want to consider these open source filesharing-type applications.
-
- * If your main goal is to sync files between devices, rather than to share files, check out [Syncthing][29]).
- * If you're a Git fan and don't need a mobile app, you might appreciate [SparkleShare][30].
- * If you primarily want a place to aggregate all your personal data, take a look at [Cozy][31].
- * And, if you're looking for a lightweight or dedicated filesharing tool, peruse [Scott Nesbitt's review][32] of some lesser-known options.
-
-
-
-What is your favorite open source filesharing application? Let us know in the comments.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/alternatives/dropbox
-
-作者:[OPensource.com][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
-[1]:https://opensource.com/open-source-way
-[2]:https://owncloud.org/
-[3]:https://www.gnu.org/licenses/agpl-3.0.html
-[4]:https://marketplace.owncloud.com/
-[5]:https://doc.owncloud.com/
-[6]:https://github.com/owncloud
-[7]:https://nextcloud.com/
-[8]:https://nextcloud.com/secure/
-[9]:https://nextcloud.com/providers/
-[10]:https://apps.nextcloud.com/
-[11]:https://nextcloud.com/support/
-[12]:https://github.com/nextcloud
-[13]:https://www.seafile.com/en/home/
-[14]:https://github.com/haiwen/seafile
-[15]:https://manual.seafile.com/
-[16]:https://seacloud.cc/group/3/wiki/
-[17]:https://forum.seafile.com/
-[18]:https://github.com/haiwen/seafile/blob/master/LICENSE.txt
-[19]:https://onionshare.org/
-[20]:https://onionshare.org/#downloads
-[21]:https://www.torproject.org/
-[22]:https://github.com/micahflee/onionshare/blob/develop/LICENSE
-[23]:https://github.com/micahflee/onionshare/wiki
-[24]:https://pydio.com/en
-[25]:https://pydio.com/download/
-[26]:https://pydio.com/en/docs/faq
-[27]:https://github.com/pydio/cells
-[28]:https://github.com/pydio/pydio-core/blob/develop/LICENSE
-[29]:https://syncthing.net/
-[30]:http://www.sparkleshare.org/
-[31]:https://cozy.io/en/
-[32]:https://opensource.com/article/17/3/file-sharing-tools
diff --git a/sources/tech/20180618 What-s all the C Plus Fuss- Bjarne Stroustrup warns of dangerous future plans for his C.md b/sources/tech/20180618 What-s all the C Plus Fuss- Bjarne Stroustrup warns of dangerous future plans for his C.md
deleted file mode 100644
index 04644aebb2..0000000000
--- a/sources/tech/20180618 What-s all the C Plus Fuss- Bjarne Stroustrup warns of dangerous future plans for his C.md
+++ /dev/null
@@ -1,154 +0,0 @@
-What's all the C Plus Fuss? Bjarne Stroustrup warns of dangerous future plans for his C++
-======
-
-
-
-**Interview** Earlier this year, Bjarne Stroustrup, creator of C++, managing director in the technology division of Morgan Stanley, and a visiting professor of computer science at Columbia University in the US, wrote [a letter][1] inviting those overseeing the evolution of the programming language to “Remember the Vasa!”
-
-Easy for a Dane to understand no doubt, but perhaps more of a stretch for those with a few gaps in their knowledge of 17th century Scandinavian history. The Vasa was a Swedish warship, commissioned by King Gustavus Adolphus. It was the most powerful warship in the Baltic Sea from its maiden voyage on the August 10, 1628, until a few minutes later when it sank.
-
-The formidable Vasa suffered from a design flaw: it was top-heavy, so much so that it was [undone by a gust of wind][2]. By invoking the memory of the capsized ship, Stroustrup served up a cautionary tale about the risks facing C++ as more and more features get added to the language.
-
-Quite a few such features have been suggested. Stroustrup cited 43 proposals in his letter. He contends those participating in the evolution of the ISO standard language, a group known as [WG21][3], are working to advance the language but not together.
-
-In his letter, he wrote:
-
->Individually, many proposals make sense. Together they are insanity to the point of endangering the future of C++.
-
-He makes clear that he doesn’t interpret the fate of the Vasa to mean that incremental improvements spell doom. Rather, he takes it as a lesson to build a solid foundation, to learn from experience and to test thoroughly.
-
-With the recent conclusion of the C++ Standardization Committee Meeting in Rapperswil, Switzerland, earlier this month, Stroustrup addressed a few questions put to him by _The Register_ about what's next for the language. (The most recent version is C++17, which arrived last year; the next version C++20 is under development and expected in 2020.)
-
-**_Register:_ In your note, Remember the Vasa!, you wrote:**
-
->The foundation begun in C++11 is not yet complete, and C++17 did little to make our foundation more solid, regular, and complete. Instead, it added significant surface complexity and increased the number of features people need to learn. C++ could crumble under the weight of these – mostly not quite fully-baked – proposals. We should not spend most our time creating increasingly complicated facilities for experts, such as ourselves.
-
-**Is C++ too challenging for newcomers, and if so, what features do you believe would make the language more accessible?**
-
-_**Stroustrup:**_ Some parts of C++ are too challenging for newcomers.
-
-On the other hand, there are parts of C++ that makes it far more accessible to newcomers than C or 1990s C++. The difficulty is to get the larger community to focus on those parts and help beginners and casual C++ users to avoid the parts that are there to support implementers of advanced libraries.
-
-I recommend the [C++ Core Guidelines][4] as an aide for that.
-
-Also, my “A Tour of C++” can help people get on the right track with modern C++ without getting lost in 1990s complexities or ensnarled by modern facilities meant for expert use. The second edition of “A Tour of C++” covering C++17 and parts of C++20 is on its way to the stores.
-
-I and others have taught C++ to 1st year university students with no previous programming experience in 3 months. It can be done as long as you don’t try to dig into every obscure corner of the language and focus on modern C++.
-
-“Making simple things simple” is a long-term goal of mine. Consider the C++11 range-for loop:
-```
-for (int& x : v) ++x; // increment each element of the container v
-
-```
-
-where v can be just about any container. In C and C-style C++, that might look like this:
-```
-for (int i=0; i``.` This overwrites any local changes you haven't committed. In effect, it resets (clears out) the staging area and overwrites content in the working directory with the content from the commit you reset to. Before you use the `hard` option, be sure that's what you really want to do, since the command overwrites any uncommitted changes.
-
-### Revert
-
-The net effect of the `git revert` command is similar to reset, but its approach is different. Where the `reset` command moves the branch pointer back in the chain (typically) to "undo" changes, the `revert` command adds a new commit at the end of the chain to "cancel" changes. The effect is most easily seen by looking at Figure 1 again. If we add a line to a file in each commit in the chain, one way to get back to the version with only two lines is to reset to that commit, i.e., `git reset HEAD~1`.
-
-Another way to end up with the two-line version is to add a new commit that has the third line removed—effectively canceling out that change. This can be done with a `git revert` command, such as:
-```
-$ git revert HEAD
-
-```
-
-Because this adds a new commit, Git will prompt for the commit message:
-```
-Revert "File with three lines"
-
-This reverts commit b764644bad524b804577684bf74e7bca3117f554.
-
-# Please enter the commit message for your changes. Lines starting
-# with '#' will be ignored, and an empty message aborts the commit.
-# On branch master
-# Changes to be committed:
-# modified: file1.txt
-#
-```
-
-Figure 3 (below) shows the result after the `revert` operation is completed.
-
-If we do a `git log` now, we'll see a new commit that reflects the contents before the previous commit.
-```
-$ git log --oneline
-11b7712 Revert "File with three lines"
-b764644 File with three lines
-7c709f0 File with two lines
-9ef9173 File with one line
-```
-
-Here are the current contents of the file in the working directory:
-```
-$ cat
-Line 1
-Line 2
-```
-
-#### Revert or reset?
-
-Why would you choose to do a `revert` over a `reset` operation? If you have already pushed your chain of commits to the remote repository (where others may have pulled your code and started working with it), a revert is a nicer way to cancel out changes for them. This is because the Git workflow works well for picking up additional commits at the end of a branch, but it can be challenging if a set of commits is no longer seen in the chain when someone resets the branch pointer back.
-
-This brings us to one of the fundamental rules when working with Git in this manner: Making these kinds of changes in your local repository to code you haven't pushed yet is fine. But avoid making changes that rewrite history if the commits have already been pushed to the remote repository and others may be working with them.
-
-In short, if you rollback, undo, or rewrite the history of a commit chain that others are working with, your colleagues may have a lot more work when they try to merge in changes based on the original chain they pulled. If you must make changes against code that has already been pushed and is being used by others, consider communicating before you make the changes and give people the chance to merge their changes first. Then they can pull a fresh copy after the infringing operation without needing to merge.
-
-You may have noticed that the original chain of commits was still there after we did the reset. We moved the pointer and reset the code back to a previous commit, but it did not delete any commits. This means that, as long as we know the original commit we were pointing to, we can "restore" back to the previous point by simply resetting back to the original head of the branch:
-```
-git reset
-
-```
-
-A similar thing happens in most other operations we do in Git when commits are replaced. New commits are created, and the appropriate pointer is moved to the new chain. But the old chain of commits still exists.
-
-### Rebase
-
-Now let's look at a branch rebase. Consider that we have two branches—master and feature—with the chain of commits shown in Figure 4 below. Master has the chain `C4->C2->C1->C0` and feature has the chain `C5->C3->C2->C1->C0`.
-
-![Chain of commits for branches master and feature][6]
-
-Fig. 4: Chain of commits for branches master and feature
-
-If we look at the log of commits in the branches, they might look like the following. (The `C` designators for the commit messages are used to make this easier to understand.)
-```
-$ git log --oneline master
-6a92e7a C4
-259bf36 C2
-f33ae68 C1
-5043e79 C0
-
-$ git log --oneline feature
-79768b8 C5
-000f9ae C3
-259bf36 C2
-f33ae68 C1
-5043e79 C0
-```
-
-I tell people to think of a rebase as a "merge with history" in Git. Essentially what Git does is take each different commit in one branch and attempt to "replay" the differences onto the other branch.
-
-So, we can rebase a feature onto master to pick up `C4` (e.g., insert it into feature's chain). Using the basic Git commands, it might look like this:
-```
-$ git checkout feature
-$ git rebase master
-
-First, rewinding head to replay your work on top of it...
-Applying: C3
-Applying: C5
-```
-
-Afterward, our chain of commits would look like Figure 5.
-
-![Chain of commits after the rebase command][8]
-
-Fig. 5: Chain of commits after the `rebase` command
-
-Again, looking at the log of commits, we can see the changes.
-```
-$ git log --oneline master
-6a92e7a C4
-259bf36 C2
-f33ae68 C1
-5043e79 C0
-
-$ git log --oneline feature
-c4533a5 C5
-64f2047 C3
-6a92e7a C4
-259bf36 C2
-f33ae68 C1
-5043e79 C0
-```
-
-Notice that we have `C3'` and `C5'`—new commits created as a result of making the changes from the originals "on top of" the existing chain in master. But also notice that the "original" `C3` and `C5` are still there—they just don't have a branch pointing to them anymore.
-
-If we did this rebase, then decided we didn't like the results and wanted to undo it, it would be as simple as:
-```
-$ git reset 79768b8
-
-```
-
-With this simple change, our branch would now point back to the same set of commits as before the `rebase` operation—effectively undoing it (Figure 6).
-
-![After undoing rebase][10]
-
-Fig. 6: After undoing the `rebase` operation
-
-What happens if you can't recall what commit a branch pointed to before an operation? Fortunately, Git again helps us out. For most operations that modify pointers in this way, Git remembers the original commit for you. In fact, it stores it in a special reference named `ORIG_HEAD `within the `.git` repository directory. That path is a file containing the most recent reference before it was modified. If we `cat` the file, we can see its contents.
-```
-$ cat .git/ORIG_HEAD
-79768b891f47ce06f13456a7e222536ee47ad2fe
-```
-
-We could use the `reset` command, as before, to point back to the original chain. Then the log would show this:
-```
-$ git log --oneline feature
-79768b8 C5
-000f9ae C3
-259bf36 C2
-f33ae68 C1
-5043e79 C0
-```
-
-Another place to get this information is in the reflog. The reflog is a play-by-play listing of switches or changes to references in your local repository. To see it, you can use the `git reflog` command:
-```
-$ git reflog
-79768b8 HEAD@{0}: reset: moving to 79768b
-c4533a5 HEAD@{1}: rebase finished: returning to refs/heads/feature
-c4533a5 HEAD@{2}: rebase: C5
-64f2047 HEAD@{3}: rebase: C3
-6a92e7a HEAD@{4}: rebase: checkout master
-79768b8 HEAD@{5}: checkout: moving from feature to feature
-79768b8 HEAD@{6}: commit: C5
-000f9ae HEAD@{7}: checkout: moving from master to feature
-6a92e7a HEAD@{8}: commit: C4
-259bf36 HEAD@{9}: checkout: moving from feature to master
-000f9ae HEAD@{10}: commit: C3
-259bf36 HEAD@{11}: checkout: moving from master to feature
-259bf36 HEAD@{12}: commit: C2
-f33ae68 HEAD@{13}: commit: C1
-5043e79 HEAD@{14}: commit (initial): C0
-```
-
-You can then reset to any of the items in that list using the special relative naming format you see in the log:
-```
-$ git reset HEAD@{1}
-
-```
-
-Once you understand that Git keeps the original chain of commits around when operations "modify" the chain, making changes in Git becomes much less scary. This is one of Git's core strengths: being able to quickly and easily try things out and undo them if they don't work.
-
-Brent Laster will present [Power Git: Rerere, Bisect, Subtrees, Filter Branch, Worktrees, Submodules, and More][11] at the 20th annual [OSCON][12] event, July 16-19 in Portland, Ore. For more tips and explanations about using Git at any level, checkout Brent's book "[Professional Git][13]," available on Amazon.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/6/git-reset-revert-rebase-commands
-
-作者:[Brent Laster][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/bclaster
-[1]:/file/401126
-[2]:https://opensource.com/sites/default/files/uploads/gitcommands1_local-environment.png (Local Git environment with repository, staging area, and working directory)
-[3]:/file/401131
-[4]:https://opensource.com/sites/default/files/uploads/gitcommands2_reset.png (After reset)
-[5]:/file/401141
-[6]:https://opensource.com/sites/default/files/uploads/gitcommands4_commits-branches.png (Chain of commits for branches master and feature)
-[7]:/file/401146
-[8]:https://opensource.com/sites/default/files/uploads/gitcommands5_commits-rebase.png (Chain of commits after the rebase command)
-[9]:/file/401151
-[10]:https://opensource.com/sites/default/files/uploads/gitcommands6_rebase-undo.png (After undoing rebase)
-[11]:https://conferences.oreilly.com/oscon/oscon-or/public/schedule/detail/67142
-[12]:https://conferences.oreilly.com/oscon/oscon-or
-[13]:https://www.amazon.com/Professional-Git-Brent-Laster/dp/111928497X/ref=la_B01MTGIINQ_1_2?s=books&ie=UTF8&qid=1528826673&sr=1-2
diff --git a/sources/tech/20180622 Automatically Change Wallpapers in Linux with Little Simple Wallpaper Changer.md b/sources/tech/20180622 Automatically Change Wallpapers in Linux with Little Simple Wallpaper Changer.md
deleted file mode 100644
index d3d3c00937..0000000000
--- a/sources/tech/20180622 Automatically Change Wallpapers in Linux with Little Simple Wallpaper Changer.md
+++ /dev/null
@@ -1,85 +0,0 @@
-translating----geekpi
-
-Automatically Change Wallpapers in Linux with Little Simple Wallpaper Changer
-======
-
-**Brief: Here is a tiny script that automatically changes wallpaper at regular intervals in your Linux desktop.**
-
-As the name suggests, LittleSimpleWallpaperChanger is a small script that changes the wallpapers randomly at intervals.
-
-Now I know that there is a random wallpaper option in the ‘Appearance’ or the ‘Change desktop background’ settings. But that randomly changes the pre-installed wallpapers and not the wallpapers that you add.
-
-So in this article, we’ll be seeing how to set up a random desktop wallpaper setup consisting of your photos using LittleSimpleWallpaperChanger.
-
-### Little Simple Wallpaper Changer (LSWC)
-
-[LittleSimpleWallpaperChanger][1] or LSWC is a very lightweight script that runs in the background, changing the wallpapers from the user-specified folder. The wallpapers change at a random interval between 1 to 5 minutes. The software is rather simple to set up, and once set up, the user can just forget about it.
-
-![Little Simple Wallpaper Changer to change wallpapers in Linux][2]
-
-#### Installing LSWC
-
-Download LSWC by [clicking on this link.][3] The zipped file is around 15 KB in size.
-
- * Browse to the download location.
- * Right click on the downloaded .zip file and select ‘extract here’.
- * Open the extracted folder, right click and select ‘Open in terminal’.
- * Copy paste the command in the terminal and hit enter.
-`bash ./README_and_install.sh`
- * Now a dialogue box will pop up asking you to select the folder containing the wallpapers. Click on it and then select the folder that you’ve stored your wallpapers in.
- * That’s it. Reboot your computer.
-
-
-
-![Little Simple Wallpaper Changer for Linux][4]
-
-#### Using LSWC
-
-On installation, LSWC asks you to select the folder containing your wallpapers. So I suggest you create a folder and move all the wallpapers you want to use there before we install LSWC. Or you can just use the ‘Wallpapers’ folder in the Pictures folder. **All the wallpapers need to be .jpg format.**
-
-You can add more wallpapers or delete the current wallpapers from your selected folder. To change the wallpapers folder location, you can edit the location of the wallpapers in the
-following file.
-```
-.config/lswc/homepath.conf
-
-```
-
-#### To remove LSWC
-
-Open a terminal and run the below command to stop LSWC
-```
-pkill lswc
-
-```
-
-Open home in your file manager and press ctrl+H to show hidden files, then delete the following files:
-
- * ‘scripts’ folder from .local
- * ‘lswc’ folder from .config
- * ‘lswc.desktop’ file from .config/autostart
-
-
-
-There you have it. How to create your own desktop background slideshow. LSWC is really lightweight and simple to use. Install it and then forget it.
-
-LSWC is not very feature rich but that intentional. It does what it intends to do and that is to change wallpapers. If you want a tool that automatically downloads wallpapers try [WallpaperDownloader][5].
-
-Do share your thoughts on this nifty little software in the comments section below. Don’t forget to share this article. Cheers.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/little-simple-wallpaper-changer/
-
-作者:[Aquil Roshan][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/aquil/
-[1]:https://github.com/LittleSimpleWallpaperChanger/lswc
-[2]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/05/Little-simple-wallpaper-changer-2-800x450.jpg
-[3]:https://github.com/LittleSimpleWallpaperChanger/lswc/raw/master/Lswc.zip
-[4]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/05/Little-simple-wallpaper-changer-1-800x450.jpg
-[5]:https://itsfoss.com/wallpaperdownloader-linux/
diff --git a/sources/tech/20180622 How to Check Disk Space on Linux from the Command Line.md b/sources/tech/20180622 How to Check Disk Space on Linux from the Command Line.md
deleted file mode 100644
index c69e6459fc..0000000000
--- a/sources/tech/20180622 How to Check Disk Space on Linux from the Command Line.md
+++ /dev/null
@@ -1,181 +0,0 @@
-How to Check Disk Space on Linux from the Command Line
-======
-
-
-
-Quick question: How much space do you have left on your drives? A little or a lot? Follow up question: Do you know how to find out? If you happen to use a GUI desktop (e.g., GNOME, KDE, Mate, Pantheon, etc.), the task is probably pretty simple. But what if you’re looking at a headless server, with no GUI? Do you need to install tools for the task? The answer is a resounding no. All the necessary bits are already in place to help you find out exactly how much space remains on your drives. In fact, you have two very easy-to-use options at the ready.
-
-In this article, I’ll demonstrate these tools. I’ll be using [Elementary OS][1], which also includes a GUI option, but we’re going to limit ourselves to the command line. The good news is these command-line tools are readily available for every Linux distribution. On my testing system, there are a number of attached drives (both internal and external). The commands used are agnostic to where a drive is plugged in; they only care that the drive is mounted and visible to the operating system.
-
-With that said, let’s take a look at the tools.
-
-### df
-
-The df command is the tool I first used to discover drive space on Linux, way back in the 1990s. It’s very simple in both usage and reporting. To this day, df is my go-to command for this task. This command has a few switches but, for basic reporting, you really only need one. That command is df -H. The -H switch is for human-readable format. The output of df -H will report how much space is used, available, percentage used, and the mount point of every disk attached to your system (Figure 1).
-
-
-![df output][3]
-
-Figure 1: The output of df -H on my Elementary OS system.
-
-[Used with permission][4]
-
-What if your list of drives is exceedingly long and you just want to view the space used on a single drive? With df, that is possible. Let’s take a look at how much space has been used up on our primary drive, located at /dev/sda1. To do that, issue the command:
-```
-df -H /dev/sda1
-
-```
-
-The output will be limited to that one drive (Figure 2).
-
-
-![disk usage][6]
-
-Figure 2: How much space is on one particular drive?
-
-[Used with permission][4]
-
-You can also limit the reported fields shown in the df output. Available fields are:
-
- * source — the file system source
-
- * size — total number of blocks
-
- * used — spaced used on a drive
-
- * avail — space available on a drive
-
- * pcent — percent of used space, divided by total size
-
- * target — mount point of a drive
-
-
-
-
-Let’s display the output of all our drives, showing only the size, used, and avail (or availability) fields. The command for this would be:
-```
-df -H --output=size,used,avail
-
-```
-
-The output of this command is quite easy to read (Figure 3).
-
-
-![output][8]
-
-Figure 3: Specifying what output to display for our drives.
-
-[Used with permission][4]
-
-The only caveat here is that we don’t know the source of the output, so we’d want to include source like so:
-```
-df -H --output=source,size,used,avail
-
-```
-
-Now the output makes more sense (Figure 4).
-
-![source][10]
-
-Figure 4: We now know the source of our disk usage.
-
-[Used with permission][4]
-
-### du
-
-Our next command is du. As you might expect, that stands for disk usage. The du command is quite different to the df command, in that it reports on directories and not drives. Because of this, you’ll want to know the names of directories to be checked. Let’s say I have a directory containing virtual machine files on my machine. That directory is /media/jack/HALEY/VIRTUALBOX. If I want to find out how much space is used by that particular directory, I’d issue the command:
-```
-du -h /media/jack/HALEY/VIRTUALBOX
-
-```
-
-The output of the above command will display the size of every file in the directory (Figure 5).
-
-![du command][12]
-
-Figure 5: The output of the du command on a specific directory.
-
-[Used with permission][4]
-
-So far, this command isn’t all that helpful. What if we want to know the total usage of a particular directory? Fortunately, du can handle that task. On the same directory, the command would be:
-```
-du -sh /media/jack/HALEY/VIRTUALBOX/
-
-```
-
-Now we know how much total space the files are using up in that directory (Figure 6).
-
-![space used][14]
-
-Figure 6: My virtual machine files are using 559GB of space.
-
-[Used with permission][4]
-
-You can also use this command to see how much space is being used on all child directories of a parent, like so:
-```
-du -h /media/jack/HALEY
-
-```
-
-The output of this command (Figure 7) is a good way to find out what subdirectories are hogging up space on a drive.
-
-![directories][16]
-
-Figure 7: How much space are my subdirectories using?
-
-[Used with permission][4]
-
-The du command is also a great tool to use in order to see a list of directories that are using the most disk space on your system. The way to do this is by piping the output of du to two other commands: sort and head. The command to find out the top 10 directories eating space on a drive would look something like this:
-```
-du -a /media/jack | sort -n -r | head -n 10
-
-```
-
-The output would list out those directories, from largest to least offender (Figure 8).
-
-![top users][18]
-
-Figure 8: Our top ten directories using up space on a drive.
-
-[Used with permission][4]
-
-### Not as hard as you thought
-
-Finding out how much space is being used on your Linux-attached drives is quite simple. As long as your drives are mounted to the Linux system, both df and du will do an outstanding job of reporting the necessary information. With df you can quickly see an overview of how much space is used on a disk and with du you can discover how much space is being used by specific directories. These two tools in combination should be considered must-know for every Linux administrator.
-
-And, in case you missed it, I recently showed how to [determine your memory usage on Linux][19]. Together, these tips will go a long way toward helping you successfully manage your Linux servers.
-
-Learn more about Linux through the free ["Introduction to Linux"][20]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/learn/intro-to-linux/2018/6how-check-disk-space-linux-command-line
-
-作者:[Jack Wallen][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://www.linux.com/users/jlwallen
-[1]:https://elementary.io/
-[2]:/files/images/diskspace1jpg
-[3]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_1.jpg?itok=aJa8AZAM (df output)
-[4]:https://www.linux.com/licenses/category/used-permission
-[5]:/files/images/diskspace2jpg
-[6]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_2.jpg?itok=_PAq3kxC (disk usage)
-[7]:/files/images/diskspace3jpg
-[8]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_3.jpg?itok=51m8I-Vu (output)
-[9]:/files/images/diskspace4jpg
-[10]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_4.jpg?itok=SuwgueN3 (source)
-[11]:/files/images/diskspace5jpg
-[12]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_5.jpg?itok=XfS4s7Zq (du command)
-[13]:/files/images/diskspace6jpg
-[14]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_6.jpg?itok=r71qICyG (space used)
-[15]:/files/images/diskspace7jpg
-[16]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_7.jpg?itok=PtDe4q5y (directories)
-[17]:/files/images/diskspace8jpg
-[18]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/diskspace_8.jpg?itok=v9E1SFcC (top users)
-[19]:https://www.linux.com/learn/5-commands-checking-memory-usage-linux
-[20]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180623 Don-t Install Yaourt- Use These Alternatives for AUR in Arch Linux.md b/sources/tech/20180623 Don-t Install Yaourt- Use These Alternatives for AUR in Arch Linux.md
deleted file mode 100644
index b2e4eed821..0000000000
--- a/sources/tech/20180623 Don-t Install Yaourt- Use These Alternatives for AUR in Arch Linux.md
+++ /dev/null
@@ -1,203 +0,0 @@
-Don’t Install Yaourt! Use These Alternatives for AUR in Arch Linux
-======
-**Brief: Yaourt had been the most popular AUR helper, but it is not being developed anymore. In this article, we list out some of the best alternatives to Yaourt for Arch based Linux distributions. **
-
-[Arch User Repository][1] popularly known as AUR is the community-driven software repository for Arch users. Debian/Ubuntu users can think of AUR as the equivalent of PPA.
-
-It contains the packages that are not directly endorsed by [Arch Linux][2]. If someone develops a software or package for Arch Linux, it can be provided through this community repositories. This enables the end-user to access more software than what they get by default.
-
-So, how do you use AUR then? Well, you need a different tool to install software from AUR. Arch’s package manager [pacman][3] doesn’t support it directly. These ‘special tools’ are called [AUR helpers][4].
-
-Yaourt (Yet AnOther User Repository Tool) is/was a wrapper for pacman that helps to install AUR packages on Arch Linux. It uses the same syntax as pacman. Yaourt has great support for Arch User Repository for searching, installing, conflict resolution and dependency maintenance.
-
-However, Yaourt development has been slow lately and is [listed][5] as “Discontinued or problematic” on Arch Wiki. [Many Arch User believe it’s not secure][6] and hence go towards a different AUR helper.
-
-![AUR Helpers other than Yaourt][7]
-
-In this article, we will see the best Yaourt alternatives that you can use for installing software from AUR.
-
-### Best AUR helpers to use AUR
-
-I am deliberating omitting some of the other popular AUR helpers like trizen or packer because they too have been flagged as ‘discontinued or problematic’.
-
-#### 1\. aurman
-
-[aurman][8] is one of the best AUR helpers and serves pretty well as an alternative to Yaourt. It has almost similar syntax to pacman with support for all pacman operations. You can search the AUR, resolve dependencies, check PKGBUILD content before a package build etc.
-
-##### Features of aurman
-
- * aurman supports all pacman operations and incorporates reliable dependency resolving, conflict detection and split package support.
- * Threaded sudo loop runs in the background saving you from entering your password each time.
- * Provides development package support and distincts between explictily and inlicitly installed packages.
- * Support for searching of AUR packages and repositories.
- * You can see and edit the PKGBUILDs before starting AUR package build.
- * It can also be used as a standalone [dependency solver][9].
-
-
-
-##### Installing aurman
-```
-git clone https://aur.archlinux.org/aurman.git
-cd aurman
-makepkg -si
-
-```
-
-##### Using aurman
-
-Searching for an application through aurman in Arch User Repository is done in the following manner:
-```
-aurman -Ss
-
-```
-
-Installing an application using aurman:
-```
-aurman -S <package-name>
-
-```
-
-#### 2\. yay
-
-[yay][10] is the next best AUR helper written in Go with the objective of providing an interface of pacman with minimal user input, yaourt like search and with almost no dependencies.
-
-##### Features of yay
-
- * yay provides AUR table completion and download the PKGBUILD from ABS or AUR.
- * Supports search narrowing and no sourcing of PKGBUILD.
- * The binary has no additional dependencies than pacman.
- * Provides advanced dependency solver and remove make dependencies at the end of the build process.
- * Supports colored output when you enable Color option in the /etc/pacman.conf file.
- * It can be made to support only AUR package or only repo packages.
-
-
-
-##### Installing yay
-
-You can install yay by cloning the git repo and building it. Use the below command to install yay in Arch Linux :
-```
-git clone https://aur.archlinux.org/yay.git
-cd yay
-makepkg -si
-
-```
-
-##### Using yay
-
-Searching an application through Yay in AUR:
-```
-yay -Ss
-
-```
-
-Installing an application:
-```
-yay -S
-
-```
-
-#### 3\. pakku
-
-[Pakku][11] is another pacman wrapper which is still in its initial stage. However, just because its new doesn’t mean its lacking any of the features supported by other AUR helper. It does its job pretty nice and along with searching and installing applications from AUR, it removes dependencies after a build.
-
-##### Features of pakku
-
- * Searching and installing packages from Arch User Repository.
- * Viewing files and changes between builds.
- * Building packages from official repositories and removing make dependencies after a build.
- * PKGBUILD retrieving and Pacman integration.
- * Pacman-like user interface and pacman options supports.
- * Pacman configuration supports and no PKGBUILD sourcing.
-
-
-
-##### Installing pakku
-```
-git clone https://aur.archlinux.org/pakku.git
-cd pakku
-makepkg -si
-
-```
-
-##### Using pakku
-
-You can search an application from AUR using below command.:
-```
-pakku -Ss spotify
-
-```
-
-And then the package can be installed similar to pacman:
-```
-pakku -S spotify
-
-```
-
-#### 4\. aurutils
-
-[aurutils][12] is basically a collection of scripts that automates the usage of Arch User Repository. It can search AUR, check updates for different applications installed and settle up dependencies issues.
-
-##### Features of aurutils
-
- * aurutils uses a local repository which gives it a benefit of pacman file support, and all packages works with –asdeps.
- * There can be multiple repos for different tasks.
- * Update local repository in one go with aursync -u
- * pkgbase, long format and raw support for aursearch
- * Ability to ignore package
-
-
-
-##### Installing aurutils
-```
-git clone https://aur.archlinux.org/aurutils.git
-cd aurutils
-makepkg -si
-
-```
-
-##### Using aurutils
-
-Searching an application via aurutils:
-```
-aurutils -Ss
-
-```
-
-Installing a package from AUR:
-```
-aurutils -S
-
-```
-
-All of these packages can directly be installed if you are already using Yaourt or any other AUR helper.
-
-#### Final Words on AUR helpers
-
-Arch Linux has some [more AUR helper][4] that can automate certain tasks for the Arch User Repository. Many users are still using Yaourt for their AUR-work and
-
-The choice differs for each user and we would like to know which one you use for your Arch Linux. Let us know in the comments.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/best-aur-helpers/
-
-作者:[Ambarish Kumar][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/ambarish/
-[1]:https://wiki.archlinux.org/index.php/Arch_User_Repository
-[2]:https://www.archlinux.org/
-[3]:https://wiki.archlinux.org/index.php/pacman
-[4]:https://wiki.archlinux.org/index.php/AUR_helpers
-[5]:https://wiki.archlinux.org/index.php/AUR_helpers#Comparison_table
-[6]:https://www.reddit.com/r/archlinux/comments/4azqyb/whats_so_bad_with_yaourt/
-[7]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/06/no-yaourt-arch-800x450.jpeg
-[8]:https://github.com/polygamma/aurman
-[9]:https://github.com/polygamma/aurman/wiki/Using-aurman-as-dependency-solver
-[10]:https://github.com/Jguer/yay
-[11]:https://github.com/kitsunyan/pakku
-[12]:https://github.com/AladW/aurutils
diff --git a/sources/tech/20180623 Intercepting and Emulating Linux System Calls with Ptrace - null program.md b/sources/tech/20180623 Intercepting and Emulating Linux System Calls with Ptrace - null program.md
deleted file mode 100644
index 08fde90f66..0000000000
--- a/sources/tech/20180623 Intercepting and Emulating Linux System Calls with Ptrace - null program.md
+++ /dev/null
@@ -1,293 +0,0 @@
-Intercepting and Emulating Linux System Calls with Ptrace « null program
-======
-
-The `ptrace(2)` (“process trace”) system call is usually associated with debugging. It’s the primary mechanism through which native debuggers monitor debuggees on unix-like systems. It’s also the usual approach for implementing [strace][1] — system call trace. With Ptrace, tracers can pause tracees, [inspect and set registers and memory][2], monitor system calls, or even intercept system calls.
-
-By intercept, I mean that the tracer can mutate system call arguments, mutate the system call return value, or even block certain system calls. Reading between the lines, this means a tracer can fully service system calls itself. This is particularly interesting because it also means **a tracer can emulate an entire foreign operating system**. This is done without any special help from the kernel beyond Ptrace.
-
-The catch is that a process can only have one tracer attached at a time, so it’s not possible emulate a foreign operating system while also debugging that process with, say, GDB. The other issue is that emulated systems calls will have higher overhead.
-
-For this article I’m going to focus on [Linux’s Ptrace][3] on x86-64, and I’ll be taking advantage of a few Linux-specific extensions. For the article I’ll also be omitting error checks, but the full source code listings will have them.
-
-You can find runnable code for the examples in this article here:
-
-****
-
-### strace
-
-Before getting into the really interesting stuff, let’s start by reviewing a bare bones implementation of strace. It’s [no DTrace][4], but strace is still incredibly useful.
-
-Ptrace has never been standardized. Its interface is similar across different operating systems, especially in its core functionality, but it’s still subtly different from system to system. The `ptrace(2)` prototype generally looks something like this, though the specific types may be different.
-```
-long ptrace(int request, pid_t pid, void *addr, void *data);
-
-```
-
-The `pid` is the tracee’s process ID. While a tracee can have only one tracer attached at a time, a tracer can be attached to many tracees.
-
-The `request` field selects a specific Ptrace function, just like the `ioctl(2)` interface. For strace, only two are needed:
-
- * `PTRACE_TRACEME`: This process is to be traced by its parent.
- * `PTRACE_SYSCALL`: Continue, but stop at the next system call entrance or exit.
- * `PTRACE_GETREGS`: Get a copy of the tracee’s registers.
-
-
-
-The other two fields, `addr` and `data`, serve as generic arguments for the selected Ptrace function. One or both are often ignored, in which case I pass zero.
-
-The strace interface is essentially a prefix to another command.
-```
-$ strace [strace options] program [arguments]
-
-```
-
-My minimal strace doesn’t have any options, so the first thing to do — assuming it has at least one argument — is `fork(2)` and `exec(2)` the tracee process on the tail of `argv`. But before loading the target program, the new process will inform the kernel that it’s going to be traced by its parent. The tracee will be paused by this Ptrace system call.
-```
-pid_t pid = fork();
-switch (pid) {
- case -1: /* error */
- FATAL("%s", strerror(errno));
- case 0: /* child */
- ptrace(PTRACE_TRACEME, 0, 0, 0);
- execvp(argv[1], argv + 1);
- FATAL("%s", strerror(errno));
-}
-
-```
-
-The parent waits for the child’s `PTRACE_TRACEME` using `wait(2)`. When `wait(2)` returns, the child will be paused.
-```
-waitpid(pid, 0, 0);
-
-```
-
-Before allowing the child to continue, we tell the operating system that the tracee should be terminated along with its parent. A real strace implementation may want to set other options, such as `PTRACE_O_TRACEFORK`.
-```
-ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL);
-
-```
-
-All that’s left is a simple, endless loop that catches on system calls one at a time. The body of the loop has four steps:
-
- 1. Wait for the process to enter the next system call.
- 2. Print a representation of the system call.
- 3. Allow the system call to execute and wait for the return.
- 4. Print the system call return value.
-
-
-
-The `PTRACE_SYSCALL` request is used in both waiting for the next system call to begin, and waiting for that system call to exit. As before, a `wait(2)` is needed to wait for the tracee to enter the desired state.
-```
-ptrace(PTRACE_SYSCALL, pid, 0, 0);
-waitpid(pid, 0, 0);
-
-```
-
-When `wait(2)` returns, the registers for the thread that made the system call are filled with the system call number and its arguments. However, the operating system has not yet serviced this system call. This detail will be important later.
-
-The next step is to gather the system call information. This is where it gets architecture specific. On x86-64, [the system call number is passed in `rax`][5], and the arguments (up to 6) are passed in `rdi`, `rsi`, `rdx`, `r10`, `r8`, and `r9`. Reading the registers is another Ptrace call, though there’s no need to `wait(2)` since the tracee isn’t changing state.
-```
-struct user_regs_struct regs;
-ptrace(PTRACE_GETREGS, pid, 0, ®s);
-long syscall = regs.orig_rax;
-
-fprintf(stderr, "%ld(%ld, %ld, %ld, %ld, %ld, %ld)",
- syscall,
- (long)regs.rdi, (long)regs.rsi, (long)regs.rdx,
- (long)regs.r10, (long)regs.r8, (long)regs.r9);
-
-```
-
-There’s one caveat. For [internal kernel purposes][6], the system call number is stored in `orig_rax` rather than `rax`. All the other system call arguments are straightforward.
-
-Next it’s another `PTRACE_SYSCALL` and `wait(2)`, then another `PTRACE_GETREGS` to fetch the result. The result is stored in `rax`.
-```
-ptrace(PTRACE_GETREGS, pid, 0, ®s);
-fprintf(stderr, " = %ld\n", (long)regs.rax);
-
-```
-
-The output from this simple program is very crude. There is no symbolic name for the system call and every argument is printed numerically, even if it’s a pointer to a buffer. A more complete strace would know which arguments are pointers and use `process_vm_readv(2)` to read those buffers from the tracee in order to print them appropriately.
-
-However, this does lay the groundwork for system call interception.
-
-### System call interception
-
-Suppose we want to use Ptrace to implement something like OpenBSD’s [`pledge(2)`][7], in which [a process pledges to use only a restricted set of system calls][8]. The idea is that many programs typically have an initialization phase where they need lots of system access (opening files, binding sockets, etc.). After initialization they enter a main loop in which they processing input and only a small set of system calls are needed.
-
-Before entering this main loop, a process can limit itself to the few operations that it needs. If [the program has a flaw][9] allowing it to be exploited by bad input, the pledge significantly limits what the exploit can accomplish.
-
-Using the same strace model, rather than print out all system calls, we could either block certain system calls or simply terminate the tracee when it misbehaves. Termination is easy: just call `exit(2)` in the tracer. Since it’s configured to also terminate the tracee. Blocking the system call and allowing the child to continue is a little trickier.
-
-The tricky part is that **there’s no way to abort a system call once it’s started**. When tracer returns from `wait(2)` on the entrance to the system call, the only way to stop a system call from happening is to terminate the tracee.
-
-However, not only can we mess with the system call arguments, we can change the system call number itself, converting it to a system call that doesn’t exist. On return we can report a “friendly” `EPERM` error in `errno` [via the normal in-band signaling][10].
-```
-for (;;) {
- /* Enter next system call */
- ptrace(PTRACE_SYSCALL, pid, 0, 0);
- waitpid(pid, 0, 0);
-
- struct user_regs_struct regs;
- ptrace(PTRACE_GETREGS, pid, 0, ®s);
-
- /* Is this system call permitted? */
- int blocked = 0;
- if (is_syscall_blocked(regs.orig_rax)) {
- blocked = 1;
- regs.orig_rax = -1; // set to invalid syscall
- ptrace(PTRACE_SETREGS, pid, 0, ®s);
- }
-
- /* Run system call and stop on exit */
- ptrace(PTRACE_SYSCALL, pid, 0, 0);
- waitpid(pid, 0, 0);
-
- if (blocked) {
- /* errno = EPERM */
- regs.rax = -EPERM; // Operation not permitted
- ptrace(PTRACE_SETREGS, pid, 0, ®s);
- }
-}
-
-```
-
-This simple example only checks against a whitelist or blacklist of system calls. And there’s no nuance, such as allowing files to be opened (`open(2)`) read-only but not as writable, allowing anonymous memory maps but not non-anonymous mappings, etc. There’s also no way to the tracee to dynamically drop privileges.
-
-How could the tracee communicate to the tracer? Use an artificial system call!
-
-### Creating an artificial system call
-
-For my new pledge-like system call — which I call `xpledge()` to distinguish it from the real thing — I picked system call number 10000, a nice high number that’s unlikely to ever be used for a real system call.
-```
-#define SYS_xpledge 10000
-
-```
-
-Just for demonstration purposes, I put together a minuscule interface that’s not good for much in practice. It has little in common with OpenBSD’s `pledge(2)`, which uses a [string interface][11]. Actually designing robust and secure sets of privileges is really complicated, as the `pledge(2)` manpage shows. Here’s the entire interface and implementation of the system call for the tracee:
-```
-#define _GNU_SOURCE
-#include
-
-#define XPLEDGE_RDWR (1 << 0)
-#define XPLEDGE_OPEN (1 << 1)
-
-#define xpledge(arg) syscall(SYS_xpledge, arg)
-
-```
-
-If it passes zero for the argument, only a few basic system calls are allowed, including those used to allocate memory (e.g. `brk(2)`). The `PLEDGE_RDWR` bit allows [various][12] read and write system calls (`read(2)`, `readv(2)`, `pread(2)`, `preadv(2)`, etc.). The `PLEDGE_OPEN` bit allows `open(2)`.
-
-To prevent privileges from being escalated back, `pledge()` blocks itself — though this also prevents dropping more privileges later down the line.
-
-In the xpledge tracer, I just need to check for this system call:
-```
-/* Handle entrance */
-switch (regs.orig_rax) {
- case SYS_pledge:
- register_pledge(regs.rdi);
- break;
-}
-
-```
-
-The operating system will return `ENOSYS` (Function not implemented) since this isn’t a real system call. So on the way out I overwrite this with a success (0).
-```
-/* Handle exit */
-switch (regs.orig_rax) {
- case SYS_pledge:
- ptrace(PTRACE_POKEUSER, pid, RAX * 8, 0);
- break;
-}
-
-```
-
-I wrote a little test program that opens `/dev/urandom`, makes a read, tries to pledge, then tries to open `/dev/urandom` a second time, then confirms it can read from the original `/dev/urandom` file descriptor. Running without a pledge tracer, the output looks like this:
-```
-$ ./example
-fread("/dev/urandom")[1] = 0xcd2508c7
-XPledging...
-XPledge failed: Function not implemented
-fread("/dev/urandom")[2] = 0x0be4a986
-fread("/dev/urandom")[1] = 0x03147604
-
-```
-
-Making an invalid system call doesn’t crash an application. It just fails, which is a rather convenient fallback. When run under the tracer, it looks like this:
-```
-$ ./xpledge ./example
-fread("/dev/urandom")[1] = 0xb2ac39c4
-XPledging...
-fopen("/dev/urandom")[2]: Operation not permitted
-fread("/dev/urandom")[1] = 0x2e1bd1c4
-
-```
-
-The pledge succeeds but the second `fopen(3)` does not since the tracer blocked it with `EPERM`.
-
-This concept could be taken much further, to, say, change file paths or return fake results. A tracer could effectively chroot its tracee, prepending some chroot path to the root of any path passed through a system call. It could even lie to the process about what user it is, claiming that it’s running as root. In fact, this is exactly how the [Fakeroot NG][13] program works.
-
-### Foreign system emulation
-
-Suppose you don’t just want to intercept some system calls, but all system calls. You’ve got [a binary intended to run on another operating system][14], so none of the system calls it makes will ever work.
-
-You could manage all this using only what I’ve described so far. The tracer would always replace the system call number with a dummy, allow it to fail, then service the system call itself. But that’s really inefficient. That’s essentially three context switches for each system call: one to stop on the entrance, one to make the always-failing system call, and one to stop on the exit.
-
-The Linux version of PTrace has had a more efficient operation for this technique since 2005: `PTRACE_SYSEMU`. PTrace stops only once per a system call, and it’s up to the tracer to service that system call before allowing the tracee to continue.
-```
-for (;;) {
- ptrace(PTRACE_SYSEMU, pid, 0, 0);
- waitpid(pid, 0, 0);
-
- struct user_regs_struct regs;
- ptrace(PTRACE_GETREGS, pid, 0, ®s);
-
- switch (regs.orig_rax) {
- case OS_read:
- /* ... */
-
- case OS_write:
- /* ... */
-
- case OS_open:
- /* ... */
-
- case OS_exit:
- /* ... */
-
- /* ... and so on ... */
- }
-}
-
-```
-
-To run binaries for the same architecture from any system with a stable (enough) system call ABI, you just need this `PTRACE_SYSEMU` tracer, a loader (to take the place of `exec(2)`), and whatever system libraries the binary needs (or only run static binaries).
-
-In fact, this sounds like a fun weekend project.
-
---------------------------------------------------------------------------------
-
-via: http://nullprogram.com/blog/2018/06/23/
-
-作者:[Chris Wellons][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]:http://nullprogram.com
-[1]:https://blog.plover.com/Unix/strace-groff.html
-[2]:http://nullprogram.com/blog/2016/09/03/
-[3]:http://man7.org/linux/man-pages/man2/ptrace.2.html
-[4]:http://nullprogram.com/blog/2018/01/17/
-[5]:http://nullprogram.com/blog/2015/05/15/
-[6]:https://stackoverflow.com/a/6469069
-[7]:https://man.openbsd.org/pledge.2
-[8]:http://www.openbsd.org/papers/hackfest2015-pledge/mgp00001.html
-[9]:http://nullprogram.com/blog/2017/07/19/
-[10]:http://nullprogram.com/blog/2016/09/23/
-[11]:https://www.tedunangst.com/flak/post/string-interfaces
-[12]:http://nullprogram.com/blog/2017/03/01/
-[13]:https://fakeroot-ng.lingnu.com/index.php/Home_Page
-[14]:http://nullprogram.com/blog/2017/11/30/
diff --git a/sources/tech/20180625 How To Upgrade Everything Using A Single Command In Linux.md b/sources/tech/20180625 How To Upgrade Everything Using A Single Command In Linux.md
deleted file mode 100644
index 741cd82f0d..0000000000
--- a/sources/tech/20180625 How To Upgrade Everything Using A Single Command In Linux.md
+++ /dev/null
@@ -1,123 +0,0 @@
-How To Upgrade Everything Using A Single Command In Linux
-======
-
-
-
-As we all know already, keeping our Linux system up-to-date involves invoking more than one package manager. Say for instance, in Ubuntu you can’t upgrade everything using “sudo apt update && sudo apt upgrade” command. This command will only upgrade the applications which are installed using APT package manager. There are chances that you might have installed some other applications using **cargo** , [**pip**][1], **npm** , **snap** , **flatpak** or [**Linuxbrew**][2] package managers. You need to use the respective package manager in order to keep them all updated. Not anymore! Say hello to **“topgrade”** , an utility to upgrade all the things in your system in one go.
-
-You need not to run every package manager to update the packages. The topgrade tool resolves this problem by detecting the installed packages, tools, plugins and run their appropriate package manager to update everything in your Linux box with a single command. It is free, open source and written using **rust programming language**. It supports GNU/Linux and Mac OS X.
-
-### Upgrade Everything Using A Single Command In Linux
-
-The topgrade is available in AUR. So, you can install it using [**Yay**][3] helper program in any Arch-based systems.
-```
-$ yay -S topgrade
-
-```
-
-On other Linux distributions, you can install topgrade utility using **cargo** package manager. To install cargo package manager, refer the following link.
-
-And, then run the following command to install topgrade.
-```
-$ cargo install topgrade
-
-```
-
-Once installed, run the topgrade to upgrade all the things in your Linux system.
-```
-$ topgrade
-
-```
-
-Once topgrade is invoked, it will perform the following tasks one by one. You will be asked to enter root/sudo user password wherever necessary.
-
-1 Run your system’s package manager:
-
- * Arch: Run **yay** or fall back to [**pacman**][4]
- * CentOS/RHEL: Run `yum upgrade`
- * Fedora – Run `dnf upgrade`
- * Debian/Ubuntu: Run `apt update && apt dist-upgrade`
- * Linux/macOS: Run `brew update && brew upgrade`
-
-
-
-2\. Check if the following paths are tracked by Git. If so, pull them:
-
- * ~/.emacs.d (Should work whether you use **Spacemacs** or a custom configuration)
- * ~/.zshrc
- * ~/.oh-my-zsh
- * ~/.tmux
- * ~/.config/fish/config.fish
- * Custom defined paths
-
-
-
-3\. Unix: Run **zplug** update
-
-4\. Unix: Upgrade **tmux** plugins with **TPM**
-
-5\. Run **Cargo install-update**
-
-6\. Upgrade **Emacs** packages
-
-7\. Upgrade Vim packages. Works with the following plugin frameworks:
-
- * NeoBundle
- * [**Vundle**][5]
- * Plug
-
-
-
-8\. Upgrade [**NPM**][6] globally installed packages
-
-9\. Upgrade **Atom** packages
-
-10\. Update [**Flatpak**][7] packages
-
-11\. Update [**snap**][8] packages
-
-12\. **Linux:** Run **fwupdmgr** to show firmware upgrade. (View only. No upgrades will actually be performed)
-
-13\. Run custom defined commands.
-
-Finally, topgrade utility will run **needrestart** to restart all services. In Mac OS X, it will upgrade App Store applications.
-
-Sample output from my Ubuntu 18.04 LTS test box:
-
-![][10]
-
-The good thing is if one task is failed, it will automatically run the next task and complete all other subsequent tasks. Finally, it will display the summary with details such as how many tasks did it run, how many succeeded and how many failed etc.
-
-![][11]
-
-**Suggested read:**
-
-Personally, I liked this idea of creating an utility like topgrade and upgrade everything installed with various package managers with a single command. I hope you find it useful too. More good stuffs to come. Stay tuned!
-
-Cheers!
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/how-to-upgrade-everything-using-a-single-command-in-linux/
-
-作者:[SK][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://www.ostechnix.com/author/sk/
-[1]:https://www.ostechnix.com/manage-python-packages-using-pip/
-[2]:https://www.ostechnix.com/linuxbrew-common-package-manager-linux-mac-os-x/
-[3]:https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
-[4]:https://www.ostechnix.com/getting-started-pacman/
-[5]:https://www.ostechnix.com/manage-vim-plugins-using-vundle-linux/
-[6]:https://www.ostechnix.com/manage-nodejs-packages-using-npm/
-[7]:https://www.ostechnix.com/flatpak-new-framework-desktop-applications-linux/
-[8]:https://www.ostechnix.com/install-snap-packages-arch-linux-fedora/
-[9]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[10]:http://www.ostechnix.com/wp-content/uploads/2018/06/topgrade-1.png
-[11]:http://www.ostechnix.com/wp-content/uploads/2018/06/topgrade-2.png
diff --git a/sources/tech/20180625 How to install Pipenv on Fedora.md b/sources/tech/20180625 How to install Pipenv on Fedora.md
deleted file mode 100644
index e1099d5ded..0000000000
--- a/sources/tech/20180625 How to install Pipenv on Fedora.md
+++ /dev/null
@@ -1,95 +0,0 @@
-translating---geekpi
-
-How to install Pipenv on Fedora
-======
-
-
-
-Pipenv aims to bring the best of all packaging worlds (bundler, composer, npm, cargo, yarn, etc.) to the Python world. It tries to solve a couple of problems and also simplify the whole management process.
-
-Currently the management of Python application dependencies sometimes seems like a bit of a challenge. Developers usually create a [virtual environment][1] for each new project and install dependencies into it using [pip][2]. In addition they have to store the set of installed packages into the requirements.txt text file. We’ve seen many tools and wrappers that aim to automate this workflow. However, there was still necessity to combine multiple utilities and the requirements.txt format itself is not ideal for more complicated scenarios.
-
-### One tol to rule them all
-
-Pipenv manages complex inter-dependencies properly and it also provides manual documenting of installed packages. For example development, testing and production environments often require a different set of packages. It used to be necessary to maintain multiple requirements.txt per project. Pipenv introduces the new [Pipfile][3] format using [TOML][4] syntax. Thanks to this format, you can finally maintain multiple set of requirement for different environments in a single file.
-
-Pipenv has become the officially recommended tool for managing Python application dependencies only a year after the first lines of code were committed into the project. Now it is finally available as an package in Fedora repositories as well.
-
-### Installing Pipenv on Fedora
-
-On clean installation of Fedora 28 and later you can simply install Pipenv by running this command at the terminal:
-```
-$ sudo dnf install pipenv
-
-```
-
-Your system is now ready to start working on your new Python 3 application with help of Pipenv.
-
-The important point is that while this tool provides nice solution for the applications, it is not designed for dealing with library requirements. When writing a Python library, pinning dependencies is not desirable. You should rather specify install_requires in setup.py file.
-
-### Basic dependencies management
-
-Create a directory for your project first:
-```
-$ mkdir new-project && cd new-project
-
-```
-
-Another step is to create a virtual environment for this project:
-```
-$ pipenv --three
-
-```
-
-The –three option here sets the Python version of the virtual environment to Python 3.
-
-Install dependencies:
-```
-$ pipenv install requests
-Installing requests…
-Adding requests to Pipfile's [packages]…
-Pipfile.lock not found, creating…
-Locking [dev-packages] dependencies…
-Locking [packages] dependencies…
-
-```
-
-Finally generate a lockfile:
-```
-$ pipenv lock
-Locking [dev-packages] dependencies…
-Locking [packages] dependencies…
-Updated Pipfile.lock (b14837)
-
-```
-
-You can also check a dependency graph:
-```
-$ pipenv graph
- - certifi [required: >=2017.4.17, installed: 2018.4.16]
-- chardet [required: <3.1.0,>=3.0.2, installed: 3.0.4]
-- idna [required: <2.8,>=2.5, installed: 2.7]
-- urllib3 [required: >=1.21.1,<1.24, installed: 1.23]
-
-```
-
-More details on Pipenv and it commands are available in the [documentation][5].
-
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/install-pipenv-fedora/
-
-作者:[Michal Cyprian][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://fedoramagazine.org/author/mcyprian/
-[1]:https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments
-[2]:https://developer.fedoraproject.org/tech/languages/python/pypi-installation.html
-[3]:https://github.com/pypa/pipfile
-[4]:https://github.com/toml-lang/toml
-[5]:https://docs.pipenv.org/
diff --git a/sources/tech/20180626 TrueOS Doesnt Want to Be BSD for Desktop Anymore.md b/sources/tech/20180626 TrueOS Doesnt Want to Be BSD for Desktop Anymore.md
deleted file mode 100644
index 1a4d55e474..0000000000
--- a/sources/tech/20180626 TrueOS Doesnt Want to Be BSD for Desktop Anymore.md
+++ /dev/null
@@ -1,77 +0,0 @@
-TrueOS Doesn’t Want to Be ‘BSD for Desktop’ Anymore
-============================================================
-
-
-There are some really big changes on the horizon for [TrueOS][9]. Today, we will take a look at what is going on in the world of desktop BSD.
-
-### The Announcement
-
-
-
-The team behind [TrueOS][10] [announced][11] that they would be changing the focus of the project. Up until this point, TrueOS has made it easy to install BSD with a graphical user interface out of the box. However, it will now become “a cutting-edge operating system that keeps all of the stability that you know and love from ZFS ([OpenZFS][12]) and [FreeBSD][13], and adds additional features to create a fresh, innovative operating system. Our goal is to create a core-centric operating system that is modular, functional, and perfect for do-it-yourselfers and advanced users alike.”
-
-Essentially, TrueOs will become a downstream fork of FreeBSD. They will integrate newer software into the system, such as [OpenRC][14] and [LibreSSL][15]. They hope to stick to a 6-month release cycle.
-
-The goal is to make TrueOS so it can be used as the base for other projects to build on. The graphical part will be missing to make it more distro-agnostic.
-
-[Suggested readInterview with MidnightBSD Founder and Lead Dev Lucas Holt][16]
-
-### What about Desktop Users?
-
-If you read my [review of TrueOS][17] and are interested in trying a desktop BSD or already use TrueOS, never fear (which is good advice for life too). All of the desktop elements of TrueOS will be spun off into [Project Trident][18]. Currently, the Project Trident website is very light on details. It seems as though they are still figuring out the logistics of the spin-off.
-
-If you currently have TrueOS, you don’t have to worry about moving. The TrueOS team said that “there will be migration paths available for those that would like to move to other FreeBSD-based distributions like Project Trident or [GhostBSD][19].”
-
-[Suggested readInterview with FreeDOS Founder and Lead Dev Jim Hall][20]
-
-### Thoughts
-
-When I first read the announcement, I was frankly a little worried. Changing names can be a bad idea. Customers will be used to one name, but if the product name changes they could lose track of the project very easily. TrueOS already went through a name change. When the project was started in 2006 it was named PC-BSD, but in 2016 the name was changed to TrueOS. It kinds of reminds me of the [ArchMerge and Arcolinux saga][21].
-
-That being said, I think this will be a good thing for desktop users of BSD. One of the common criticisms that I heard about PC-BSD and TrueOS is that it wasn’t very polished. Separating the two parts of the project will help sharpen the focus of the respective developers. The TrueOS team will be able to add newer features to the slow-moving FreeBSD base and the Project Trident team will be able to improve user’s desktop experience.
-
-I wish both teams well. Remember, people, when someone works on open source, we all benefit even if the work is done on something we don’t use.
-
-What are your thoughts about the future of TrueOS and Project Trident? Please let us know in the comments below.
-
-
-------------------------------
-
-关于作者:
-
-My name is John Paul Wohlscheid. I'm an aspiring mystery writer who loves to play with technology, especially Linux. You can catch up with me at [my personal website][23]
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/trueos-plan-change/
-
-作者:[John Paul Wohlscheid ][a]
-译者:[译者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/
-[1]:https://itsfoss.com/author/john/
-[2]:https://itsfoss.com/trueos-plan-change/#comments
-[3]:https://itsfoss.com/category/bsd/
-[4]:https://itsfoss.com/category/news/
-[5]:https://itsfoss.com/tag/bsd/
-[6]:https://itsfoss.com/tag/freebsd/
-[7]:https://itsfoss.com/tag/project-trident/
-[8]:https://itsfoss.com/tag/trueos/
-[9]:https://www.trueos.org/
-[10]:https://www.trueos.org/
-[11]:https://www.trueos.org/blog/trueosdownstream/
-[12]:http://open-zfs.org/wiki/Main_Page
-[13]:https://www.freebsd.org/
-[14]:https://en.wikipedia.org/wiki/OpenRC
-[15]:http://www.libressl.org/
-[16]:https://itsfoss.com/midnightbsd-founder-lucas-holt/
-[17]:https://itsfoss.com/trueos-bsd-review/
-[18]:http://www.project-trident.org/
-[19]:https://www.ghostbsd.org/
-[20]:https://itsfoss.com/interview-freedos-jim-hall/
-[21]:https://itsfoss.com/archlabs-vs-archmerge/
-[22]:http://reddit.com/r/linuxusersgroup
-[23]:http://johnpaulwohlscheid.work/
diff --git a/sources/tech/20180628 Blockchain evolution- A quick guide and why open source is at the heart of it.md b/sources/tech/20180628 Blockchain evolution- A quick guide and why open source is at the heart of it.md
deleted file mode 100644
index 585a7203d1..0000000000
--- a/sources/tech/20180628 Blockchain evolution- A quick guide and why open source is at the heart of it.md
+++ /dev/null
@@ -1,97 +0,0 @@
-Blockchain evolution: A quick guide and why open source is at the heart of it
-======
-
-
-
-It isn't uncommon, when working on a new version of an open source project, to suffix it with "-ng", for "next generation." Fortunately, in their rapid evolution blockchains have so far avoided this naming pitfall. But in this evolutionary open source ecosystem, changes have been abundant, and good ideas have been picked up, remixed, and evolved between many different projects in a typical open source fashion.
-
-In this article, I will look at the different generations of blockchains and what ideas have emerged to address the problems the ecosystem has encountered. Of course, any attempt at classifying an ecosystem will have limits—and objectors—but it should provide a rough guide to the jungle of blockchain projects.
-
-### The beginning: Bitcoin
-
-The first generation of blockchains stems from the [Bitcoin][1] blockchain, the ledger underpinning the decentralized, peer-to-peer cryptocurrency that has gone from [Slashdot][2] miscellanea to a mainstream topic.
-
-This blockchain is a distributed ledger that keeps track of all users' transactions to prevent them from double-spending their coins (a task historically entrusted to third parties: banks). To prevent attackers from gaming the system, the ledger is replicated to every computer participating in the Bitcoin network and can be updated by only one computer in the network at a time. To decide which computer earns the right to update the ledger, the system organizes every 10 minutes a race between the computers, which costs them (a lot of) energy to enter. The winner wins the right to commit the last 10 minutes of transactions to the ledger (the "block" in blockchain) and some Bitcoin as a reward for their efforts. This setup is called a _proof of work_ consensus mechanism.
-
-The goal of using a blockchain is to raise the level of trust participants have in the network.
-
-This is where it gets interesting. Bitcoin was released as an [open source project][3] in January 2009. In 2010, realizing that quite a few of these elements can be tweaked, the community that had aggregated around Bitcoin, often on the [bitcointalk forums][4], started experimenting with them.
-
-First, seeing that the Bitcoin blockchain is a form of a distributed database, the [Namecoin][5] project emerged, suggesting to store arbitrary data in its transaction database. If the blockchain can record the transfer of money, it could also record the transfer of other assets, such as domain names. This is exactly Namecoin's main use case, which went live in April 2011, two years after Bitcoin's introduction.
-
-Where Namecoin tweaked the content of the blockchain, [Litecoin][6] tweaked two technical aspects: reducing the time between two blocks from 10 to 2.5 minutes and changing how the race is run (replacing the SHA-256 secure hashing algorithm with [scrypt][7]). This was possible because Bitcoin was released as open source software and Litecoin is essentially identical to Bitcoin in all other places. Litecoin was the first fork to modify the consensus mechanism, paving the way for many more.
-
-Along the way, many more variations of the Bitcoin codebase have appeared. Some started as proposed extensions to Bitcoin, such as the [Zerocash][8] protocol, which aimed to provide transaction anonymity and fungibility but was eventually spun off into its own currency, [Zcash][9].
-
-While Zcash has brought its own innovations, using recent cryptographic advances known as zero-knowledge proofs, it maintains compatibility with the vast majority of the Bitcoin code base, meaning it too can benefit from upstream Bitcoin innovations.
-
-Another project, [CryptoNote][10], didn't use the same code base but sprouted from the same community, building on (and against) Bitcoin and again, on older ideas. Published in December 2012, it led to the creation of several cryptocurrencies, of which [Monero][11] (2014) is the best-known. Monero takes a different approach to Zcash but aims to solve the same issues: privacy and fungibility.
-
-As is often the case in the open source world, there is more than one tool for the job.
-
-### The next generations: "Blockchain-ng"
-
-So far, however, all these variations have only really been about refining cryptocurrencies or extending them to support another type of transaction. This brings us to the second generation of blockchains.
-
-Once the community started modifying what a blockchain could be used for and tweaking technical aspects, it didn't take long for some people to expand and rethink them further. A longtime follower of Bitcoin, [Vitalik Buterin][12] suggested in late 2013 that a blockchain's transactions could represent the change of states of a state machine, conceiving the blockchain as a distributed computer capable of running applications ("smart contracts"). The project, [Ethereum][13], went live in July 2015. It has seen fair success in running distributed apps, and the popularity of some of its better-known distributed apps ([CryptoKitties][14]) have even caused the Ethereum blockchain to slow down.
-
-This demonstrates one of the big limitations of current blockchains: speed and capacity. (Speed is often measured in transactions per second, or TPS.) Several approaches have been suggested to solve this, from sharding to sidechains and so-called "second-layer" solutions. The need for more innovation here is strong.
-
-With the words "smart contract" in the air and a proved—if still slow—technology to run them, another idea came to fruition: permissioned blockchains. So far, all the blockchain networks we've described have had two unsaid characteristics: They are public (anyone can see them function), and they are without permission (anyone can join them). These two aspects are both desirable and necessary to run a distributed, non-third-party-based currency.
-
-As blockchains were being considered more and more separately from cryptocurrencies, it started to make sense to consider them in some private, permissioned settings. A consortium-type group of actors that have business relationships but don't necessarily trust each other fully can benefit from these types of blockchains—for example, actors along a logistics chain, financial or insurance institutions that regularly do bilateral settlements or use a clearinghouse, idem for healthcare institutions.
-
-Once you change the setting from "anyone can join" to "invitation-only," further changes and tweaks to the blockchain building blocks become possible, yielding interesting results for some.
-
-For a start, proof of work, designed to protect the network from malicious and spammy actors, can be replaced by something simpler and less resource-hungry, such as a [Raft][15]-based consensus protocol. A tradeoff appears between a high level of security or faster speed, embodied by the option of simpler consensus algorithms. This is highly desirable to many groups, as they can trade some cryptography-based assurance for assurance based on other means—legal relationships, for instance—and avoid the energy-hungry arms race that proof of work often leads to. This is another area where innovation is ongoing, with [Proof of Stake][16] a notable contender for the public network consensus mechanism of choice. It would likely also find its way to permissioned networks too.
-
-Several projects make it simple to create permissioned blockchains, including [Quorum][17] (a fork of Ethereum) and [Hyperledger][18]'s [Fabric][19] and [Sawtooth][20], two open source projects based on new code.
-
-Permissioned blockchains can avoid certain complexities that public, non-permissioned ones can't, but they still have their own set of issues. Proper management of participants is one: Who can join? How do they identify? How can they be removed from the network? Does one entity on the network manage a central public key infrastructure (PKI)?
-
-The open nature of blockchains is seen as a form of governance.
-
-### Open nature of blockchains
-
-In all of the cases so far, one thing is clear: The goal of using a blockchain is to raise the level of trust participants have in the network and the data it produces—ideally, enough to be able to use it as is, without further work.
-
-Reaching this level of trust is possible only if the software that powers the network is free and open source. Even a correctly distributed proprietary blockchain is essentially a collection of independent agents running the same third party's code. By nature, it's necessary—but not sufficient—for a blockchain's source code to be open source. This has both been a minimum guarantee and the source of further innovation as the ecosystem keeps growing.
-
-Finally, it is worth mentioning that while the open nature of blockchains has been a source of innovation and variation, it has also been seen as a form of governance: governance by code, where users are expected to run whichever specific version of the code contains a function or approach they think the whole network should embrace. In this respect, one can say the open nature of some blockchains has also become a cop-out regarding governance. But this is being addressed.
-
-### Third and fourth generations: governance
-
-Next, I will look at what I am currently considering the third and fourth generations of blockchains: blockchains with built-in governance tools and projects to solve the tricky question of interconnecting the multitude of different blockchain projects to let them exchange information and value with each other.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/6/blockchain-guide-next-generation
-
-作者:[Axel Simon][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/axel
-[1]:https://bitcoin.org
-[2]:https://slashdot.org/
-[3]:https://github.com/bitcoin/bitcoin
-[4]:https://bitcointalk.org/
-[5]:https://www.namecoin.org/
-[6]:https://litecoin.org/
-[7]:https://en.wikipedia.org/wiki/Scrypt
-[8]:http://zerocash-project.org/index
-[9]:https://z.cash
-[10]:https://cryptonote.org/
-[11]:https://en.wikipedia.org/wiki/Monero_(cryptocurrency)
-[12]:https://en.wikipedia.org/wiki/Vitalik_Buterin
-[13]:https://ethereum.org
-[14]:http://cryptokitties.co/
-[15]:https://en.wikipedia.org/wiki/Raft_(computer_science)
-[16]:https://www.investopedia.com/terms/p/proof-stake-pos.asp
-[17]:https://www.jpmorgan.com/global/Quorum
-[18]:https://hyperledger.org/
-[19]:https://www.hyperledger.org/projects/fabric
-[20]:https://www.hyperledger.org/projects/sawtooth
diff --git a/sources/tech/20180628 Sosreport - A Tool To Collect System Logs And Diagnostic Information.md b/sources/tech/20180628 Sosreport - A Tool To Collect System Logs And Diagnostic Information.md
deleted file mode 100644
index a476c5e0cd..0000000000
--- a/sources/tech/20180628 Sosreport - A Tool To Collect System Logs And Diagnostic Information.md
+++ /dev/null
@@ -1,142 +0,0 @@
-translating---geekpi
-
-
-Sosreport – A Tool To Collect System Logs And Diagnostic Information
-======
-
-
-
-If you’re working as RHEL administrator, you might definitely heard about **Sosreport** – an extensible, portable and support data collection tool. It is a tool to collect system configuration details and diagnostic information from a Unix-like operating system. When the user raise a support ticket, he/she has to run this tool and send the resulting report generated by Sosreport tool to the Red Hat support executive. The executive will then perform an initial analysis based on the report and try to find what’s the problem in the system. Not just on RHEL system, you can use it on any Unix-like operating systems for collecting system logs and other debug information.
-
-### Installing Sosreport
-
-Sosreport is available on Red Hat official systems, so you can install it using Yum Or DNF package managers as shown below.
-```
-$ sudo yum install sos
-
-```
-
-Or,
-```
-$ sudo dnf install sos
-
-```
-
-On Debian, Ubuntu and Linux Mint, run:
-```
-$ sudo apt install sosreport
-
-```
-
-### Usage
-
-Once installed, run the following command to collect your system configuration details and other diagnostic information.
-```
-$ sudo sosreport
-
-```
-
-You will be asked to enter some details of your system, such as system name, case id etc. Type the details accordingly, and press ENTER key to generate the report. If you don’t want to change anything and want to use the default values, simply press ENTER.
-
-Sample output from my CentOS 7 server:
-```
-sosreport (version 3.5)
-
-This command will collect diagnostic and configuration information from
-this CentOS Linux system and installed applications.
-
-An archive containing the collected information will be generated in
-/var/tmp/sos.DiJXi7 and may be provided to a CentOS support
-representative.
-
-Any information provided to CentOS will be treated in accordance with
-the published support policies at:
-
-https://wiki.centos.org/
-
-The generated archive may contain data considered sensitive and its
-content should be reviewed by the originating organization before being
-passed to any third party.
-
-No changes will be made to system configuration.
-
-Press ENTER to continue, or CTRL-C to quit.
-
-Please enter your first initial and last name [server.ostechnix.local]:
-Please enter the case id that you are generating this report for []:
-
-Setting up archive ...
-Setting up plugins ...
-Running plugins. Please wait ...
-
-Running 73/73: yum...
-Creating compressed archive...
-
-Your sosreport has been generated and saved in:
-/var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz
-
-The checksum is: 8f08f99a1702184ec13a497eff5ce334
-
-Please send this file to your support representative.
-
-```
-
-If you don’t want to be prompted for entering such details, simply use batch mode like below.
-```
-$ sudo sosreport --batch
-
-```
-
-As you can see in the above output, an archived report is generated and saved in **/var/tmp/sos.DiJXi7** file. In RHEL 6/CentOS 6, the report will be generated in **/tmp** location. You can now send this report to your support executive, so that he can do initial analysis and find what’s the problem.
-
-You might be concerned or wanted to know what’s in the report. If so, you can view it by running the following command:
-```
-$ sudo tar -tf /var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz
-
-```
-
-Or,
-```
-$ sudo vim /var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz
-
-```
-
-Please note that above commands will not extract the archive, but only display the list of files and folders in the archive. If you want to view the actual contents of the files in the archive, first extract the archive using command:
-```
-$ sudo tar -xf /var/tmp/sosreport-server.ostechnix.local-20180628171844.tar.xz
-
-```
-
-All the contents of the archive will be extracted in a directory named “sosreport-server.ostechnix.local-20180628171844/” in the current working directory. Go to the directory and view the contents of any file using cat command or any other text viewer:
-```
-$ cd sosreport-server.ostechnix.local-20180628171844/
-
-$ cat uptime
-17:19:02 up 1:03, 2 users, load average: 0.50, 0.17, 0.10
-
-```
-
-For more details about Sosreport, refer man pages.
-```
-$ man sosreport
-
-```
-
-And, that’s all for now. Hope this was useful. More good stuffs to come. Stay tuned!
-
-Cheers!
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/sosreport-a-tool-to-collect-system-logs-and-diagnostic-information/
-
-作者:[SK][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://www.ostechnix.com/author/sk/
diff --git a/sources/tech/20180629 How To Get Flatpak Apps And Games Built With OpenGL To Work With Proprietary Nvidia Graphics Drivers.md b/sources/tech/20180629 How To Get Flatpak Apps And Games Built With OpenGL To Work With Proprietary Nvidia Graphics Drivers.md
new file mode 100644
index 0000000000..a9d540adae
--- /dev/null
+++ b/sources/tech/20180629 How To Get Flatpak Apps And Games Built With OpenGL To Work With Proprietary Nvidia Graphics Drivers.md
@@ -0,0 +1,113 @@
+How To Get Flatpak Apps And Games Built With OpenGL To Work With Proprietary Nvidia Graphics Drivers
+======
+**Some applications and games built with OpenGL support and packaged as Flatpak fail to start with proprietary Nvidia drivers. This article explains how to get such Flatpak applications or games them to start, without installing the open source drivers (Nouveau).**
+
+Here's an example. I'm using the proprietary Nvidia drivers on my Ubuntu 18.04 desktop (`nvidia-driver-390`) and when I try to launch the latest
+```
+$ /usr/bin/flatpak run --branch=stable --arch=x86_64 --command=krita --file-forwarding org.kde.krita
+Gtk-Message: Failed to load module "canberra-gtk-module"
+Gtk-Message: Failed to load module "canberra-gtk-module"
+libGL error: No matching fbConfigs or visuals found
+libGL error: failed to load driver: swrast
+Could not initialize GLX
+
+```
+
+To fix Flatpak games and applications not starting when using OpenGL with proprietary Nvidia graphics drivers, you'll need to install a runtime for your currently installed proprietary Nvidia drivers. Here's how to do this.
+
+**1\. Add the FlatHub repository if you haven't already. You can find exact instructions for your Linux distribution[here][1].**
+
+**2. Now you'll need to figure out the exact version of the proprietary Nvidia drivers installed on your system. **
+
+_This step is dependant of the Linux distribution you're using and I can't cover all cases. The instructions below are Ubuntu-oriented (and Ubuntu flavors) but hopefully you can figure out for yourself the Nvidia drivers version installed on your system._
+
+To do this in Ubuntu, open `Software & Updates` , switch to the `Additional Drivers` tab and note the name of the Nvidia driver package.
+
+As an example, this is `nvidia-driver-390` in my case, as you can see here:
+
+
+
+That's not all. We've only found out the Nvidia drivers major version but we'll also need to know the minor version. To get the exact Nvidia driver version, which we'll need for the next step, run this command (should work in any Debian-based Linux distribution, like Ubuntu, Linux Mint and so on):
+```
+apt-cache policy NVIDIA-PACKAGE-NAME
+
+```
+
+Where NVIDIA-PACKAGE-NAME is the Nvidia drivers package name listed in `Software & Updates` . For example, to see the exact installed version of the `nvidia-driver-390` package, run this command:
+```
+$ apt-cache policy nvidia-driver-390
+nvidia-driver-390:
+ Installed: 390.48-0ubuntu3
+ Candidate: 390.48-0ubuntu3
+ Version table:
+ * 390.48-0ubuntu3 500
+ 500 http://ro.archive.ubuntu.com/ubuntu bionic/restricted amd64 Packages
+ 100 /var/lib/dpkg/status
+
+```
+
+In this command's output, look for the `Installed` section and note the version numbers (excluding `-0ubuntu3` and anything similar). Now we know the exact version of the installed Nvidia drivers (`390.48` in my example). Remember this because we'll need it for the next step.
+
+**3\. And finally, you can install the Nvidia runtime for your installed proprietary Nvidia graphics drivers, from FlatHub**
+
+To list all the available Nvidia runtime packages available on FlatHub, you can use this command:
+```
+flatpak remote-ls flathub | grep nvidia
+
+```
+
+Hopefully the runtime for your installed Nvidia drivers is available on FlatHub. You can now proceed to install the runtime by using this command:
+
+ * For 64bit systems:
+
+
+```
+flatpak install flathub org.freedesktop.Platform.GL.nvidia-MAJORVERSION-MINORVERSION
+
+```
+
+Replace MAJORVERSION with the Nvidia driver major version installed on your computer (390 in my example above) and
+MINORVERSION with the minor version (48 in my example from step 2).
+
+For example, to install the runtime for Nvidia graphics driver version 390.48, you'd have to use this command:
+```
+flatpak install flathub org.freedesktop.Platform.GL.nvidia-390-48
+
+```
+
+ * For 32bit systems (or to be able to run 32bit applications or games on 64bit), install the 32bit runtime using:
+
+
+```
+flatpak install flathub org.freedesktop.Platform.GL32.nvidia-MAJORVERSION-MINORVERSION
+
+```
+
+Once again, replace MAJORVERSION with the Nvidia driver major version installed on your computer (390 in my example above) and MINORVERSION with the minor version (48 in my example from step 2).
+
+For example, to install the 32bit runtime for Nvidia graphics driver version 390.48, you'd have to use this command:
+```
+flatpak install flathub org.freedesktop.Platform.GL32.nvidia-390-48
+
+```
+
+That is all you need to do to get applications or games packaged as Flatpak that are built with OpenGL to run.
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxuprising.com/2018/06/how-to-get-flatpak-apps-and-games-built.html
+
+作者:[Logix][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://plus.google.com/118280394805678839070
+[1]:https://flatpak.org/setup/
+[2]:https://www.linuxuprising.com/2018/06/free-painting-software-krita-410.html
+[3]:https://www.linuxuprising.com/2018/06/winepak-is-flatpak-repository-for.html
+[4]:https://github.com/winepak/applications/issues/23
+[5]:https://github.com/flatpak/flatpak/issues/138
diff --git a/sources/tech/20180701 How to migrate to the world of Linux from Windows.md b/sources/tech/20180701 How to migrate to the world of Linux from Windows.md
new file mode 100644
index 0000000000..5d9ef80c08
--- /dev/null
+++ b/sources/tech/20180701 How to migrate to the world of Linux from Windows.md
@@ -0,0 +1,154 @@
+How to migrate to the world of Linux from Windows
+======
+Installing Linux on a computer, once you know what you’re doing, really isn’t a difficult process. After getting accustomed to the ins and outs of downloading ISO images, creating bootable media, and installing your distribution (henceforth referred to as distro) of choice, you can convert a computer to Linux in no time at all. In fact, the time it takes to install Linux and get it updated with all the latest patches is so short that enthusiasts do the process over and over again to try out different distros; this process is called distro hopping.
+
+With this guide, I want to target people who have never used Linux before. I’ll give an overview of some distros that are great for beginners, how to write or burn them to media, and how to install them. I’ll show you the installation process of Linux Mint, but the process is similar if you choose Ubuntu. For a distro such as Fedora, however, your experience will deviate quite a bit from what’s shown in this post. I’ll also touch on the sort of software available, and how to install additional software.
+
+The command line will not be covered; despite what some people say, using the command line really is optional in distributions such as Linux Mint, which is aimed at beginners. Most distros come with update managers, software managers, and file managers with graphical interfaces, which largely do away with the need for a command line. Don’t get me wrong, the command line can be great – I do use it myself from time to time – but largely for convenience purposes.
+
+This guide will also not touch on troubleshooting or dual booting. While Linux does generally support new hardware, there’s a slight chance that any cutting edge hardware you have might not yet be supported by Linux. Setting up a dual boot system is easy enough, though wiping the disk and doing a clean install is usually my preferred method. For this reason, if you intend to follow the guide, either use a virtual machine to install Linux or use a spare computer that you’ve got lying around.
+
+The chief appeal for most Linux users is the customisability and the diverse array of Linux distributions or distros that are available. For the majority of people getting into Linux, the usual entry point is Ubuntu, which is backed by Canonical. Ubuntu was my gateway Linux distribution in 2008; although not my favourite, it’s certainly easy to begin using and is very polished.
+
+Another beginner-friendly distribution is Linux Mint. It’s the distribution I use day-to-day on every one of my machines. It’s very easy to start using, is generally very stable, and the user interface (UI) doesn’t drastically change; anyone familiar with Windows XP or Windows Vista will be familiar with the the UI of Linux Mint. While everyone went chasing the convergence dream of merging mobile and desktop together, Linux Mint stayed staunchly of the position that an operating system on the desktop should be designed for desktop and therefore totally avoids being mobile-friendly UI; desktop and laptops are front and centre.
+
+For your first dive into Linux, I highly recommend the two mentioned above, simply because they’ve got huge communities and developers tending to them around the clock. With that said, several other operating systems such as elementary OS (based on Ubuntu) and Fedora (run by Red Hat) are also good ways to get started. Other users are fond of options such as Manjaro and Antergos which make the difficult-to-configure Arch Linux easy to use.
+
+Now, we’re starting to get our hands dirty. For this guide, I will include screenshots of Linux Mint 18.3 Cinnamon edition. If you decide to go with Ubuntu or another version of Linux Mint, note that things may look slightly different. For example, when it comes to a distro that isn’t based on Ubuntu – like Fedora or Manjaro – things will look significantly different during installation, but not so much that you won’t be able to work the process out.
+
+In order to download Linux Mint, head on over to the Linux Mint downloads page and select either the 32-bit version or 64-bit version of the Cinnamon edition. If you aren’t sure which version is needed for your computer, pick the 64-bit version; this tends to work on computers even from 2007, so it’s a safe bet. The only time I’d advise the 32-bit version is if you’re planning to install Linux on a netbook.
+
+Once you’ve selected your version, you can either download the ISO image via one of the many mirrors, or as a torrent. It’s best to download it as a torrent because if your internet cuts out, you won’t have to restart the 1.9 GB download. Additionally, the downloaded ISO you receive via torrent will be signed with the correct keys, ensuring authenticity. If you download another distribution, you’ll be able to continue to the next step once you have an ISO file saved to your computer.
+
+Note: If you’re using a virtual machine, you don’t need to write or burn the ISO to USB or DVD, just use the ISO to launch the distro on your chosen virtual machine.
+
+Ten years ago when I started using Linux, you could fit an entire distribution onto a CD. Nowadays, you’ll need a DVD or a USB to boot the distro from.
+
+To write the ISO to a USB device, I recommend downloading a tool called Rufus. Once it’s downloaded and installed, you should insert a USB stick that’s 4GB or more. Be sure to backup the data as the device will be erased.
+
+Next, launch Rufus and select the device you want to write to; if you aren’t sure which is your USB device, unplug it, check the list, then plug it back in to work out which device you need to write to. Once you’ve worked out which USB drive you want to write to, select ‘MBR Partition Scheme for BIOS or UEFI’ under ‘Partition scheme and target system type’. Once you’ve done that, press the optical drive icon alongside the enabled ‘Create a bootable disk using’ field. You can then navigate to the ISO file that you just downloaded. Once it finishes writing to the USB, you’ve got everything you need to boot into Linux.
+
+Note: If you’re using a virtual machine, you don’t need to write or burn the ISO to USB or DVD, just use the ISO to launch the distro on your chosen virtual machine.
+
+If you’re on Windows 7 or above and want to burn the ISO to a DVD, simply insert a blank DVD into the computer, then right-click the ISO file and select ‘Burn disc image’, from the dialogue window which appears, select the drive where the DVD is located, and tick ‘Verify disc after burning’, then hit Burn.
+
+If you’re on Windows Vista, XP, or lower, download an install Infra Recorder and insert your blank DVD into your computer, selecting ‘Do nothing’ or ‘Cancel’ if any autorun windows pop up. Next, open Infra Recorder and select ‘Write Image’ on the main screen or go to Actions > Burn Image. From there find the Linux ISO you want to burn and press ‘OK’ when prompted.
+
+Once you’ve got your DVD or USB media ready you’re ready to boot into Linux; doing so won’t harm your Windows install in any way.
+
+Once you’ve got your installation media on hand, you’re ready to boot into the live environment. The operating system will load entirely from your DVD or USB device without making changes to your hard drive, meaning Windows will be left intact. The live environment is used to see whether your graphics card, wireless devices, and so on are compatible with Linux before you install it.
+
+To boot into the live environment you’re going to have to switch off the computer and boot it back up with your installation media already inserted into the computer. It’s also a must to ensure that your boot up sequence is set to launch from USB or DVD before your current operating system boots up from the hard drive. Configuring the boot sequence is beyond the scope of this guide, but if you can’t boot from the USB or DVD, I recommend doing a web search for how to access the BIOS to change the boot sequence order on your specific motherboard. Common keys to enter the BIOS or select the drive to boot from are F2, F10, and F11.
+
+If your boot up sequence is configured correctly, you should see a ten second countdown, that when completed, will automatically boot Linux Mint.
+
+![][1]
+
+![][2]
+
+Those who opted to try Linux Mint can let the countdown run to zero and the boot up will commence normally. On Ubuntu you’ll probably be prompted to choose a language, then press ‘Try Ubuntu without installing’, or the equivalent option on Linux Mint if you interrupted the automatic countdown by pressing the keyboard. If at any time you have the choice between trying or installing your Linux distribution of choice, always opt to try it, as the install option can cause irreversible damage to your Windows installation.
+
+Hopefully, everything went according to plan, and you’ve made it through to the live environment. The first thing to do now is to check to see whether your Wi-Fi is available. To connect to Wi-Fi press the icon to the left of the clock, where you should see the usual list of available networks; if this is the case, great! If not, don’t despair just yet. In the second case, when wireless card doesn’t seem to be working, either establish a wired connection via Ethernet or connect your phone to the computer – provided your handset supports tethering (via Wi-Fi, not data).
+
+Once you’ve got some sort of internet connection via one of those methods, press ‘Menu’ and use the search box to look for ‘Driver Manager’. This usually requires an internet connection and may let you enable your wireless card driver. If that doesn’t work, you’re probably out of luck, but the vast majority of cards should work with Linux Mint.
+
+For those who have a fancy graphics card, chances are that Linux is using an open source driver alternative instead of the proprietary driver you use on Windows. If you notice any issues pertaining to graphics, you can check the Driver Manager and see whether any proprietary drivers are available.
+
+Once those two critical components are confirmed to be up and running, you may want to check printer and webcam compatibility. To test your printer, go to ‘Menu’ > ‘Office’ > ‘LibreOffice Writer’ and try printing a document. If it works, that’s great, if not, some printers may be made to work with some effort, but that’s outside the scope of this particular guide. I’d recommend searching something like ‘Linux [your printer model]’ and there may be solutions available. As for your webcam, go to ‘Menu’ again and use the search box to look for ‘Software Manager’; this is the Microsoft Store equivalent on Linux Mint. Search for a program named ‘Cheese’ and install it. Once installed, open it up using the ‘Launch’ button in Software Manager, or have a look in ‘Menu’ and find it manually. If it detects a webcam it means it’s compatible!
+
+![][3]
+
+By now, you’ve probably had a good look at Linux Mint or your distribution of choice and, hopefully, everything is working for you. If you’ve had enough and want to return to Windows, simply press Menu and then the power off button which is located right above ‘Menu’, then press ‘Shut Down’ if a dialogue box pops up.
+
+Given that you’re sticking with me and want to install Linux Mint on your computer, thus erasing Windows, ensure that you’ve backed up everything on your computer. Dual boot installations are available from the installer, but in this guide I’ll explain how to install Linux as the sole operating system. Assuming you do decide to deviate and set up a dual boot system, then ensure you still back up your files from Windows first, because things could potentially go wrong for you.
+
+In order to do a clean install, close down any programs that you’ve got running in the live environment. On the desktop, you should see a disc icon labelled ‘Install Linux Mint’ – click that to continue.
+
+![][4]
+
+On the first screen of the installer, choose your language and press continue.
+
+![][5]
+
+On the second screen, most users will want to install third-party software to ensure hardware and codecs work.
+
+![][6]
+
+In the ‘Installation type’ section you can choose to erase your hard drive or dual boot. You can encrypt the entire drive if you check ‘Encrypt the new Linux Mint installation for security’ and ‘Use LVM with the new Linux Mint installation’. You can press ‘Something else’ for a specific custom set up. In order to set up a dual boot system, the hard drive which you’re installing to must already have Windows installed first.
+
+![][7]
+
+Now pick your location so that the operating system’s time can be set correctly, and press continue.
+
+![][8]
+
+Now set your keyboard’s language, and press continue.
+
+![][9]
+
+On the ‘Who are you’ screen, you’ll create a new user. Pop in your name, leave the computer’s name as default or enter a custom name, pick a username, and enter a password. You can choose to have the system log you in automatically or require a password. If you choose to require a password then you can also encrypt your home folder, which is different from encrypting your entire system. However, if you encrypt your entire system, there’s not a lot of point to encrypting your home folder too.
+
+![][10]
+
+Once you’ve completed the ‘Who are you’ screen, Linux Mint will begin installing. You’ll see a slideshow detailing what the operating system offers.
+
+![][11]
+
+Once the installation finishes, you’ll be prompted to restart. Go ahead and do so.
+
+Now that you’ve restarted the computer and removed the Linux media, your computer should boot up straight to your new install. If everything has gone smoothly, you should arrive at the login screen where you just need to enter the password you created during the set up.
+
+![][12]
+
+Once you reach the desktop, the first thing you’ll want to do is apply all the system updates that are available. On Linux Mint you should see a shield icon with a blue logo in the bottom right-hand corner of the desktop near the clock, click on it to open the Update Manager.
+
+![][13]
+
+You should be prompted to pick an update policy, give them all a read over and apply whichever you think is most appropriate for you then press ‘OK’.
+
+![][14]
+
+![][15]
+
+You’ll probably be asked to pick a more local mirror too. This is optional, but could allow your updates to download quicker. Now, apply any updates offered, until the shield icon has a green tick indicating that all updates have been applied. In future, the Update Manager will continually check for new updates and alert you to them.
+
+You’ve got all the necessary tasks out the way for setting up Linux Mint and now you’re free to start using the system for whatever you like. By default, Mozilla Firefox is installed, so if you’ve got a Sync account it’s probably a good idea to go pull in all your passwords and bookmarks. If you’re a Chrome user, you can either run Chromium which is in the Software Manager, or download Google Chrome from the internet. If you opt to get Chrome, you’ll be offered a .deb file which you should save to your system and then double-click to install. Installing .deb files is straightforward enough, just press ‘Install’ when prompted and the system will handle the rest, you’ll find the new software in ‘Menu’.
+
+![][16]
+
+Other pre-installed software includes LibreOffice which has decent compatibility with Microsoft Office; Mozilla’s Thunderbird for managing your emails; GIMP for editing images; Transmission is readily available for you to begin torrenting files, it supports adding IP block lists too; Pidgin and Hexchat will allow you to send instant messages and connect to IRC respectively. As for media playback, you will find VLC and Rhythmbox under ‘Sound and Video’ to satisfy all your music and video needs. If you need any other software, check out the Software Manager, there are lots of popular packages including Skype, Minecraft, Google Earth, Steam, and Private Internet Access Manager.
+
+Throughout this guide, I’ve explained that it will not touch on troubleshooting problems. However, the Linux Mint community can help you overcome any complications. The first port of call is definitely a quick web search, as most problems have been resolved by others in the past and you might be able to find your solution online. If you’re still stuck, you can try the Linux Mint forums as well as the Linux Mint subreddit, both of which are oriented towards troubleshooting.
+
+Linux definitely isn’t for everyone. It still lacks on the gaming front, despite the existence of Steam on Linux, and the growing number of games. In addition, some commonly used software isn’t available on Linux, but usually there are alternatives available. If, however, you have a computer lying around that isn’t powerful enough to support Windows any more, then Linux could be a good option for you. Linux is also free to use, so it’s great for those who don’t want to spend money on a new copy of Windows too.
+
+loading...
+
+--------------------------------------------------------------------------------
+
+via: http://infosurhoy.com/cocoon/saii/xhtml/en_GB/technology/how-to-migrate-to-the-world-of-linux-from-windows/
+
+作者:[Marta Subat][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]:http://infosurhoy.com/cocoon/saii/xhtml/en_GB/author/marta-subat/
+[1]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139198_autoboot_linux_mint.jpg
+[2]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139206_bootmenu_linux_mint.jpg
+[3]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139213_cheese_linux_mint.jpg
+[4]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139254_install_1_linux_mint.jpg
+[5]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139261_install_2_linux_mint.jpg
+[6]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139270_install_3_linux_mint.jpg
+[7]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139278_install_4_linux_mint.jpg
+[8]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139285_install_5_linux_mint.jpg
+[9]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139293_install_6_linux_mint.jpg
+[10]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139302_install_7_linux_mint.jpg
+[11]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139317_install_8_linux_mint.jpg
+[12]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139224_first_boot_1_linux_mint.jpg
+[13]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139232_first_boot_2_linux_mint.jpg
+[14]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139240_first_boot_3_linux_mint.jpg
+[15]:https://cdn.neow.in/news/images/uploaded/2018/02/1519139248_first_boot_4_linux_mint.jpg
+[16]:https://cdn.neow.in/news/images/uploaded/2018/02/1519219725_software_1_linux_mint.jpg
diff --git a/sources/tech/20180702 Diggs v4 launch: an optimism born of necessity.md b/sources/tech/20180702 Diggs v4 launch an optimism born of necessity.md
similarity index 100%
rename from sources/tech/20180702 Diggs v4 launch: an optimism born of necessity.md
rename to sources/tech/20180702 Diggs v4 launch an optimism born of necessity.md
diff --git a/sources/tech/20180702 How to edit Adobe InDesign files with Scribus and Gedit.md b/sources/tech/20180702 How to edit Adobe InDesign files with Scribus and Gedit.md
deleted file mode 100644
index 3e8d2022c2..0000000000
--- a/sources/tech/20180702 How to edit Adobe InDesign files with Scribus and Gedit.md
+++ /dev/null
@@ -1,128 +0,0 @@
-How to edit Adobe InDesign files with Scribus and Gedit
-======
-
-
-
-To be a good graphic designer, you must be adept at using the profession's tools, which for most designers today are the ones in the proprietary Adobe Creative Suite.
-
-However, there are times that open source tools will get you out of a jam. For example, imagine you're a commercial printer tasked with printing a file created in Adobe InDesign. You need to make a simple change (e.g., fixing a small typo) to the file, but you don't have immediate access to the Adobe suite. While these situations are admittedly rare, open source tools like desktop publishing software [Scribus][1] and text editor [Gedit][2] can save the day.
-
-In this article, I'll show you how I edit Adobe InDesign files with Scribus and Gedit. Note that there are many open source graphic design solutions that can be used instead of or in conjunction with Adobe InDesign. For more on this subject, check out my articles: [Expensive tools aren't the only option for graphic design (and never were)][3] and [2 open][4][source][4][Adobe InDesign scripts][4].
-
-When developing this solution, I read a few blogs on how to edit InDesign files with open source software but did not find what I was looking for. One suggestion I found was to create an EPS from InDesign and open it as an editable file in Scribus, but that did not work. Another suggestion was to create an IDML (an older InDesign file format) document from InDesign and open that in Scribus. That worked much better, so that's the workaround I used in the following examples.
-
-### Editing a business card
-
-Opening and editing my InDesign business card file in Scribus worked fairly well. The only issue I had was that the tracking (the space between letters) was a bit off and the upside-down "J" I used to create the lower-case "f" in "Jeff" was flipped. Otherwise, the styles and colors were all intact.
-
-
-![Business card in Adobe InDesign][6]
-
-Business card designed in Adobe InDesign.
-
-![InDesign IDML file opened in Scribus][8]
-
-InDesign IDML file opened in Scribus.
-
-### Deleting copy in a paginated book
-
-The book conversion didn't go as well. The main body of the text was OK, but the table of contents and some of the drop caps and footers were messed up when I opened the InDesign file in Scribus. Still, it produced an editable document. One problem was some of my blockquotes defaulted to Arial font because a character style (apparently carried over from the original Word file) was on top of the paragraph style. This was simple to fix.
-
-![Book layout in InDesign][10]
-
-Book layout in InDesign.
-
-![InDesign IDML file of book layout opened in Scribus][12]
-
-InDesign IDML file of book layout opened in Scribus.
-
-Trying to select and delete a page of text produced surprising results. I placed the cursor in the text and hit Command+A (the keyboard shortcut for "select all"). It looked like one page was highlighted. However, that wasn't really true.
-
-![Selecting text in Scribus][14]
-
-Selecting text in Scribus.
-
-When I hit the Delete key, the entire text string (not just the highlighted page) disappeared.
-
-![Both pages of text deleted in Scribus][16]
-
-Both pages of text deleted in Scribus.
-
-Then something even more interesting happened… I hit Command+Z to undo the deletion. When the text came back, the formatting was messed up.
-
-![Undo delete restored the text, but with bad formatting.][18]
-
-Command+Z (undo delete) restored the text, but the formatting was bad.
-
-### Opening a design file in a text editor
-
-If you open a Scribus file and an InDesign file in a standard text editor (e.g., TextEdit on a Mac), you will see that the Scribus file is very readable whereas the InDesign file is not.
-
-You can use TextEdit to make changes to either type of file and save it, but the resulting file is useless. Here's the error I got when I tried re-opening the edited file in InDesign.
-
-![InDesign error message][20]
-
-InDesign error message.
-
-I got much better results when I used Gedit on my Linux Ubuntu machine to edit the Scribus file. I launched Gedit from the command line and voilà, the Scribus file opened, and the changes I made in Gedit were retained.
-
-![Editing Scribus file in Gedit][22]
-
-Editing a Scribus file in Gedit.
-
-![Result of the Gedit edit in Scribus][24]
-
-Result of the Gedit edit opened in Scribus.
-
-This could be very useful to a printer that receives a call from a client about a small typo in a project. Instead of waiting to get a new file, the printer could open the Scribus file in Gedit, make the change, and be good to go.
-
-### Dropping images into a file
-
-I converted an InDesign doc to an IDML file so I could try dropping in some PDFs using Scribus. It seems Scribus doesn't do this as well as InDesign, as it failed. Instead, I converted my PDFs to JPGs and imported them into Scribus. That worked great. However, when I exported my document as a PDF, I found that the files size was rather large.
-
-![Huge PDF file][26]
-
-Exporting Scribus to PDF produced a huge file.
-
-I'm not sure why this happened—I'll have to investigate it later.
-
-Do you have any tips for using open source software to edit graphics files? If so, please share them in the comments.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/7/adobe-indesign-open-source-tools
-
-作者:[Jeff Macharyas][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/rikki-endsley
-[1]:https://www.scribus.net/
-[2]:https://wiki.gnome.org/Apps/Gedit
-[3]:https://opensource.com/life/16/8/open-source-alternatives-graphic-design
-[4]:https://opensource.com/article/17/3/scripts-adobe-indesign
-[5]:/file/402516
-[6]:https://opensource.com/sites/default/files/uploads/1-business_card_designed_in_adobe_indesign_cc.png (Business card in Adobe InDesign)
-[7]:/file/402521
-[8]:https://opensource.com/sites/default/files/uploads/2-indesign_.idml_file_opened_in_scribus.png (InDesign IDML file opened in Scribus)
-[9]:/file/402531
-[10]:https://opensource.com/sites/default/files/uploads/3-book_layout_in_indesign.png (Book layout in InDesign)
-[11]:/file/402536
-[12]:https://opensource.com/sites/default/files/uploads/4-indesign_.idml_file_of_book_opened_in_scribus.png (InDesign IDML file of book layout opened in Scribus)
-[13]:/file/402541
-[14]:https://opensource.com/sites/default/files/uploads/5-command-a_in_the_scribus_file.png (Selecting text in Scribus)
-[15]:/file/402546
-[16]:https://opensource.com/sites/default/files/uploads/6-deleted_text_in_scribus.png (Both pages of text deleted in Scribus)
-[17]:/file/402551
-[18]:https://opensource.com/sites/default/files/uploads/7-command-z_in_scribus.png (Undo delete restored the text, but with bad formatting.)
-[19]:/file/402556
-[20]:https://opensource.com/sites/default/files/uploads/8-indesign_error_message.png (InDesign error message)
-[21]:/file/402561
-[22]:https://opensource.com/sites/default/files/uploads/9-scribus_edited_in_gedit_on_linux.png (Editing Scribus file in Gedit)
-[23]:/file/402566
-[24]:https://opensource.com/sites/default/files/uploads/10-scribus_opens_after_gedit_changes.png (Result of the Gedit edit in Scribus)
-[25]:/file/402571
-[26]:https://opensource.com/sites/default/files/uploads/11-large_pdf_size.png (Huge PDF file)
diff --git a/sources/tech/20180702 View The Contents Of An Archive Or Compressed File Without Extracting It.md b/sources/tech/20180702 View The Contents Of An Archive Or Compressed File Without Extracting It.md
deleted file mode 100644
index bff7f44c63..0000000000
--- a/sources/tech/20180702 View The Contents Of An Archive Or Compressed File Without Extracting It.md
+++ /dev/null
@@ -1,184 +0,0 @@
-View The Contents Of An Archive Or Compressed File Without Extracting It
-======
-
-
-In this tutorial, we are going to learn how to view the contents of an Archive and/or Compressed file without actually extracting it in Unix-like operating systems. Before going further, let be clear about Archive and compress files. There is significant difference between both. The Archiving is the process of combining multiple files or folders or both into a single file. In this case, the resulting file is not compressed. The compressing is a method of combining multiple files or folders or both into a single file and finally compress the resulting file. The archive is not a compressed file, but the compressed file can be an archive. Clear? Well, let us get to the topic.
-
-### View The Contents Of An Archive Or Compressed File Without Extracting It
-
-Thanks to Linux community, there are many command line applications are available to do it. Let us going to see some of them with examples.
-
-**1\. Using Vim Editor**
-
-Vim is not just an editor. Using Vim, we can do numerous things. The following command displays the contents of an compressed archive file without decompressing it.
-```
-$ vim ostechnix.tar.gz
-
-```
-
-![][2]
-
-You can even browse through the archive and open the text files (if there are any) in the archive as well. To open a text file, just put the mouse cursor in-front of the file using arrow keys and hit ENTER to open it.
-
-
-**2\. Using Tar command**
-
-To list the contents of a tar archive file, run:
-```
-$ tar -tf ostechnix.tar
-ostechnix/
-ostechnix/image.jpg
-ostechnix/file.pdf
-ostechnix/song.mp3
-
-```
-
-Or, use **-v** flag to view the detailed properties of the archive file, such as permissions, file owner, group, creation date etc.
-```
-$ tar -tvf ostechnix.tar
-drwxr-xr-x sk/users 0 2018-07-02 19:30 ostechnix/
--rw-r--r-- sk/users 53632 2018-06-29 15:57 ostechnix/image.jpg
--rw-r--r-- sk/users 156831 2018-06-04 12:37 ostechnix/file.pdf
--rw-r--r-- sk/users 9702219 2018-04-25 20:35 ostechnix/song.mp3
-
-```
-
-
-**3\. Using Rar command**
-
-To view the contents of a rar file, simply do:
-```
-$ rar v ostechnix.rar
-
-RAR 5.60 Copyright (c) 1993-2018 Alexander Roshal 24 Jun 2018
-Trial version Type 'rar -?' for help
-
-Archive: ostechnix.rar
-Details: RAR 5
-
-Attributes Size Packed Ratio Date Time Checksum Name
------------ --------- -------- ----- ---------- ----- -------- ----
--rw-r--r-- 53632 52166 97% 2018-06-29 15:57 70260AC4 ostechnix/image.jpg
--rw-r--r-- 156831 139094 88% 2018-06-04 12:37 C66C545E ostechnix/file.pdf
--rw-r--r-- 9702219 9658527 99% 2018-04-25 20:35 DD875AC4 ostechnix/song.mp3
------------ --------- -------- ----- ---------- ----- -------- ----
-9912682 9849787 99% 3
-
-```
-
-**4\. Using Unrar command**
-
-You can also do the same using **Unrar** command with **l** flag as shown below.
-```
-$ unrar l ostechnix.rar
-
-UNRAR 5.60 freeware Copyright (c) 1993-2018 Alexander Roshal
-
-Archive: ostechnix.rar
-Details: RAR 5
-
-Attributes Size Date Time Name
------------ --------- ---------- ----- ----
--rw-r--r-- 53632 2018-06-29 15:57 ostechnix/image.jpg
--rw-r--r-- 156831 2018-06-04 12:37 ostechnix/file.pdf
--rw-r--r-- 9702219 2018-04-25 20:35 ostechnix/song.mp3
------------ --------- ---------- ----- ----
-9912682 3
-
-```
-
-**5\. Using Zip command**
-
-To view the contents of a zip file without extracting it, use the following zip command:
-```
-$ zip -sf ostechnix.zip
-Archive contains:
-Life advices.jpg
-Total 1 entries (597219 bytes)
-
-```
-
-**6. Using Unzip command
-**
-
-You can also use Unzip command with -l flag to display the contents of a zip file like below.
-```
-$ unzip -l ostechnix.zip
-Archive: ostechnix.zip
-Length Date Time Name
---------- ---------- ----- ----
-597219 2018-04-09 12:48 Life advices.jpg
---------- -------
-597219 1 file
-
-```
-
-
-**7\. Using Zipinfo command**
-```
-$ zipinfo ostechnix.zip
-Archive: ostechnix.zip
-Zip file size: 584859 bytes, number of entries: 1
--rw-r--r-- 6.3 unx 597219 bx defN 18-Apr-09 12:48 Life advices.jpg
-1 file, 597219 bytes uncompressed, 584693 bytes compressed: 2.1%
-
-```
-
-As you can see, the above command displays the contents of the zip file, its permissions, creating date, and percentage of compression etc.
-
-**8. Using Zcat command
-**
-
-To view the contents of a compressed archive file without extracting it using **zcat** command, we do:
-```
-$ zcat ostechnix.tar.gz
-
-```
-
-The zcat is same as “gunzip -c” command. So, you can also use the following command to view the contents of the archive/compressed file:
-```
-$ gunzip -c ostechnix.tar.gz
-
-```
-
-**9. Using Zless command
-**
-
-To view the contents of an archive/compressed file using Zless command, simply do:
-```
-$ zless ostechnix.tar.gz
-
-```
-
-This command is similar to “less” command where it displays the output page by page.
-
-**10. Using Less command
-**
-
-As you might already know, the **less** command can be used to open a file for interactive reading, allowing scrolling and search.
-
-Run the following command to view the contents of an archive/compressed file using less command:
-```
-$ less ostechnix.tar.gz
-
-```
-
-And, that’s all for now. You know now how to view the contents of an archive of compressed file using various commands in Linux. Hope you find this useful. More good stuffs to come. Stay tuned!
-
-Cheers!
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/how-to-view-the-contents-of-an-archive-or-compressed-file-without-extracting-it/
-
-作者:[SK][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://www.ostechnix.com/author/sk/
-[1]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[2]:http://www.ostechnix.com/wp-content/uploads/2018/07/vim.png
diff --git a/sources/tech/20180703 10 killer tools for the admin in a hurry.md b/sources/tech/20180703 10 killer tools for the admin in a hurry.md
new file mode 100644
index 0000000000..363f401709
--- /dev/null
+++ b/sources/tech/20180703 10 killer tools for the admin in a hurry.md
@@ -0,0 +1,87 @@
+10 killer tools for the admin in a hurry
+======
+
+
+
+Administering networks and systems can get very stressful when the workload piles up. Nobody really appreciates how long anything takes, and everyone wants their specific thing done yesterday.
+
+So it's no wonder so many of us are drawn to the open source spirit of figuring out what works and sharing it with everyone. Because, when deadlines are looming, and there just aren't enough hours in the day, it really helps if you can just find free answers you can implement immediately.
+
+So, without further ado, here's my Swiss Army Knife of stuff to get you out of the office before dinner time.
+
+### Server configuration and scripting
+
+Let's jump right in.
+
+**[NixCraft][1]**
+Use the site's internal search function. With more than a decade of regular updates, there's gold to be found here—useful scripts and handy hints that can solve your problem straight away. This is often the second place I look after Google.
+
+**[Webmin][2]**
+This gives you a nice web interface to remotely edit your configuration files. It cuts down on a lot of time spent having to juggle directory paths and `sudo nano`, which is handy when you're handling several customers.
+
+**[Windows Subsystem for Linux][3]**
+The reality of the modern workplace is that most employees are on Windows, while the grown-up gear in the server room is on Linux. So sometimes you find yourself trying to do admin tasks from (gasp) a Windows desktop.
+
+What do you do? Install a virtual machine? It's actually much faster and far less work to configure if you install the Windows Subsystem for Linux compatibility layer, now available at no cost on Windows 10.
+
+This gives you a Bash terminal in a window where you can run Bash scripts and Linux binaries on the local machine, have full access to both Windows and Linux filesystems, and mount network drives. It's available in Ubuntu, OpenSUSE, SLES, Debian, and Kali flavors.
+
+**[mRemoteNG][4]**
+This is an excellent SSH and remote desktop client for when you have 100+ servers to manage.
+
+### Setting up a network so you don't have to do it again
+
+A poorly planned network is the sworn enemy of the admin who hates working overtime.
+
+**[IP Addressing Schemes that Scale][5]**
+The diabolical thing about running out of IP addresses is that, when it happens, the network's grown large enough that a new addressing scheme is an expensive, time-consuming pain in the proverbial.
+
+Ain't nobody got time for that!
+
+At some point, IPv6 will finally arrive to save the day. Until then, these one-size-fits-most IP addressing schemes should keep you going, no matter how many network-connected wearables, tablets, smart locks, lights, security cameras, VoIP headsets, and espresso machines the world throws at us.
+
+**[Linux Chmod Permissions Cheat Sheet][6]**
+A short but sweet cheat sheet of Bash commands to set permissions across the network. This is so when Bill from Customer Service falls for that ransomware scam, you're recovering just his files and not the entire company's.
+
+**[VLSM Subnet Calculator][7]**
+Just put in the number of networks you want to create from an address space and the number of hosts you want per network, and it calculates what the subnet mask should be for everything.
+
+### Single-purpose Linux distributions
+
+Need a Linux box that does just one thing? It helps if someone else has already sweated the small stuff on an operating system you can install and have ready immediately.
+
+Each of these has, at one point, made my work day so much easier.
+
+**[Porteus Kiosk][8]**
+This is for when you want a computer totally locked down to just a web browser. With a little tweaking, you can even lock the browser down to just one website. This is great for public access machines. It works with touchscreens or with a keyboard and mouse.
+
+**[Parted Magic][9]**
+This is an operating system you can boot from a USB drive to partition hard drives, recover data, and run benchmarking tools.
+
+**[IPFire][10]**
+Hahahaha, I still can't believe someone called a router/firewall/proxy combo "I pee fire." That's my second favorite thing about this Linux distribution. My favorite is that it's a seriously solid software suite. It's so easy to set up and configure, and there is a heap of plugins available to extend it.
+
+So, how about you? What tools, resources, and cheat sheets have you found to make the workday easier? I'd love to know. Please share in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/tools-admin
+
+作者:[Grant Hamono][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/grantdxm
+[1]:https://www.cyberciti.biz/
+[2]:http://www.webmin.com/
+[3]:http://wsl-guide.org/en/latest/
+[4]:https://mremoteng.org/
+[5]:https://blog.dxmtechsupport.com.au/ip-addressing-for-a-small-business-that-might-grow/
+[6]:https://isabelcastillo.com/linux-chmod-permissions-cheat-sheet
+[7]:http://www.vlsm-calc.net/
+[8]:http://porteus-kiosk.org/
+[9]:https://partedmagic.com/
+[10]:https://www.ipfire.org/
diff --git a/sources/tech/20180703 Install Oracle VirtualBox On Ubuntu 18.04 LTS Headless Server.md b/sources/tech/20180703 Install Oracle VirtualBox On Ubuntu 18.04 LTS Headless Server.md
new file mode 100644
index 0000000000..dd8c3cdb13
--- /dev/null
+++ b/sources/tech/20180703 Install Oracle VirtualBox On Ubuntu 18.04 LTS Headless Server.md
@@ -0,0 +1,320 @@
+Install Oracle VirtualBox On Ubuntu 18.04 LTS Headless Server
+======
+
+
+
+This step by step tutorial walk you through how to install **Oracle VirtualBox** on Ubuntu 18.04 LTS headless server. And, this guide also describes how to manage the VirtualBox headless instances using **phpVirtualBox** , a web-based front-end tool for VirtualBox. The steps described below might also work on Debian, and other Ubuntu derivatives such as Linux Mint. Let us get started.
+
+### Prerequisites
+
+Before installing Oracle VirtualBox, we need to do the following prerequisites in our Ubuntu 18.04 LTS server.
+
+First of all, update the Ubuntu server by running the following commands one by one.
+```
+$ sudo apt update
+
+$ sudo apt upgrade
+
+$ sudo apt dist-upgrade
+
+```
+
+Next, install the following necessary packages:
+```
+$ sudo apt install build-essential dkms unzip wget
+
+```
+
+After installing all updates and necessary prerequisites, restart the Ubuntu server.
+```
+$ sudo reboot
+
+```
+
+### Install Oracle VirtualBox on Ubuntu 18.04 LTS server
+
+Add Oracle VirtualBox official repository. To do so, edit **/etc/apt/sources.list** file:
+```
+$ sudo nano /etc/apt/sources.list
+
+```
+
+Add the following lines.
+
+Here, I will be using Ubuntu 18.04 LTS, so I have added the following repository.
+```
+deb http://download.virtualbox.org/virtualbox/debian bionic contrib
+
+```
+
+![][2]
+
+Replace the word **‘bionic’** with your Ubuntu distribution’s code name, such as ‘xenial’, ‘vivid’, ‘utopic’, ‘trusty’, ‘raring’, ‘quantal’, ‘precise’, ‘lucid’, ‘jessie’, ‘wheezy’, or ‘squeeze**‘.**
+
+Then, run the following command to add the Oracle public key:
+```
+$ wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add -
+
+```
+
+For VirtualBox older versions, add the following key:
+```
+$ wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add -
+
+```
+
+Next, update the software sources using command:
+```
+$ sudo apt update
+
+```
+
+Finally, install latest Oracle VirtualBox latest version using command:
+```
+$ sudo apt install virtualbox-5.2
+
+```
+
+### Adding users to VirtualBox group
+
+We need to create and add our system user to the **vboxusers** group. You can either create a separate user and assign it to vboxusers group or use the existing user. I don’t want to create a new user, so I added my existing user to this group. Please note that if you use a separate user for virtualbox, you must log out and log in to that particular user and do the rest of the steps.
+
+I am going to use my username named **sk** , so, I ran the following command to add it to the vboxusers group.
+```
+$ sudo usermod -aG vboxusers sk
+
+```
+
+Now, run the following command to check if virtualbox kernel modules are loaded or not.
+```
+$ sudo systemctl status vboxdrv
+
+```
+
+![][3]
+
+As you can see in the above screenshot, the vboxdrv module is loaded and running!
+
+For older Ubuntu versions, run:
+```
+$ sudo /etc/init.d/vboxdrv status
+
+```
+
+If the virtualbox module doesn’t start, run the following command to start it.
+```
+$ sudo /etc/init.d/vboxdrv setup
+
+```
+
+Great! We have successfully installed VirtualBox and started virtualbox module. Now, let us go ahead and install Oracle VirtualBox extension pack.
+
+### Install VirtualBox Extension pack
+
+The VirtualBox Extension pack provides the following functionalities to the VirtualBox guests.
+
+ * The virtual USB 2.0 (EHCI) device
+ * VirtualBox Remote Desktop Protocol (VRDP) support
+ * Host webcam passthrough
+ * Intel PXE boot ROM
+ * Experimental support for PCI passthrough on Linux hosts
+
+
+
+Download the latest Extension pack for VirtualBox 5.2.x from [**here**][4].
+```
+$ wget https://download.virtualbox.org/virtualbox/5.2.14/Oracle_VM_VirtualBox_Extension_Pack-5.2.14.vbox-extpack
+
+```
+
+Install Extension pack using command:
+```
+$ sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-5.2.14.vbox-extpack
+
+```
+
+Congratulations! We have successfully installed Oracle VirtualBox with extension pack in Ubuntu 16.04 LTS server. It is time to deploy virtual machines. Refer the [**virtualbox official guide**][5] to start creating and managing virtual machines in command line.
+
+Not everyone is command line expert. Some of you might want to create and use virtual machines graphically. No worries! Here is where **phpVirtualBox** comes in handy!!
+
+### About phpVirtualBox
+
+**phpVirtualBox** is a free, web-based front-end to Oracle VirtualBox. It is written using PHP language. Using phpVirtualBox, we can easily create, delete, manage and administer virtual machines via a web browser from any remote system on the network.
+
+### Install phpVirtualBox in Ubuntu 18.04 LTS
+
+Since it is a web-based tool, we need to install Apache web server, PHP and some php modules.
+
+To do so, run:
+```
+$ sudo apt install apache2 php php-mysql libapache2-mod-php php-soap php-xml
+
+```
+
+Then, Download the phpVirtualBox 5.2.x version from the [**releases page**][6]. Please note that we have installed VirtualBox 5.2, so we must install phpVirtualBox version 5.2 as well.
+
+To download it, run:
+```
+$ wget https://github.com/phpvirtualbox/phpvirtualbox/archive/5.2-0.zip
+
+```
+
+Extract the downloaded archive with command:
+```
+$ unzip 5.2-0.zip
+
+```
+
+This command will extract the contents of 5.2.0.zip file into a folder named “phpvirtualbox-5.2-0”. Now, copy or move the contents of this folder to your apache web server root folder.
+```
+$ sudo mv phpvirtualbox-5.2-0/ /var/www/html/phpvirtualbox
+
+```
+
+Assign the proper permissions to the phpvirtualbox folder.
+```
+$ sudo chmod 777 /var/www/html/phpvirtualbox/
+
+```
+
+Next, let us configure phpVirtualBox.
+
+Copy the sample config file as shown below.
+```
+$ sudo cp /var/www/html/phpvirtualbox/config.php-example /var/www/html/phpvirtualbox/config.php
+
+```
+
+Edit phpVirtualBox **config.php** file:
+```
+$ sudo nano /var/www/html/phpvirtualbox/config.php
+
+```
+
+Find the following lines and replace the username and password with your system user (The same username that we used in “Adding users to VirtualBox group” section).
+
+In my case, my Ubuntu system username is **sk** , and its password is **ubuntu**.
+```
+var $username = 'sk';
+var $password = 'ubuntu';
+
+```
+
+![][7]
+
+Save and close the file.
+
+Next, create a new file called **/etc/default/virtualbox** :
+```
+$ sudo nano /etc/default/virtualbox
+
+```
+
+Add the following line. Replace ‘sk’ with your own username.
+```
+VBOXWEB_USER=sk
+
+```
+
+Finally, Reboot your system or simply restart the following services to complete the configuration.
+```
+$ sudo systemctl restart vboxweb-service
+
+$ sudo systemctl restart vboxdrv
+
+$ sudo systemctl restart apache2
+
+```
+
+### Adjust firewall to allow Apache web server
+
+By default, the apache web browser can’t be accessed from remote systems if you have enabled the UFW firewall in Ubuntu 18.04 LTS. You must allow the http and https traffic via UFW by following the below steps.
+
+First, let us view which applications have installed a profile using command:
+```
+$ sudo ufw app list
+Available applications:
+Apache
+Apache Full
+Apache Secure
+OpenSSH
+
+```
+
+As you can see, Apache and OpenSSH applications have installed UFW profiles.
+
+If you look into the **“Apache Full”** profile, you will see that it enables traffic to the ports **80** and **443** :
+```
+$ sudo ufw app info "Apache Full"
+Profile: Apache Full
+Title: Web Server (HTTP,HTTPS)
+Description: Apache v2 is the next generation of the omnipresent Apache web
+server.
+
+Ports:
+80,443/tcp
+
+```
+
+Now, run the following command to allow incoming HTTP and HTTPS traffic for this profile:
+```
+$ sudo ufw allow in "Apache Full"
+Rules updated
+Rules updated (v6)
+
+```
+
+If you want to allow https traffic, but only http (80) traffic, run:
+```
+$ sudo ufw app info "Apache"
+
+```
+
+### Access phpVirtualBox Web console
+
+Now, go to any remote system that has graphical web browser.
+
+In the address bar, type: ****.
+
+In my case, I navigated to this link – ****
+
+You should see the following screen. Enter the phpVirtualBox administrative user credentials.
+
+The default username and phpVirtualBox is **admin** / **admin**.
+
+![][8]
+
+Congratulations! You will now be greeted with phpVirtualBox dashboard.
+
+![][9]
+
+Now, start creating your VMs and manage them from phpvirtualbox dashboard. As I mentioned earlier, You can access the phpVirtualBox from any system in the same network. All you need is a web browser and the username and password of phpVirtualBox.
+
+If you haven’t enabled virtualization support in the BISO of host system (not the guest), phpVirtualBox allows you to create 32-bit guests only. To install 64-bit guest systems, you must enable virtualization in your host system’s BIOS. Look for an option that is something like “virtualization” or “hypervisor” in your bios and make sure it is enabled.
+
+That’s it. Hope this helps. If you find this guide useful, please share it on your social networks and support us.
+
+More good stuffs to come. Stay tuned!
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/install-oracle-virtualbox-ubuntu-16-04-headless-server/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
+[1]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[2]:http://www.ostechnix.com/wp-content/uploads/2016/07/Add-VirtualBox-repository.png
+[3]:http://www.ostechnix.com/wp-content/uploads/2016/07/vboxdrv-service.png
+[4]:https://www.virtualbox.org/wiki/Downloads
+[5]:http://www.virtualbox.org/manual/ch08.html
+[6]:https://github.com/phpvirtualbox/phpvirtualbox/releases
+[7]:http://www.ostechnix.com/wp-content/uploads/2016/07/phpvirtualbox-config.png
+[8]:http://www.ostechnix.com/wp-content/uploads/2016/07/phpvirtualbox-1.png
+[9]:http://www.ostechnix.com/wp-content/uploads/2016/07/phpvirtualbox-2.png
diff --git a/sources/tech/20180704 BASHing data- Truncated data items.md b/sources/tech/20180704 BASHing data- Truncated data items.md
new file mode 100644
index 0000000000..33a9dd636b
--- /dev/null
+++ b/sources/tech/20180704 BASHing data- Truncated data items.md
@@ -0,0 +1,107 @@
+BASHing data: Truncated data items
+======
+### Truncated data items
+
+**truncated** (adj.): abbreviated, abridged, curtailed, cut off, clipped, cropped, trimmed...
+
+One way to truncate a data item is to enter it into a database field that has a character limit shorter than the data item. For example, the string
+
+>Yarrow Ravine Rattlesnake Habitat Area, 2 mi ENE of Yermo CA
+
+is 60 characters long. If you enter it into a "Locality" field with a 50-character limit, you get
+
+>Yarrow Ravine Rattlesnake Habitat Area, 2 mi ENE #Ends with a whitespace
+
+Truncations can also be data entry errors. You meant to enter
+
+>Sally Ann Hunter (aka Sally Cleveland)
+
+but you forgot the closing bracket
+
+>Sally Ann Hunter (aka Sally Cleveland
+
+leaving the data user to wonder whether Sally has other aliases that were trimmed off the data item.
+
+Truncated data items are very difficult to detect. When auditing data I use three different methods to find possible truncations, but I probably miss some.
+
+**Item length distribution.** The first method catches most of the truncations I find in individual fields. I pass the field to an AWK command that tallies up data items by field width, then I use **sort** to print the tallies in reverse order of width. For example, to check field 33 in the tab-separated file "midges":
+
+```
+awk -F"\t" 'NR>1 {a[length($33)]++} \
+END {for (i in a) print i FS a[i]}' midges | sort -nr
+```
+
+![distro1][1]
+
+The longest entries have exactly 50 characters, which is suspicious, and there's a "bulge" of data items at that width, which is even more suspicious. Inspection of those 50-character-wide items reveals truncations:
+
+![distro2][2]
+
+Other tables I've checked this way had bulges at 100, 200 and 255 characters. In each case the bulges contained apparent truncations.
+
+**Unmatched brackets**. The second method looks for data items like "...(Sally Cleveland" above. A good starting point is a tally of all the punctuation in the data table. Here I'm checking the file "mag2":
+
+grep -o "[[:punct:]]" file | sort | uniqc
+
+![punct][3]
+
+Note that the numbers of opening and closing round brackets in "mag2" aren't equal. To see what's going on, I use the function "unmatched", which takes three arguments and checks all fields in a data table. The first argument is the filename and the second and third are the opening and closing brackets, enclosed in quotes.
+
+```
+unmatched()
+{
+awk -F"\t" -v start="$2" -v end="$3" \
+'{for (i=1;i<=NF;i++) \
+if (split($i,a,start) != split($i,b,end)) \
+print "line "NR", field "i":\n"$i}' "$1"
+
+}
+```
+
+"unmatched" reports line number and field number if it finds a mismatch between opening and closing brackets in the field. It relies on AWK's **split** function, which returns the number of elements (including blank space) separated by the splitting character. This number will always be one more than the number of splitters:
+
+![split][4]
+
+Here "ummatched" checks the round brackets in "mag2" and finds some likely truncations:
+
+![unmatched][5]
+
+I use "unmatched" to locate unmatched round brackets (), square brackets [], curly brackets {} and arrows <>, but the function can be used for any paired punctuation characters.
+
+**Unexpected endings**. The third method looks for data items that end in a trailing space or a non-terminal punctuation mark, like a comma or a hyphen. This can be done on a single field with **cut** piped to **grep** , or in one step with AWK. Here I'm checking field 47 of the tab-separated table "herp5", and pulling out suspect data items and their line numbers:
+
+```
+cut -f47 herp5 | grep -n "[ ,;:-]$"
+
+awk -F"\t" '$47 ~ /[ ,;:-]$/ {print NR": "$47}' herp5
+```
+
+![herps5][6]
+
+The all-fields version of the AWK command for a tab-separated file is:
+
+```
+awk -F"\t" '{for (i=1;i<=NF;i++) if ($i ~ /[ ,;:-]$/) \
+print "line "NR", field "i":\n"$i}' file
+```
+
+**Cautionary thoughts**. Truncations also appear during the validation tests I do on fields. For example, I might be checking for plausible 4-digit entries in a "Year" field, and there's a 198 that hints at 198n. Or is it 1898? Truncated data items with their lost characters are mysteries. As a data auditor I can only report (possible) character losses and suggest that the (possibly) missing characters be restored by the data compilers or managers.
+
+--------------------------------------------------------------------------------
+
+via: https://www.polydesmida.info/BASHing/2018-07-04.html
+
+作者:[polydesmida][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://www.polydesmida.info/
+[1]:https://www.polydesmida.info/BASHing/img1/2018-07-04_1.png
+[2]:https://www.polydesmida.info/BASHing/img1/2018-07-04_2.png
+[3]:https://www.polydesmida.info/BASHing/img1/2018-07-04_3.png
+[4]:https://www.polydesmida.info/BASHing/img1/2018-07-04_4.png
+[5]:https://www.polydesmida.info/BASHing/img1/2018-07-04_5.png
+[6]:https://www.polydesmida.info/BASHing/img1/2018-07-04_6.png
diff --git a/sources/tech/20180704 Setup Headless Virtualization Server Using KVM In Ubuntu 18.04 LTS.md b/sources/tech/20180704 Setup Headless Virtualization Server Using KVM In Ubuntu 18.04 LTS.md
new file mode 100644
index 0000000000..a85a637830
--- /dev/null
+++ b/sources/tech/20180704 Setup Headless Virtualization Server Using KVM In Ubuntu 18.04 LTS.md
@@ -0,0 +1,332 @@
+Setup Headless Virtualization Server Using KVM In Ubuntu 18.04 LTS
+======
+
+
+
+We already have covered [**setting up Oracle VirtualBox on Ubuntu 18.04**][1] headless server. In this tutorial, we will be discussing how to setup headless virtualization server using **KVM** and how to manage the guest machines from a remote client. As you may know already, KVM ( **K** ernel-based **v** irtual **m** achine) is an open source, full virtualization for Linux. Using KVM, we can easily turn any Linux server in to a complete virtualization environment in minutes and deploy different kind of VMs such as GNU/Linux, *BSD, Windows etc.
+
+### Setup Headless Virtualization Server Using KVM
+
+I tested this guide on Ubuntu 18.04 LTS server, however this tutorial will work on other Linux distributions such as Debian, CentOS, RHEL and Scientific Linux. This method will be perfectly suitable for those who wants to setup a simple virtualization environment in a Linux server that doesn’t have any graphical environment.
+
+For the purpose of this guide, I will be using two systems.
+
+**KVM virtualization server:**
+
+ * **Host OS** – Ubuntu 18.04 LTS minimal server (No GUI)
+ * **IP Address of Host OS** : 192.168.225.22/24
+ * **Guest OS** (Which we are going to host on Ubuntu 18.04) : Ubuntu 16.04 LTS server
+
+
+
+**Remote desktop client :**
+
+ * **OS** – Arch Linux
+
+
+
+### Install KVM
+
+First, let us check if our system supports hardware virtualization. To do so, run the following command from the Terminal:
+```
+$ egrep -c '(vmx|svm)' /proc/cpuinfo
+
+```
+
+If the result is **zero (0)** , the system doesn’t support hardware virtualization or the virtualization is disabled in the Bios. Go to your bios and check for the virtualization option and enable it.
+
+if the result is **1** or **more** , the system will support hardware virtualization. However, you still need to enable the virtualization option in Bios before running the above commands.
+
+Alternatively, you can use the following command to verify it. You need to install kvm first as described below, in order to use this command.
+```
+$ kvm-ok
+
+```
+
+**Sample output:**
+```
+INFO: /dev/kvm exists
+KVM acceleration can be used
+
+```
+
+If you got the following error instead, you still can run guest machines in KVM, but the performance will be very poor.
+```
+INFO: Your CPU does not support KVM extensions
+INFO: For more detailed results, you should run this as root
+HINT: sudo /usr/sbin/kvm-ok
+
+```
+
+Also, there are other ways to find out if your CPU supports Virtualization or not. Refer the following guide for more details.
+
+Next, Install KVM and other required packages to setup a virtualization environment in Linux.
+
+On Ubuntu and other DEB based systems, run:
+```
+$ sudo apt-get install qemu-kvm libvirt-bin virtinst bridge-utils cpu-checker
+
+```
+
+Once KVM installed, start libvertd service (If it is not started already):
+```
+$ sudo systemctl enable libvirtd
+
+$ sudo systemctl start libvirtd
+
+```
+
+### Create Virtual machines
+
+All virtual machine files and other related files will be stored under **/var/lib/libvirt/**. The default path of ISO images is **/var/lib/libvirt/boot/**.
+
+First, let us see if there is any virtual machines. To view the list of available virtual machines, run:
+```
+$ sudo virsh list --all
+
+```
+
+**Sample output:**
+```
+Id Name State
+----------------------------------------------------
+
+```
+
+![][3]
+
+As you see above, there is no virtual machine available right now.
+
+Now, let us crate one.
+
+For example, let us create Ubuntu 16.04 Virtual machine with 512 MB RAM, 1 CPU core, 8 GB Hdd.
+```
+$ sudo virt-install --name Ubuntu-16.04 --ram=512 --vcpus=1 --cpu host --hvm --disk path=/var/lib/libvirt/images/ubuntu-16.04-vm1,size=8 --cdrom /var/lib/libvirt/boot/ubuntu-16.04-server-amd64.iso --graphics vnc
+
+```
+
+Please make sure you have Ubuntu 16.04 ISO image in path **/var/lib/libvirt/boot/** or any other path you have given in the above command.
+
+**Sample output:**
+```
+WARNING Graphics requested but DISPLAY is not set. Not running virt-viewer.
+WARNING No console to launch for the guest, defaulting to --wait -1
+
+Starting install...
+Creating domain... | 0 B 00:00:01
+Domain installation still in progress. Waiting for installation to complete.
+Domain has shutdown. Continuing.
+Domain creation completed.
+Restarting guest.
+
+```
+
+![][4]
+
+Let us break down the above command and see what each option do.
+
+ * **–name** : This option defines the name of the virtual name. In our case, the name of VM is **Ubuntu-16.04**.
+ * **–ram=512** : Allocates 512MB RAM to the VM.
+ * **–vcpus=1** : Indicates the number of CPU cores in the VM.
+ * **–cpu host** : Optimizes the CPU properties for the VM by exposing the host’s CPU’s configuration to the guest.
+ * **–hvm** : Request the full hardware virtualization.
+ * **–disk path** : The location to save VM’s hdd and it’s size. In our example, I have allocated 8GB hdd size.
+ * **–cdrom** : The location of installer ISO image. Please note that you must have the actual ISO image in this location.
+ * **–graphics vnc** : Allows VNC access to the VM from a remote client.
+
+
+
+### Access Virtual machines using VNC client
+
+Now, go to the remote Desktop system. SSH to the Ubuntu server(Virtualization server) as shown below.
+
+Here, **sk** is my Ubuntu server’s user name and **192.168.225.22** is its IP address.
+
+Run the following command to find out the VNC port number. We need this to access the Vm from a remote system.
+```
+$ sudo virsh dumpxml Ubuntu-16.04 | grep vnc
+
+```
+
+**Sample output:**
+```
+
+
+```
+
+![][5]
+
+Note down the port number **5900**. Install any VNC client application. For this guide, I will be using TigerVnc. TigerVNC is available in the Arch Linux default repositories. To install it on Arch based systems, run:
+```
+$ sudo pacman -S tigervnc
+
+```
+
+Type the following SSH port forwarding command from your remote client system that has VNC client application installed.
+
+Again, **192.168.225.22** is my Ubuntu server’s (virtualization server) IP address.
+
+Then, open the VNC client from your Arch Linux (client).
+
+Type **localhost:5900** in the VNC server field and click **Connect** button.
+
+![][6]
+
+Then start installing the Ubuntu VM as the way you do in the physical system.
+
+![][7]
+
+![][8]
+
+Similarly, you can setup as many as virtual machines depending upon server hardware specifications.
+
+Alternatively, you can use **virt-viewer** utility in order to install operating system in the guest machines. virt-viewer is available in the most Linux distribution’s default repositories. After installing virt-viewer, run the following command to establish VNC access to the VM.
+```
+$ sudo virt-viewer --connect=qemu+ssh://192.168.225.22/system --name Ubuntu-16.04
+
+```
+
+### Manage virtual machines
+
+Managing VMs from the command-line using virsh management user interface is very interesting and fun. The commands are very easy to remember. Let us see some examples.
+
+To view the list of running VMs, run:
+```
+$ sudo virsh list
+
+```
+
+Or,
+```
+$ sudo virsh list --all
+
+```
+
+**Sample output:**
+```
+ Id Name State
+----------------------------------------------------
+ 2 Ubuntu-16.04 running
+
+```
+
+![][9]
+
+To start a VM, run:
+```
+$ sudo virsh start Ubuntu-16.04
+
+```
+
+Alternatively, you can use the VM id to start it.
+
+![][10]
+
+As you see in the above output, Ubuntu 16.04 virtual machine’s Id is 2. So, in order to start it, just specify its Id like below.
+```
+$ sudo virsh start 2
+
+```
+
+To restart a VM, run:
+```
+$ sudo virsh reboot Ubuntu-16.04
+
+```
+
+**Sample output:**
+```
+Domain Ubuntu-16.04 is being rebooted
+
+```
+
+![][11]
+
+To pause a running VM, run:
+```
+$ sudo virsh suspend Ubuntu-16.04
+
+```
+
+**Sample output:**
+```
+Domain Ubuntu-16.04 suspended
+
+```
+
+To resume the suspended VM, run:
+```
+$ sudo virsh resume Ubuntu-16.04
+
+```
+
+**Sample output:**
+```
+Domain Ubuntu-16.04 resumed
+
+```
+
+To shutdown a VM, run:
+```
+$ sudo virsh shutdown Ubuntu-16.04
+
+```
+
+**Sample output:**
+```
+Domain Ubuntu-16.04 is being shutdown
+
+```
+
+To completely remove a VM, run:
+```
+$ sudo virsh undefine Ubuntu-16.04
+
+$ sudo virsh destroy Ubuntu-16.04
+
+```
+
+**Sample output:**
+```
+Domain Ubuntu-16.04 destroyed
+
+```
+
+![][12]
+
+For more options, I recommend you to look into the man pages.
+```
+$ man virsh
+
+```
+
+That’s all for now folks. Start playing with your new virtualization environment. KVM virtualization will be opt for research & development and testing purposes, but not limited to. If you have sufficient hardware, you can use it for large production environments. Have fun and don’t forget to leave your valuable comments in the comment section below.
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/setup-headless-virtualization-server-using-kvm-ubuntu/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
+[1]:https://www.ostechnix.com/install-oracle-virtualbox-ubuntu-16-04-headless-server/
+[2]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[3]:http://www.ostechnix.com/wp-content/uploads/2016/11/sk@ubuntuserver-_001.png
+[4]:http://www.ostechnix.com/wp-content/uploads/2016/11/sk@ubuntuserver-_008-1.png
+[5]:http://www.ostechnix.com/wp-content/uploads/2016/11/sk@ubuntuserver-_002.png
+[6]:http://www.ostechnix.com/wp-content/uploads/2016/11/VNC-Viewer-Connection-Details_005.png
+[7]:http://www.ostechnix.com/wp-content/uploads/2016/11/QEMU-Ubuntu-16.04-TigerVNC_006.png
+[8]:http://www.ostechnix.com/wp-content/uploads/2016/11/QEMU-Ubuntu-16.04-TigerVNC_007.png
+[9]:http://www.ostechnix.com/wp-content/uploads/2016/11/sk@ubuntuserver-_010-1.png
+[10]:http://www.ostechnix.com/wp-content/uploads/2016/11/sk@ubuntuserver-_010-2.png
+[11]:http://www.ostechnix.com/wp-content/uploads/2016/11/sk@ubuntuserver-_011-1.png
+[12]:http://www.ostechnix.com/wp-content/uploads/2016/11/sk@ubuntuserver-_012.png
diff --git a/sources/tech/20180705 5 Reasons Open Source Certification Matters More Than Ever.md b/sources/tech/20180705 5 Reasons Open Source Certification Matters More Than Ever.md
new file mode 100644
index 0000000000..dace150f39
--- /dev/null
+++ b/sources/tech/20180705 5 Reasons Open Source Certification Matters More Than Ever.md
@@ -0,0 +1,49 @@
+5 Reasons Open Source Certification Matters More Than Ever
+======
+
+
+In today’s technology landscape, open source is the new normal, with open source components and platforms driving mission-critical processes and everyday tasks at organizations of all sizes. As open source has become more pervasive, it has also profoundly impacted the job market. Across industries [the skills gap is widening][1], making it ever more difficult to hire people with much needed job skills. In response, the [demand for training and certification is growing][2].
+
+In a recent webinar, Clyde Seepersad, General Manager of Training and Certification at The Linux Foundation, discussed the growing need for certification and some of the benefits of obtaining open source credentials. “As open source has become the new normal in everything from startups to Fortune 2000 companies, it is important to start thinking about the career road map, the paths that you can take and how Linux and open source in general can help you reach your career goals,” Seepersad said.
+
+With all this in mind, this is the first article in a weekly series that will cover: why it is important to obtain certification; what to expect from training options that lead to certification; and how to prepare for exams and understand what your options are if you don’t initially pass them.
+
+Seepersad pointed to these five reasons for pursuing certification:
+
+ * **Demand for Linux and open source talent.** “Year after year, we do the Linux jobs report, and year after year we see the same story, which is that the demand for Linux professionals exceeds the supply. This is true for the open source market in general,” Seepersad said. For example, certifications such as the [LFCE, LFCS,][3] and [OpenStack administrator exam][4] have made a difference for many people.
+
+ * **Getting the interview.** “One of the challenges that recruiters always reference, especially in the age of open source, is that it can be hard to decide who you want to have come in to the interview,” Seepersad said. “Not everybody has the time to do reference checks. One of the beautiful things about certification is that it independently verifies your skillset.”
+
+ * **Confirming your skills.** “Certification programs allow you to step back, look across what we call the domains and topics, and find those areas where you might be a little bit rusty,” Seepersad said. “Going through that process and then being able to demonstrate skills on the exam shows that you have a very broad skillset, not just a deep skillset in certain areas.”
+
+ * **Confidence.** This is the beauty of performance-based exams,” Seepersad said. “You're working on our live system. You're being monitored and recorded. Your timer is counting down. This really puts you on the spot to demonstrate that you can troubleshoot.” The inevitable result of successfully navigating the process is confidence.
+
+ * **Making hiring decisions.** “As you become more senior in your career, you're going to find the tables turned and you are in the role of making a hiring decision,” Seepersad said. “You're going to want to have candidates who are certified, because you recognize what that means in terms of the skillsets.”
+
+
+
+
+Although Linux has been around for more than 25 years, “it's really only in the past few years that certification has become a more prominent feature,” Seepersad noted. As a matter of fact, 87 percent of hiring managers surveyed for the [2018 Open Source Jobs Report][5] cite difficulty in finding the right open source skills and expertise. The Jobs Report also found that hiring open source talent is a priority for 83 percent of hiring managers, and half are looking for candidates holding certifications.
+
+With certification playing a more important role in securing a rewarding long-term career, are you interested in learning about options for gaining credentials? If so, stay tuned for more information in this series.
+
+[Learn more about Linux training and certification.][6]
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/sysadmin-cert/2018/7/5-reasons-open-source-certification-matters-more-ever
+
+作者:[Sam Dean][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://www.linux.com/users/sam-dean
+[1]:https://www.linuxfoundation.org/blog/open-source-skills-soar-in-demand-according-to-2018-jobs-report/
+[2]:https://www.linux.com/blog/os-jobs-report/2018/7/certification-plays-big-role-open-source-hiring
+[3]:https://www.linux.com/learn/certification/2018/5/linux-foundation-lfcs-lfce-maja-kraljic
+[4]:https://training.linuxfoundation.org/linux-courses/system-administration-training/openstack-administration-fundamentals
+[5]:https://www.linuxfoundation.org/publications/open-source-jobs-report-2018/
+[6]:https://training.linuxfoundation.org/certification
diff --git a/sources/tech/20180706 Robolinux Lets You Easily Run Linux and Windows Without Dual Booting.md b/sources/tech/20180706 Robolinux Lets You Easily Run Linux and Windows Without Dual Booting.md
new file mode 100644
index 0000000000..783aa0bd4e
--- /dev/null
+++ b/sources/tech/20180706 Robolinux Lets You Easily Run Linux and Windows Without Dual Booting.md
@@ -0,0 +1,141 @@
+Robolinux Lets You Easily Run Linux and Windows Without Dual Booting
+======
+
+
+
+The number of Linux distributions available just keeps getting bigger. In fact, in the time it took me to write this sentence, another one may have appeared on the market. Many Linux flavors have trouble standing out in this crowd, and some are just a different combination of puzzle pieces joined to form something new: An Ubuntu base with a KDE desktop environment. A Debian base with an Xfce desktop. The combinations go on and on.
+
+[Robolinux][1], however, does something unique. It’s the only distro, to my knowledge, that makes working with Windows alongside Linux a little easier for the typical user. With just a few clicks, it lets you create a Windows virtual machine (by way of VirtualBox) that can run side by side with Linux. No more dual booting. With this process, you can have Windows XP, Windows 7, or Windows 10 up and running with ease.
+
+And, you get all this on top of an operating system that’s pretty fantastic on its own. Robolinux not only makes short work of having Windows along for the ride, it simplifies using Linux itself. Installation is easy, and the installed collection of software means anyone can be productive right away.
+
+Let’s install Robolinux and see what there is to see.
+
+### Installation
+
+As I mentioned earlier, installing Robolinux is easy. Obviously, you must first [download an ISO][2] image of the operating system. You have the choice of installing a Cinnamon, Mate, LXDE, or xfce desktop (I opted to go the Mate route). I will warn you, the developers do make a pretty heavy-handed plea for donations. I don’t fault them for this. Developing an operating system takes a great deal of time. So if you have the means, do make a donation.
+Once you’ve downloaded the file, burn it to a CD/DVD or flash drive. Boot your system with the media and then, once the desktop loads, click the Install icon on the desktop. As soon as the installer opens (Figure 1), you should be immediately familiar with the layout of the tool.
+
+![Robolinux installer][4]
+
+Figure 1: The Robolinux installer is quite user-friendly.
+
+[Used with permission][5]
+
+Once you’ve walked through the installer, reboot, remove the installation media, and login when prompted. I will say that I installed Robolinux as a VirtualBox VM and it installed to perfection. This however, isn’t a method you should use, if you’re going to take advantage of the Stealth VM option. After logging in, the first thing I did was install the Guest Additions and everything was working smoothly.
+
+### Default applications
+
+The collection of default applications is impressive, but not overwhelming. You’ll find all the standard tools to get your work done, including:
+
+ * LibreOffice
+
+ * Atril Document Viewer
+
+ * Backups
+
+ * GNOME Disks
+
+ * Medit text editor
+
+ * Seahorse
+
+ * GIMP
+
+ * Shotwell
+
+ * Simple Scan
+
+ * Firefox
+
+ * Pidgen
+
+ * Thunderbird
+
+ * Transmission
+
+ * Brasero
+
+ * Cheese
+
+ * Kazam
+
+ * Rhythmbox
+
+ * VLC
+
+ * VirtualBox
+
+ * And more
+
+
+
+
+With that list of software, you shouldn’t want for much. However, should you find a app not installed, click on the desktop menu button and then click Package Manager, which will open Synaptic Package Manager, where you can install any of the Linux software you need.
+
+If that’s not enough, it’s time to take a look at the Windows side of things.
+
+### Installing Windows
+
+This is what sets Robolinux apart from other Linux distributions. If you click on the desktop menu button, you see a Stealth VM entry. Within that sub-menu, a listing of the different Windows VMs that can be installed appears (Figure 2).
+
+![Windows VMs][7]
+
+Figure 2: The available Windows VMs that can be installed alongside of Robolinux.
+
+[Used with permission][5]
+
+Before you can install one of the VMs, you must first download the Stealth VM file. To do that, double-click on the desktop icon that includes an image of the developer’s face (labeled Robo’s FREE Stealth VM). You must save that file to the ~/Downloads directory. Don’t save it anywhere else, don’t extract it, and don’t rename it. With that file in place, click the start menu and then click Stealth VM. From the listing, click the top entry, Robolinx Stealth VM Installer. When prompted, type your sudo password. You will then be prompted that the Stealth VM is ready to be used. Go back to the start menu and click Stealth VM and select the version of Windows you want to install. A new window will appear (Figure 3). Click Yes and the installation will continue.
+
+![Installing Windows][9]
+
+Figure 3: Installing Windows in the Stealth VM.
+
+[Used with permission][5]
+
+Next you will be prompted to type your sudo password again (so your user can be added to the vboxusers group). Once you’ve taken care of that, you’ll be prompted to configure the RAM you want to dedicate to the VM. After that, a browser window will appear (once again asking for a donation). At this point everything is (almost) done. Close the browser and the terminal window.
+
+You’re not finished.
+
+Next you must insert the Windows installer media that matches the type of Windows VM you installed. You then must start VirtualBox by click start menu > System Tools > Oracle VM VirtualBox. When VirtualBox opens, an entry will already be created for your Windows VM (Figure 4).
+
+![Windows VM][11]
+
+Figure 4: Your Windows VM is ready to go.
+
+[Used with permission][5]
+
+You can now click the Start button (in VirtualBox) to finish up the installation. When the Windows installation completes, you’re ready to work with Linux and Windows side-by-side.
+
+### Making VMs a bit more user-friendly
+
+You may be thinking to yourself, “Creating a virtual machine for Windows is actually easier than that!”. Although you are correct with that sentiment, not everyone knows how to create a new VM with VirtualBox. In the time it took me to figure out how to work with the Robolinux Stealth VM, I could have had numerous VMs created in VirtualBox. Additionally, this approach doesn’t happen free of charge. You do still have to have a licensed copy of Windows (as well as the installation media). But anything developers can do to make using Linux easier is a plus. That’s how I see this—a Linux distribution doing something just slightly different that could remove a possible barrier to entry for the open source platform. From my perspective, that’s a win-win. And, you’re getting a pretty solid Linux distribution to boot.
+
+If you already know the ins and outs of VirtualBox, Robolinux might not be your cuppa. But, if you don’t like technology getting in the way of getting your work done and you want to have a Linux distribution that includes all the necessary tools to help make you productive, Robolinux is definitely worth a look.
+
+Learn more about Linux through the free ["Introduction to Linux" ][12] course from The Linux Foundation and edX.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/learn/intro-to-linux/2018/7/robolinux-lets-you-easily-run-linux-and-windows-without-dual-booting
+
+作者:[Jack Wallen][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://www.linux.com/users/jlwallen
+[1]:https://www.robolinux.org
+[2]:https://www.robolinux.org/downloads/
+[3]:/files/images/robolinux1jpg
+[4]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/robolinux_1.jpg?itok=MA0MD6KY (Robolinux installer)
+[5]:/licenses/category/used-permission
+[6]:/files/images/robolinux2jpg
+[7]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/robolinux_2.jpg?itok=bHktIhhK (Windows VMs)
+[8]:/files/images/robolinux3jpg
+[9]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/robolinux_3.jpg?itok=B7ar6hZf (Installing Windows)
+[10]:/files/images/robolinux4jpg
+[11]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/robolinux_4.jpg?itok=nEOt5Vnc (Windows VM)
+[12]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180706 Using Ansible to set up a workstation.md b/sources/tech/20180706 Using Ansible to set up a workstation.md
new file mode 100644
index 0000000000..cc9e63b2d8
--- /dev/null
+++ b/sources/tech/20180706 Using Ansible to set up a workstation.md
@@ -0,0 +1,168 @@
+Using Ansible to set up a workstation
+======
+
+
+
+Ansible is an extremely popular [open-source configuration management and software automation project][1]. While IT professionals almost certainly use Ansible on a daily basis, its influence outside the IT industry is not as wide. Ansible is a powerful and flexible tool. It is easily applied to a task common to nearly every desktop computer user: the post-installation “checklist”.
+
+Most users like to apply one “tweak” after a new installation. Ansible’s idempotent, declarative syntax lends itself perfectly to describing how a system should be configured.
+
+### Ansible in a nutshell
+
+The _ansible_ program itself performs a **single task** against a set of hosts. This is roughly conceptualized as:
+```
+for HOST in $HOSTS; do
+ ssh $HOST /usr/bin/echo "Hello World"
+done
+
+```
+
+To perform more than one task, Ansible defines the concept of a “playbook”. A playbook is a YAML file describing the _state_ of the targeted machine. When run, Ansible inspects each host and performs only the tasks necessary to enforce the state defined in the playbook.
+```
+- hosts: all
+ tasks:
+ - name: Echo "Hello World"
+ command: echo "Hello World"
+
+```
+
+Run the playbook using the _ansible-playbook_ command:
+```
+$ ansible-playbook ~/playbook.yml
+
+```
+
+### Configuring a workstation
+
+Start by installing ansible:
+```
+dnf install ansible
+
+```
+
+Next, create a file to store the playbook:
+```
+touch ~/post_install.yml
+
+```
+
+Start by defining the host on which to run this playbook. In this case, “localhost”:
+```
+- hosts: localhost
+
+```
+
+Each task consists of a _name_ field and a module field. Ansible has **a lot** of [modules][2]. Be sure to browse the module index to become familiar with all Ansible has to offer.
+
+#### The package module
+
+Most users install additional packages after a fresh install, and many like to remove some shipped software they don’t use. The _[package][3]_ module provides a generic wrapper around the system package manager (in Fedora’s case, _dnf_ ).
+```
+- hosts: localhost
+ tasks:
+ - name: Install Builder
+ become: yes
+ package:
+ name: gnome-builder
+ state: present
+ - name: Remove Rhythmbox
+ become: yes
+ package:
+ name: rhythmbox
+ state: absent
+ - name: Install GNOME Music
+ become: yes
+ package:
+ name: gnome-music
+ state: present
+ - name: Remove Shotwell
+ become: yes
+ package:
+ name: shotwell
+ state: absent
+```
+
+This playbook results in the following outcomes:
+
+ * GNOME Builder and GNOME Music are installed
+ * Rhythmbox is removed
+ * On Fedora 28 or greater, nothing happens with Shotwell (it is not in the default list of packages)
+ * On Fedora 27 or older, Shotwell is removed
+
+
+
+This playbook also introduces the **become: yes** directive. This specifies the task must be run by a privileged user (in most cases, _root_ ).
+
+#### The DConf Module
+
+Ansible can do a lot more than install software. For example, GNOME includes a great color-shifting feature called Night Light. It ships disabled by default, however the Ansible _[dconf][4]_ module can very easily enable it.
+```
+- hosts: localhost
+ tasks:
+ - name: Enable Night Light
+ dconf:
+ key: /org/gnome/settings-daemon/plugins/color/night-light-enabled
+ value: true
+ - name: Set Night Light Temperature
+ dconf:
+ key: /org/gnome/settings-daemon/plugins/color/night-light-temperature
+ value: uint32 5500
+```
+
+Ansible can also create files at specified locations with the _[copy][5]_ module. In this example, a local file is copied to the destination path.
+```
+- hosts: localhost
+ tasks:
+ - name: Enable "AUTH_ADMIN_KEEP" for pkexec
+ become: yes
+ copy:
+ src: files/51-pkexec-auth-admin-keep.rules
+ dest: /etc/polkit-1/rules.d/51-pkexec-auth-admin-keep.rules
+
+```
+
+#### The Command Module
+
+Ansible can still run commands even if no specialized module exists (via the aptly named _[command][6]_ module). This playbook enables the [Flathub][7] repository and installs a few Flatpaks. The commands are crafted in such a way that they are effectively idempotent. This is an important behavior to consider; a playbook should succeed each time it is run on a machine.
+```
+- hosts: localhost
+ tasks:
+ - name: Enable Flathub repository
+ become: yes
+ command: flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
+ - name: Install Fractal
+ become: yes
+ command: flatpak install --assumeyes flathub org.gnome.Fractal
+ - name: Install Spotify
+ become: yes
+ command: flatpak install --assumeyes flathub com.spotify.Client
+```
+
+Combine all these tasks together into a single playbook and, in one command, ** Ansible will customize a freshly installed workstation. Not only that, but 6 months later, after making changes to the playbook, run it again to bring a “seasoned” install back to a known state.
+```
+$ ansible-playbook -K ~/post_install.yml
+
+```
+
+This article only touched the surface of what’s possible with Ansible. A follow-up article will go into more advanced Ansible concepts such as _roles,_ configuring multiple hosts with a divided set of responsibilities.
+
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/using-ansible-setup-workstation/
+
+作者:[Link Dupont][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://fedoramagazine.org/author/linkdupont/
+[1]:https://ansible.com
+[2]:https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
+[3]:https://docs.ansible.com/ansible/latest/modules/package_module.html#package-module
+[4]:https://docs.ansible.com/ansible/latest/modules/dconf_module.html#dconf-module
+[5]:https://docs.ansible.com/ansible/latest/modules/copy_module.html#copy-module
+[6]:https://docs.ansible.com/ansible/latest/modules/command_module.html#command-module
+[7]:https://flathub.org
diff --git a/sources/tech/20180708 simple and elegant free podcast player.md b/sources/tech/20180708 simple and elegant free podcast player.md
new file mode 100644
index 0000000000..72e35c7029
--- /dev/null
+++ b/sources/tech/20180708 simple and elegant free podcast player.md
@@ -0,0 +1,119 @@
+simple and elegant free podcast player
+======
+
+
+
+CPod (formerly known as Cumulonimbus) is a cross-platform, open source podcast player for the desktop. The application is built with web technologies – it’s written in the JavaScript programming language and uses the Electron framework. Electron is often (rightly?) criticized for being a memory hog and dog slow. But is that mainly because of poor programming, rather than an inherent flaw in the technology?
+
+CPod is available for Linux, Mac OS, and Windows. Installation was a breeze on my Ubuntu 18.04 distribution as the author conveniently provides a 64-bit deb package. If you don’t run a Debian/Ubuntu based distro, there’s an AppImage which effortlessly installs the software on all major Linux distributions. There’s also a snap package from the snapcraft website, but bizarrely (and incorrectly) flags the software as proprietary software. As CPod is released under an open source license, there’s the full source code available too.
+
+The deb package installs the software to /opt/CPod, although the binary is still called cumulonimbus. A bit of tidying up needed there. For Mac OS users, there’s an Apple Disk Image file.
+
+### Home
+
+![CPod Playlist][2]
+First off, you cannot fail to notice the gorgeous attractive interface. Presentation is first class.
+
+First off, you cannot fail to notice the gorgeous attractive interface. Presentation is first class.
+
+The home section shows your subscribed podcasts. There are helpful filters at the top. They let you select podcasts of specified duration (handy if time is limited), you can filter by date, filter for podcasts that you’ve downloaded an offline copy, as well as podcasts that have not been listened to, you’ve started listening to, and podcasts you’ve heard to the end.
+
+Below the filters, there’s the option to select multiple podcasts, download local copies, add podcasts to your queue, as well as actually playing a podcast. The interface is remarkably intuitive.
+
+One quirk is that offline episodes are downloaded to the directory ~/.config/cumulonimbus/offline_episodes/. The downloaded podcasts are therefore not visible in the Files file manager by default (this is because the standard installation of Files does not display ‘hidden files’). It’s easy to enable hidden files in the file manager. Good news, the developer plans to add a configurable default download directory.
+
+There’s lots of nice touches which enhance the user experience, such as the progress bars when downloading episodes.
+
+### Playing a podcast
+
+![CPod][3]
+
+Here’s one of my favourite podcasts, Ubuntu Podcast, in playback. There’s visualization effects enabled; they only show when the window has focus. The visualizations don’t always display properly. There’s also the option of changing the playback speed (0.5x – 4x speed). I’m not sure why I’d want to change the playback speed though. Maybe someone could enlighten me?
+
+More functional is the slider that lets you skip to a specific point of the podcast although this is a tad buggy. The software is in an early stage of development. In any case, I prefer using the keyboard shortcuts to move forwards and backwards, and they work fine. Some podcasts offer links that let you skip to a particular segment; they are displayed in the large pane.
+
+There’s also the ability to watch video podcasts in both fullscreen and window mode. I spend most of my time listening to audio podcasts, but having full screen video podcasts is a pretty cool feature. Video playback is powered by ffmpeg.
+
+### Queue
+
+![CPod Queue][4]
+There’s not much to say about the queue functionality, but it’s worth noting you can change the order of episodes simply by dragging and dropping them in the interface. It’s well implemented and really simple to use. Another tick for CPod.
+
+### Subscriptions
+
+There’s not much to say about the queue functionality, but it’s worth noting you can change the order of episodes simply by dragging and dropping them in the interface. It’s well implemented and really simple to use. Another tick for CPod.
+
+![CPod Subscriptions][5]
+
+The interface makes it really easy to subscribe and unsubscribe to podcasts. Clicking the image of a subscribed podcast lets you find an episode, as well as a list of recent episodes, again with the ability to play, queue, and download. It’s all very clean and easy to use.
+
+### Explore
+
+In explore you can search for podcasts. Just type some keywords into the Explore dialog box, and you’re presented with a list of podcasts you can listen and subscribe.
+
+If you’re a fan of YouTube, you’re in luck. There’s the ability to preview and subscribe to YouTube channels by pasting a channel’s URL into the Explore box. That’s great if you have YouTube channel hyperlinks handy, but some sort of YouTube channel finder would be a great addition.
+
+Here’s a YouTube video in action.
+
+![CPod YTube][6]
+
+### Settings
+
+![CPod Settings][7]
+
+There’s a lot you can configure in Settings. There’s functionality to:
+
+ * Internationalization support – the ability to select the language displayed. Currently, there’s fairly limited support in this respect. Besides English, there’s Chinese, French, German, Korean, Portuguese, Portuguese (Brazilian), and Spanish available. Contributing translations is probably the easiest way for non-programmers to contribute to an open source project.
+ * Option to group episodes in Home by day or month.
+ * Keyboard shortcuts that let you skip backward, skip forward, and play/pause playback. I love my keyboard shortcuts.
+ * Configure different lengths of forward/backward skip.
+ * Enable waveform visualization – you can see examples of the visualization in our images (Playlist and Subscription sections).
+ * Basic gpodder.net integration (currently only subscriptions and device sync are supported; other functionality such as episodes actions and queue are planned).
+ * Allow pre-releases when auto-updating.
+ * Export subscriptions to OPML – Outline Processor Markup Language is an XML format commonly used to exchange lists of web feeds between web feed aggregators.
+ * Import subscriptions from OPML.
+ * Update podcast cover art.
+ * View offline episodes directory.
+
+
+
+The software has a bag of neat touches. For example, if I change the language setting, the software presents a pop up saying CPod needs to be restarted for the change to take effect. All very user-friendly.
+
+The Media Player Remote Interfacing Specification (MPRIS) is a standard D-Bus interface which aims to provide a common programmatic API for controlling media players. CPod offers basic MPRIS integration.
+
+### Summary
+
+CPod is another good example of what’s possible with modern web technologies. Sure, it’s got a few quirks, it’s in an early stage of development (read ‘expect to find lots of bugs’), and there’s some useful functionality waiting to be implemented. But I’m using the software on a daily basis, and will definitely keep up-to-date with developments.
+
+Linux already has some high quality open source podcast players. But CPod is definitely worth a download if you’re passionate about podcasts.
+
+**Website:** [**github.com/z————-/CPod**][8]
+**Support:**
+**Developer:** Zack Guard
+**License:** Apache License 2.0
+
+Zack Guard, CPod’s developer, is a student who lives in Hong Kong. You can buy him a coffee at ****. Unfortunately, I’m an impoverished student too.
+
+### Related
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxlinks.com/cpod-simple-elegant-free-podcast-player/
+
+作者:[Luke Baker][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://www.linuxlinks.com/author/luke-baker/
+[1]:https://www.linuxlinks.com/wp-content/plugins/jetpack/modules/lazy-images/images/1x1.trans.gif
+[2]:https://i2.wp.com/www.linuxlinks.com/wp-content/uploads/2018/07/CPod-Playlist.jpg?resize=750%2C368&ssl=1
+[3]:https://i0.wp.com/www.linuxlinks.com/wp-content/uploads/2018/07/CPod-Main.jpg?resize=750%2C368&ssl=1
+[4]:https://i0.wp.com/www.linuxlinks.com/wp-content/uploads/2018/07/CPod-Queue.jpg?resize=750%2C368&ssl=1
+[5]:https://i0.wp.com/www.linuxlinks.com/wp-content/uploads/2018/07/CPod-Subscriptions.jpg?resize=750%2C368&ssl=1
+[6]:https://i1.wp.com/www.linuxlinks.com/wp-content/uploads/2018/07/CPod-YouTube.jpg?resize=750%2C368&ssl=1
+[7]:https://i1.wp.com/www.linuxlinks.com/wp-content/uploads/2018/07/CPod-Settings.jpg?resize=750%2C368&ssl=1
+[8]:https://github.com/z-------------/CPod
diff --git a/sources/tech/20180709 5 Firefox extensions to protect your privacy.md b/sources/tech/20180709 5 Firefox extensions to protect your privacy.md
new file mode 100644
index 0000000000..848856fe07
--- /dev/null
+++ b/sources/tech/20180709 5 Firefox extensions to protect your privacy.md
@@ -0,0 +1,54 @@
+5 Firefox extensions to protect your privacy
+======
+
+
+
+In the wake of the Cambridge Analytica story, I took a hard look at how far I had let Facebook penetrate my online presence. As I'm generally concerned about single points of failure (or compromise), I am not one to use social logins. I use a password manager and create unique logins for every site (and you should, too).
+
+What I was most perturbed about was the pervasive intrusion Facebook was having on my digital life. I uninstalled the Facebook mobile app almost immediately after diving into the Cambridge Analytica story. I also [disconnected all apps, games, and websites][1] from Facebook. Yes, this will change your experience on Facebook, but it will also protect your privacy. As a veteran with friends spread out across the globe, maintaining the social connectivity of Facebook is important to me.
+
+I went about the task of scrutinizing other services as well. I checked Google, Twitter, GitHub, and more for any unused connected applications. But I know that's not enough. I need my browser to be proactive in preventing behavior that violates my privacy. I began the task of figuring out how best to do that. Sure, I can lock down a browser, but I need to make the sites and tools I use work while trying to keep them from leaking data.
+
+Following are five tools that will protect your privacy while using your browser. The first three extensions are available for Firefox and Chrome, while the latter two are only available for Firefox.
+
+### Privacy Badger
+
+[Privacy Badger][2] has been my go-to extension for quite some time. Do other content or ad blockers do a better job? Maybe. The problem with a lot of content blockers is that they are "pay for play." Meaning they have "partners" that get whitelisted for a fee. That is the antithesis of why content blockers exist. Privacy Badger is made by the Electronic Frontier Foundation (EFF), a nonprofit entity with a donation-based business model. Privacy Badger promises to learn from your browsing habits and requires minimal tuning. For example, I have only had to whitelist a handful of sites. Privacy Badger also allows granular controls of exactly which trackers are enabled on what sites. It's my #1, must-install extension, no matter the browser.
+
+### DuckDuckGo Privacy Essentials
+
+The search engine DuckDuckGo has typically been privacy-conscious. [DuckDuckGo Privacy Essentials][3] works across major mobile devices and browsers. It's unique in the sense that it grades sites based on the settings you give them. For example, Facebook gets a D, even with Privacy Protection enabled. Meanwhile, [chrisshort.net][4] gets a B with Privacy Protection enabled and a C with it disabled. If you're not keen on EFF or Privacy Badger for whatever reason, I would recommend DuckDuckGo Privacy Essentials (choose one, not both, as they essentially do the same thing).
+
+### HTTPS Everywhere
+
+[HTTPS Everywhere][5] is another extension from the EFF. According to HTTPS Everywhere, "Many sites on the web offer some limited support for encryption over HTTPS, but make it difficult to use. For instance, they may default to unencrypted HTTP or fill encrypted pages with links that go back to the unencrypted site. The HTTPS Everywhere extension fixes these problems by using clever technology to rewrite requests to these sites to HTTPS." While a lot of sites and browsers are getting better about implementing HTTPS, there are a lot of sites that still need help. HTTPS Everywhere will try its best to make sure your traffic is encrypted.
+
+### NoScript Security Suite
+
+[NoScript Security Suite][6] is not for the faint of heart. While the Firefox-only extension "allows JavaScript, Java, Flash, and other plugins to be executed only by trusted websites of your choice," it doesn't do a great job at figuring out what your choices are. But, make no mistake, a surefire way to prevent leaking data is not executing code that could leak it. NoScript enables that via its "whitelist-based preemptive script blocking." This means you will need to build the whitelist as you go for sites not already on it. Note that NoScript is only available for Firefox.
+
+### Facebook Container
+
+[Facebook Container][7] makes Firefox the only browser where I will use Facebook. "Facebook Container works by isolating your Facebook identity into a separate container that makes it harder for Facebook to track your visits to other websites with third-party cookies." This means Facebook cannot snoop on activity happening elsewhere in your browser. Suddenly those creepy ads will stop appearing so frequently (assuming you uninstalled the Facebook app from your mobile devices). Using Facebook in an isolated space will prevent any additional collection of data. Remember, you've given Facebook data already, and Facebook Container can't prevent that data from being shared.
+
+These are my go-to extensions for browser privacy. What are yours? Please share them in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/firefox-extensions-protect-privacy
+
+作者:[Chris Short][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/chrisshort
+[1]:https://www.facebook.com/help/211829542181913
+[2]:https://www.eff.org/privacybadger
+[3]:https://duckduckgo.com/app
+[4]:https://chrisshort.net
+[5]:https://www.eff.org/https-everywhere
+[6]:https://noscript.net/
+[7]:https://addons.mozilla.org/en-US/firefox/addon/facebook-container/
diff --git a/sources/tech/20180709 Anbox- How To Install Google Play Store And Enable ARM (libhoudini) Support, The Easy Way.md b/sources/tech/20180709 Anbox- How To Install Google Play Store And Enable ARM (libhoudini) Support, The Easy Way.md
new file mode 100644
index 0000000000..f390109123
--- /dev/null
+++ b/sources/tech/20180709 Anbox- How To Install Google Play Store And Enable ARM (libhoudini) Support, The Easy Way.md
@@ -0,0 +1,101 @@
+Anbox: How To Install Google Play Store And Enable ARM (libhoudini) Support, The Easy Way
+======
+**[Anbox][1], or Android in a Box, is a free and open source tool that allows running Android applications on Linux.** It works by running the Android runtime environment in an LXC container, recreating the directory structure of Android as a mountable loop image, while using the native Linux kernel to execute applications.
+
+Its key features are security, performance, integration and convergence (scales across different form factors), according to its website.
+
+**Using Anbox, each Android application or game is launched in a separate window, just like system applications** , and they behave more or less like regular windows, showing up in the launcher, can be tiled, etc.
+
+By default, Anbox doesn't ship with the Google Play Store or support for ARM applications. To install applications you must download each app APK and install it manually using adb. Also, installing ARM applications or games doesn't work by default with Anbox - trying to install ARM apps results in the following error being displayed:
+```
+Failed to install PACKAGE.NAME.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]
+
+```
+
+You can set up both Google Play Store and support for ARM applications (through libhoudini) manually for Android in a Box, but it's a quite complicated process. **To make it easier to install Google Play Store and Google Play Services on Anbox, and get it to support ARM applications and games (using libhoudini), the folks at[geeks-r-us.de][2] (linked article is in German) have created a [script][3] that automates these tasks.**
+
+Before using this, I'd like to make it clear that not all Android applications and games work in Anbox, even after integrating libhoudini for ARM support. Some Android applications and games may not show up in the Google Play Store at all, while others may be available for installation but will not work. Also, some features may not be available in some applications.
+
+### Install Google Play Store and enable ARM applications / games support on Anbox (Android in a Box)
+
+These instructions will obviously not work if Anbox is not already installed on your Linux desktop. If you haven't already, install Anbox by following the installation instructions found
+
+`anbox.appmgr`
+
+at least once after installing Anbox and before using this script, to avoid running into issues.
+
+1\. Install the required dependencies (`wget` , `lzip` , `unzip` and `squashfs-tools`).
+
+In Debian, Ubuntu or Linux Mint, use this command to install the required dependencies:
+```
+sudo apt install wget lzip unzip squashfs-tools
+
+```
+
+2\. Download and run the script that automatically downloads and installs Google Play Store (and Google Play Services) and libhoudini (for ARM apps / games support) on your Android in a Box installation.
+
+**Warning: never run a script you didn't write without knowing what it does. Before running this script, check out its [code][4]. **
+
+To download the script, make it executable and run it on your Linux desktop, use these commands in a terminal:
+```
+wget https://raw.githubusercontent.com/geeks-r-us/anbox-playstore-installer/master/install-playstore.sh
+chmod +x install-playstore.sh
+sudo ./install-playstore.sh
+
+```
+
+3\. To get Google Play Store to work in Anbox, you need to enable all the permissions for both Google Play Store and Google Play Services
+
+To do this, run Anbox:
+```
+anbox.appmgr
+
+```
+
+Then go to `Settings > Apps > Google Play Services > Permissions` and enable all available permissions. Do the same for Google Play Store!
+
+You should now be able to login using a Google account into Google Play Store.
+
+Without enabling all permissions for Google Play Store and Google Play Services, you may encounter an issue when trying to login to your Google account, with the following error message: " _Couldn't sign in. There was a problem communicating with Google servers. Try again later_ ", as you can see in this screenshot:
+
+After logging in, you can disable some of the Google Play Store / Google Play Services permissions.
+
+**If you're encountering some connectivity issues when logging in to your Google account on Anbox,** make sure the `anbox-bride.sh` is running:
+
+ * to start it:
+
+
+```
+sudo /snap/anbox/current/bin/anbox-bridge.sh start
+
+```
+
+ * to restart it:
+
+
+```
+sudo /snap/anbox/current/bin/anbox-bridge.sh restart
+
+```
+
+You may also need to install the dnsmasq package if you continue to have connectivity issues with Anbox, according to
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxuprising.com/2018/07/anbox-how-to-install-google-play-store.html
+
+作者:[Logix][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://plus.google.com/118280394805678839070
+[1]:https://anbox.io/
+[2]:https://geeks-r-us.de/2017/08/26/android-apps-auf-dem-linux-desktop/
+[3]:https://github.com/geeks-r-us/anbox-playstore-installer/
+[4]:https://github.com/geeks-r-us/anbox-playstore-installer/blob/master/install-playstore.sh
+[5]:https://docs.anbox.io/userguide/install.html
+[6]:https://github.com/anbox/anbox/issues/118#issuecomment-295270113
diff --git a/sources/tech/20180710 The aftermath of the Gentoo GitHub hack.md b/sources/tech/20180710 The aftermath of the Gentoo GitHub hack.md
new file mode 100644
index 0000000000..fc9ff4b4e5
--- /dev/null
+++ b/sources/tech/20180710 The aftermath of the Gentoo GitHub hack.md
@@ -0,0 +1,72 @@
+The aftermath of the Gentoo GitHub hack
+======
+
+
+
+### Gentoo GitHub hack: What happened?
+
+Late last month (June 28), the Gentoo GitHub repository was attacked after someone gained control of an admin account. All access to the repositories was soon removed from Gentoo developers. Repository and page content were altered. But within 10 minutes of the attacker gaining access, someone noticed something was going on, 7 minutes later a report was sent, and within 70 minutes the attack was over. Legitimate Gentoo developers were shut out for 5 days while the dust settled and repairs and analysis were completed.
+
+The attackers also attempted to add "rm -rf" commands to some repositories to cause user data to be recursively removed. As it turns out, this code was unlikely to be run because of technical precautions that were in place, but this wouldn't have been obvious to the attacker.
+
+One of the things that constrained how big a disaster this break in might have turned out to be was that the attack was "loud." The removal of developers resulted in them being emailed, and developers quickly discovered they'd been shut out. A stealthier attack might have led to a significant delay in anyone responding to the problem and a significantly bigger problem.
+
+A detailed timeline showing the details of what happened is available at the [Gentoo Linux site][1].
+
+### How the Gentoo GitHub attack happened
+
+Much of the focus in the aftermath of this very significant attack has been on how the attacker was able to gain admin access and what might have been done differently to keep the site safe. The most obvious take-home was that the admin's password was guessed because it too closely related to one that had been captured on another system. This might be like your using "Spring2018" on one system and "Summer2018" on another.
+
+Another problem was that it was unclear how end users might have been able to tell whether or not they had a clean copy of the code, and there was no confirmation as to whether the malicious commits (accessible for a while) would execute.
+
+### Lessons learned from the hack
+
+The lessons learned should come as no surprise. We should all be careful not to use the same password on multiple systems and not to use passwords that relate to each other so strongly that knowing one in a set suggests another.
+
+We also have to admit that two-factor authentication would have prevented this break-in. While something of a burden on users (i.e., they may have to carry a token generator or confirm their login through some secondary service), it very strongly limits who can get access to an account.
+
+Of course the lessons learned should also not overlook what this incident showed us was going right. The fact that the break-in was noticed so quickly and that communications lines were functional meant the break-in could be quickly addressed. The breach was also made public, the repository was only a secondary copy of the main Gentoo source code, and changes in the main repository were signed and could be verified.
+
+#### The best news
+
+The really good news is that it appears that no one was affected by the break in other than the fact that developers were locked out for a while. The hackers weren't able to penetrate Gentoo's master repository (the default location for automatic updates). They also weren't able to get their hands on Gentoo's digital signing key. This means that default updates would have rejected their files as fakes.
+
+The harm that could have been made to Gentoo's reputation was avoided by the precautions in place and their professional handling of the incident. What could have cost them a lot ended up as a confirmation of what they're doing right and added to their determination to make some changes to strengthen their security. They faced up to some cyberbullies and came out stronger and more confident.
+
+### Fixing the potholes
+
+Gentoo is already addressing the weaknesses that contributed to the break-in. They are making frequent backups of their GitHub Organization (i.e., their content), starting to use two-factor authentication by default, working on an incident response plan with a focus on sharing information about a security incident with their users, and tightening procedures around credential revocation. They are also reducing the number of users with elevated privileges, auditing logins, and publishing password policies that mandate the use of password managers.
+
+### Gentoo and GitHub
+
+For readers unfamiliar with Gentoo, it's important to understand that Gentoo is different than most Linux distributions. Users download and then compile the source to build the OS they will then be using. It's as close to the Linux mantra of “know how to do it yourself” as you can get.
+
+Git is a code management system not unlike CVS, and GitHub provides repositories for the code.
+
+### Gentoo strengths
+
+Gentoo users tend to be more knowledgeable about the low-level aspects of the OS (e.g., kernel configuration and hardware support) than most Linux users — probably due to their interest in working with the source code. The OS is also highly scalable and flexible with a "build what you need" focus. The name derives from that of the "Gentoo penguin" — a penguin breed that lives on many sub-Antarctic islands. More information and downloads are available at [www.gentoo.org][2].
+
+### More on the Gentoo GitHub break-in
+
+More information on the break in is available on [Naked Security][3] and (as noted above) the [Gentoo site][1].
+
+Join the Network World communities on [Facebook][4] and [LinkedIn][5] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3287973/linux/the-aftermath-of-the-gentoo-github-hack.html
+
+作者:[Sandra Henry-Stocker][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://www.networkworld.com/author/Sandra-Henry_Stocker/
+[1]:https://wiki.gentoo.org/wiki/Project:Infrastructure/Incident_Reports/2018-06-28_Github
+[2]:https://www.gentoo.org/
+[3]:https://nakedsecurity.sophos.com/2018/06/29/linux-distro-hacked-on-github-all-code-considered-compromised/
+[4]:https://www.facebook.com/NetworkWorld/
+[5]:https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20180710 Users, Groups, and Other Linux Beasts.md b/sources/tech/20180710 Users, Groups, and Other Linux Beasts.md
new file mode 100644
index 0000000000..6083111a32
--- /dev/null
+++ b/sources/tech/20180710 Users, Groups, and Other Linux Beasts.md
@@ -0,0 +1,153 @@
+Users, Groups, and Other Linux Beasts
+======
+
+
+
+Having reached this stage, [after seeing how to manipulate folders/directories][1], but before flinging ourselves headlong into fiddling with files, we have to brush up on the matter of _permissions_ , _users_ and _groups_. Luckily, [there is already an excellent and comprehensive tutorial on this site that covers permissions][2], so you should go and read that right now. In a nutshell: you use permissions to establish who can do stuff to files and directories and what they can do with each file and directory -- read from it, write to it, move it, erase it, etc.
+
+To try everything this tutorial covers, you'll need to create a new user on your system. Let's be practical and make a user for anybody who needs to borrow your computer, that is, what we call a _guest account_.
+
+**WARNING:** _Creating and especially deleting users, along with home directories, can seriously damage your system if, for example, you remove your own user and files by mistake. You may want to practice on another machine which is not your main work machine or on a virtual machine. Regardless of whether you want to play it safe, or not, it is always a good idea to back up your stuff frequently, check the backups have worked correctly, and save yourself a lot of gnashing of teeth later on._
+
+### A New User
+
+You can create a new user with the `useradd` command. Run `useradd` with superuser/root privileges, that is using `sudo` or `su`, depending on your system, you can do:
+```
+sudo useradd -m guest
+
+```
+
+... and input your password. Or do:
+```
+su -c "useradd -m guest"
+
+```
+
+... and input the password of root/the superuser.
+
+( _For the sake of brevity, we'll assume from now on that you get superuser/root privileges by using`sudo`_ ).
+
+By including the `-m` argument, `useradd` will create a home directory for the new user. You can see its contents by listing _/home/guest_.
+
+Next you can set up a password for the new user with
+```
+sudo passwd guest
+
+```
+
+Or you could also use `adduser`, which is interactive and asks you a bunch of questions, including what shell you want to assign the user (yes, there are more than one), where you want their home directory to be, what groups you want them to belong to (more about that in a second) and so on. At the end of running `adduser`, you get to set the password. Note that `adduser` is not installed by default on many distributions, while `useradd` is.
+
+Incidentally, you can get rid of a user with `userdel`:
+```
+sudo userdel -r guest
+
+```
+
+With the `-r` option, `userdel` not only removes the _guest_ user, but also deletes their home directory and removes their entry in the mailing spool, if they had one.
+
+### Skeletons at Home
+
+Talking of users' home directories, depending on what distro you're on, you may have noticed that when you use the `-m` option, `useradd` populates a user's directory with subdirectories for music, documents, and whatnot as well as an assortment of hidden files. To see everything in you guest's home directory run `sudo ls -la /home/guest`.
+
+What goes into a new user's directory is determined by a skeleton directory which is usually _/etc/skel_. Sometimes it may be a different directory, though. To check which directory is being used, run:
+```
+useradd -D
+GROUP=100
+HOME=/home
+INACTIVE=-1
+EXPIRE=
+SHELL=/bin/bash
+SKEL=/etc/skel
+CREATE_MAIL_SPOOL=no
+
+```
+
+This gives you some extra interesting information, but what you're interested in right now is the `SKEL=/etc/skel` line. In this case, and as is customary, it is pointing to _/etc/skel/_.
+
+As everything is customizable in Linux, you can, of course, change what gets put into a newly created user directory. Try this: Create a new directory in _/etc/skel/_ :
+```
+sudo mkdir /etc/skel/Documents
+
+```
+
+And create a file containing a welcome text and copy it over:
+```
+sudo cp welcome.txt /etc/skel/Documents
+
+```
+
+Now delete the guest account:
+```
+sudo userdel -r guest
+
+```
+
+And create it again:
+```
+sudo useradd -m guest
+
+```
+
+Hey presto! Your _Documents/_ directory and _welcome.txt_ file magically appear in the guest's home directory.
+
+You can also modify other things when you create a user by editing _/etc/default/useradd_. Mine looks like this:
+```
+GROUP=users
+HOME=/home
+INACTIVE=-1
+EXPIRE=
+SHELL=/bin/bash
+SKEL=/etc/skel
+CREATE_MAIL_SPOOL=no
+
+```
+
+Most of these options are self-explanatory, but let's take a closer look at the `GROUP` option.
+
+### Herd Mentality
+
+Instead of assigning permissions and privileges to users one by one, Linux and other Unix-like operating systems rely on _groups_. A group is a what you imagine it to be: a bunch of users that are related in some way. On your system you may have a group of users that are allowed to use the printer. They would belong to the _lp_ (for " _line printer_ ") group. The members of the _wheel_ group were traditionally the only ones who could become superuser/root by using _su_. The _network_ group of users can bring up and power down the network. And so on and so forth.
+
+Different distributions have different groups and groups with the same or similar names have different privileges also depending on the distribution you are using. So don't be surprised if what you read in the prior paragraph doesn't match what is going on in your system.
+
+Either way, to see which groups are on your system you can use:
+```
+getent group
+
+```
+
+The `getent` command lists the contents of some of the system's databases.
+
+To find out which groups your current user belongs to, try:
+```
+groups
+
+```
+
+When you create a new user with `useradd`, unless you specify otherwise, the user will only belong to one group: their own. A _guest_ user will belong to a _guest_ group and the group gives the user the power to administer their own stuff and that is about it.
+
+You can create new groups and then add users to them at will with the `groupadd` command:
+```
+sudo groupadd photos
+
+```
+
+will create the _photos_ group, for example. Next time, we’ll use this to build a shared directory all members of the group can read from and write to, and we'll learn even more about permissions and privileges. Stay tuned!
+
+Learn more about Linux through the free ["Introduction to Linux" ][3]course from The Linux Foundation and edX.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/learn/intro-to-linux/2018/7/users-groups-and-other-linux-beasts
+
+作者:[Paul Brown][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://www.linux.com/users/bro66
+[1]:https://www.linux.com/blog/learn/2018/5/manipulating-directories-linux
+[2]:https://www.linux.com/learn/understanding-linux-file-permissions
+[3]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180711 5 open source racing and flying games for Linux.md b/sources/tech/20180711 5 open source racing and flying games for Linux.md
new file mode 100644
index 0000000000..c2b540f498
--- /dev/null
+++ b/sources/tech/20180711 5 open source racing and flying games for Linux.md
@@ -0,0 +1,102 @@
+5 open source racing and flying games for Linux
+======
+
+
+
+Gaming has traditionally been one of Linux's weak points. That has changed somewhat in recent years thanks to Steam, GOG, and other efforts to bring commercial games to multiple operating systems, but those games often are not open source. Sure, the games can be played on an open source operating system, but that is not good enough for an open source purist.
+
+So, can someone who uses only free and open source software find games that are polished enough to present a solid gaming experience without compromising their open source ideals? Absolutely. While open source games are unlikely to ever rival some of the AAA commercial games developed with massive budgets, there are plenty of open source games, in many genres, that are fun to play and can be installed from the repositories of most major Linux distributions. Even if a particular game is not packaged for a particular distribution, it is usually easy to download the game from the project's website to install and play it.
+
+This article looks at racing and flying games. I have already written about [arcade-style games][1], [board and card games][2], and [puzzle games][3]. In future articles, I plan to cover role-playing games and strategy & simulation games.
+
+### Extreme Tux Racer
+
+
+
+Race down snow and ice-covered mountains as Tux or other characters in [Extreme Tux Racer][4]. In this racing game, the goal is to collect herrings and earn the best time. There are many different tracks to choose from, and tracks can be customized by altering the time of day, wind, and weather conditions. While the game has a few rough edges compared to modern, commercial racing games, it is still an enjoyable game to play. The controls and gameplay are straightforward and simple to learn, making this a great choice for kids.
+
+To install Extreme Tux Racer, run the following command:
+
+ * On Fedora: `dnf install extremetuxracer`
+ * On Debian/Ubuntu: `apt install extremetuxracer`
+
+
+
+### FlightGear
+
+
+
+[FlightGear][5] is a full-fledged, open source flight simulator. Multiple aircraft types are available, and 20,000 airports are included in the full world scenery set. That means the player can fly to most parts of the world and have realistic airports and scenery. The full world scenery data is large enough to fill three DVDs. Even the developers are jokingly not sure if that counts as "a feature or a problem," so be aware that a complete installation of FlightGear and all its scenery data is huge. While certainly not the right game for everyone, FlightGear provides a very complete and complex flight simulator experience for players looking to explore the skies on their own computer.
+
+To install FlightGear, run the following command:
+
+ * On Fedora: `dnf install FlightGear`
+ * On Debian/Ubuntu: `apt install flightgear`
+
+
+
+### SuperTuxKart
+
+
+
+[SuperTuxKart][6] takes the basic formula used by Nintendo in the Mario Kart series and applies it to open source mascots. Players race around a variety of tracks in go-karts driven by the mascots for a plethora of open source projects. Character choices include the mascots for open source operating systems and applications of varying familiarity, with options ranging from Tux and Beastie to Gavroche, the mascot for [GNU MediaGoblin][7]. There are several gameplay modes to choose from, including multi-player modes, but many of the tracks are unavailable until they are unlocked by playing the game's single-player story mode. SuperTuxKart's graphics settings can be tweaked to run on everything from older computers with built-in graphics to modern hardware with high-end graphics cards. There is also a version of [SuperTuxKart for Android][8] available. SuperTuxKart is a very good game and great for players of all ages.
+
+To install SuperTuxKart, run the following command:
+
+ * On Fedora: `dnf install supertuxkart`
+ * On Debian/Ubuntu: `apt install supertuxkart`
+
+
+
+### Torcs
+
+
+
+[Torcs][9] is a fairly standard racing game with some extra features for the tech-savvy. Torcs can be played as just a standard racing game, where the player drives around a track trying to get the best time, but an alternative usage is as a platform to develop an artificial intelligence driver that can drive itself through Torcs' tracks. The cars and tracks included with the game vary in style, ranging from stock car racing to rally racing, but the gameplay is pretty typical for a racing game. Keyboard, mouse, joystick, and steering wheel input are all supported, but keyboard and mouse input modes are a little hard to get used to. Single-player races range from practice runs to championships, and there is a [split-screen multi-player mode][10] for up to four players.
+
+To install Torcs, run the following command:
+
+ * On Fedora: `dnf install torcs`
+ * On Debian/Ubuntu: `apt install torcs`
+
+
+
+### Trigger Rally
+
+
+
+[Trigger Rally][11] is an off-road, single-player rally racing game. The player needs to make it to each checkpoint in time to complete the race, which is standard racing game fare, but still enjoyable. The gameplay is more arcade-like than a strict racing simulator like Torcs but more realistic than cartoonish racing games like SuperTuxKart. The tracks are interesting and the controls are responsive, but a little too sensitive when playing with a keyboard. Joystick controls are available by changing an option in a configuration file. Unfortunately, development on the game is slow going, with the latest release in 2016, but the gameplay that is already there is fun.
+
+To install Trigger Rally, run the following command:
+
+ * On Debian/Ubuntu: `apt install trigger-rally`
+
+
+
+Unfortunately, Trigger Rally is not packaged for Fedora.
+
+Did I miss one of your favorite open source racing or flying games? Share it in the comments below.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/racing-flying-games-linux
+
+作者:[About The Author;Joshua Allen Holm;Mlis;Med;Is One Of Opensource.Com'S Community Moderators. Joshua'S Main Interests Are Digital Humanities;Open Access;Open Educational Resources. He Can Reached At][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/holmja
+[1]:https://opensource.com/article/18/1/arcade-games-linux
+[2]:https://opensource.com/article/18/3/card-board-games-linux
+[3]:https://opensource.com/article/18/6/puzzle-games-linux
+[4]:https://extremetuxracer.sourceforge.io/
+[5]:http://home.flightgear.org/
+[6]:https://supertuxkart.net/Main_Page
+[7]:https://mediagoblin.org
+[8]:https://play.google.com/store/apps/details?id=org.supertuxkart.stk
+[9]:http://torcs.sourceforge.net/index.php
+[10]:http://torcs.sourceforge.net/?name=Sections&op=viewarticle&artid=30#c4_4_4
+[11]:http://trigger-rally.sf.net/
diff --git a/sources/tech/20180711 Becoming a senior developer 9 experiences you ll encounter.md b/sources/tech/20180711 Becoming a senior developer 9 experiences you ll encounter.md
new file mode 100644
index 0000000000..7ff8e59007
--- /dev/null
+++ b/sources/tech/20180711 Becoming a senior developer 9 experiences you ll encounter.md
@@ -0,0 +1,141 @@
+Becoming a senior developer: 9 experiences you'll encounter
+============================================================
+
+
+
+Plenty of career guides suggest appropriate steps to take if you want a management track. But what if you want to stay technical—and simply become the best possible programmer? These non-obvious markers let you know you’re on the right path.
+
+Many programming career guidelines stress the skills a software developer is expected to acquire. Such general advice suggests that someone who wants to focus on a technical track—as opposed to, say, [taking a management path to CIO][5]—should go after the skills needed to mentor junior developers, design future application features, build out release engineering systems, and set company standards.
+
+That isn’t this article.
+
+Being a developer—a good one—isn't just about writing code. To be successful, you do a lot of planning, you deal with catastrophes, and you prevent catastrophes. Not to mention you spend plenty of time [working with other humans][6] about what your code should do.
+
+Following are a number of markers you’ll likely encounter as your career progresses and you become a more accomplished developer. You’ll have highs that boost you up and remind you how awesome you are. You'll also encounter lows that keep you humble and give you wisdom—at least in retrospect, if you respond to them appropriately.
+
+These experiences may feel good, they may be uncomfortable, or they may be downright scary. They're all learning experiences—at least for those developers who sincerely want to move forward, in both skills and professional ambition. These experiences often change the way developers look at their job or how they approach the next problem. It's why an experienced developer's value to a company is more than just a list of technology buzzwords.
+
+Here, in no particular order, is a sampling of what you'll run into on your way to becoming a senior developer—not in terms of a specific job title but being confident about creating quality code that serves users.
+
+### You write your first big bug into production
+
+Probably your initial step into the big leagues is the first bug you write into production. It's a sickening feeling. You know that the software you're working on is now broken in some significant way because of something you did, code you wrote, or a test you didn't run.
+
+No matter how good a programmer you are, you'll make mistakes. You're a human, and that's part of what we do.
+
+Most developers learn from the “bug that went live” experience. You promise never to make the same bug again. You analyze what happened, and you think about how the bug could have been prevented. For me, one effect of discovering I let a bug into production code is that it reinforced my belief that compiler warnings and static analysis tools are a programmer's best friend.
+
+You repeat the process when it happens again. It _will_ happen again, but as your programming skill improves, it happens less frequently.
+
+### You delete production data for the first time
+
+It might be a `DROP TABLE` in production or [a mistaken `rm -rf`][7]. Maybe you clicked on the wrong volume to format. You get an uneasy feeling that "this is taking longer to run than I would expect. It's not running on... oh, no!" followed by a mad scramble to fix it.
+
+Data loss has long-term effects on a growing-wiser developer much like the production bug. Afterward, you re-examine how you work. It teaches you to take more safeguards than you did previously. Maybe you decide to create a more rigorous rotation schedule for backups, or even start having a backup schedule at all.
+
+As with the bug in production, you learn that you can survive making a mistake, and it's not the end of the world.
+
+### You automate away part of your job
+
+There's an old saying that you can't get promoted if you can't be replaced. Anything that ties you to a specific job or task is an anchor on your ability to move up in the company or be assigned newer and more interesting tasks.
+
+When good programmers find themselves doing drudgework as part of their job, they find a way to let a machine do it. If they are stuck [scanning server logs][8] every Monday looking for problems, they'll install a tool like Logwatch to summarize the results. When there are many servers to be monitored, a good programmer will turn to a more capable tool that analyzes logs on multiple servers.
+
+Unsure how to get started with containers? Yes, we have a guide for that. Get Containers for Dummies.
+
+[Download now][4]
+
+In each case, wise programmers provide more value to their company, because an automated system is much cheaper than a senior programmer’s salary. They also grow personally by eliminating drudgery, leaving them more time to work on more challenging tasks.
+
+### You use existing code instead of writing your own
+
+A senior programmer knows that code that doesn't get written doesn't have bugs, and that many problems, both common and uncommon, have already been solved—in many cases, multiple times.
+
+Senior programmers know that the chances are very low that they can write, test, and debug their own code for a task faster or cheaper than existing code that does what they want. It doesn't have to be perfect to make it worth their while.
+
+It might take a little bit of turning down your ego to make it happen, but that's an excellent skill for senior programmers to have, too.
+
+### You are publicly recognized for achievements
+
+Many people aren't comfortable with public recognition. It's embarrassing. We have these amazing skills, and we like the feeling of helping others, but we can be embarrassed when it's called out.
+
+Praise comes in many forms and many sizes. Maybe it's winning an "employee of the quarter" award for a project you drove and being presented a plaque onstage. It could be as low-key as your team leader saying, "Thanks to Cheryl for implementing that new microservice."
+
+Whatever it is, accept it graciously and appreciatively, even if you're embarrassed by the attention. Don't diminish the praise you receive with, "Oh, it was nothing" or anything similar. Accept credit for the things that users and co-workers appreciate. Thank the speaker and say you were glad you could be of service.
+
+First, this is the polite thing to do. When people praise you, they want it to be acknowledged. In addition, that warm recognition helps you in the future. Remembering it gets you through those crappy days, such as when you uncover bugs in your code.
+
+### You turn down a user request
+
+As much as we love being superheroes who can do amazing things with computers, sometimes turning down a request is best for the organization. Part of being a senior programmer is knowing when not to write code. A senior programmer knows that every bit of code in a codebase is a chance for things to go wrong and a potential future cost for maintenance.
+
+You might be uncomfortable the first time you tell a user that you won’t be incorporating his maybe-even-useful suggestion. But this is a notable occasion. It means you understand the application and its role in a larger context. It also means you “own” the software, in a positive, confident way.
+
+The organization need not be an employer, either. Open source project managers deal with this all the time, when they have to tell a user, "Sorry, it doesn't fit with where the project is going.”
+
+### You know when to fight for what's right and when it really doesn't matter
+
+Rookie programmers are full of knowledge straight from school, having learned all the right ways to do things. They're eager to apply their knowledge and make amazing things happen for their employers. However, they're often surprised to find that out in the business world, things sometimes don't get done the "right" way.
+
+There's an old military saying: No plan survives contact with the enemy. It's the same with new programmers and project plans. Sometimes in the heat of the battle of business, the purist computer science techniques learned in school fall by the wayside.
+
+Maybe the database schema gets slapped together in a way that isn't perfect [fifth normal form][9]. Sometimes code gets cut and pasted rather than refactored out into a new function or library. Plenty of production systems run on shell scripts and prayers. The wise programmer knows when to push for the right way to do things and when to take the cheap way out.
+
+The first time you do it, it feels like you're selling out your principles. It’s not. The balance between academic purism and the realities of getting work done can be a delicate one, and that knowledge of when to do things less than perfectly is part of the wisdom you’ll acquire.
+
+### You are asked what to do
+
+After a while, you'll have earned a reputation in your organization for getting things done. It won’t be just for having expertise in a certain area—it’ll be wisdom. Someone will come to you and ask for guidance with a project or a problem.
+
+That person isn't just asking you for help with a problem. You are being asked to lead.
+
+A common situation is when you are asked to help a team of less-experienced developers that's navigating difficult new terrain or needs shepherding on a project. That's when you'll be called on to help not just do things but show people how to improve their own skills.
+
+It might also be leadership from a technical point of view. Your boss might say, "We need a new indexing solution. Find out what you can about FooIndex and BarSearch, and let me know what you propose." That's the sort of responsibility given only to someone who has demonstrated wisdom and experience.
+
+### You are seriously headhunted for the first time
+
+Recruiting professionals are always looking for talent. Most recruiters seem to do random emailing and LinkedIn harvesting. But every so often, they find out about talented performers and hunt them down.
+
+When that happens, it's a feather in your cap. Maybe a former colleague spoke to a recruiter friend trying to place a developer at a company that needs the skills you have. If you get a personal recommendation for a position—even if you don’t want the job—it means you've really arrived. You're recognized as an expert, or someone who brings value to an organization, enough to recommend you to others.
+
+### Onward
+
+I hope that my little list helps prompt some thought about [where you are in your career][10] or [where you might be headed][11]. Markers and milestones can help you understand what’s around you and what to expect.
+
+This list is far from complete, of course. Everyone has their own story. In fact, one of the ways to know you’ve hit a milestone is when you find yourself telling a story about it to others. When you do find yourself looking back at a tough situation, make sure to reflect on what it means to you and why. Experience is a great teacher—if you listen to it.
+
+What are your markers? How did you know you had finally become a senior programmer? Tweet at [@enterprisenxt][12] and let me know.
+
+This article/content was written by the individual writer identified and does not necessarily reflect the view of Hewlett Packard Enterprise Company.
+
+ [][13]
+
+### 作者简介
+
+Andy Lester has been a programmer and developer since the 1980s, when COBOL walked the earth. He is the author of the job-hunting guide [Land the Tech Job You Love][2] (2009, Pragmatic Bookshelf). Andy has been an active contributor to the open source community for decades, most notably as the creator of the grep-like code search tool [ack][3].
+
+--------------------------------------------------------------------------------
+
+via: https://www.hpe.com/us/en/insights/articles/becoming-a-senior-developer-9-experiences-youll-encounter-1807.html
+
+作者:[Andy Lester ][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.hpe.com/us/en/insights/contributors/andy-lester.html
+[1]:https://www.hpe.com/us/en/insights/contributors/andy-lester.html
+[2]:https://pragprog.com/book/algh/land-the-tech-job-you-love
+[3]:https://beyondgrep.com/
+[4]:https://www.hpe.com/us/en/resources/storage/containers-for-dummies.html?jumpid=in_510384402_seniordev0718
+[5]:https://www.hpe.com/us/en/insights/articles/7-career-milestones-youll-meet-on-the-cio-and-it-management-track-1805.html
+[6]:https://www.hpe.com/us/en/insights/articles/how-to-succeed-in-it-without-social-skills-1705.html
+[7]:https://www.hpe.com/us/en/insights/articles/the-linux-commands-you-should-never-use-1712.html
+[8]:https://www.hpe.com/us/en/insights/articles/back-to-basics-what-sysadmins-must-know-about-logging-and-monitoring-1805.html
+[9]:http://www.bkent.net/Doc/simple5.htm
+[10]:https://www.hpe.com/us/en/insights/articles/career-interventions-when-your-it-career-needs-a-swift-kick-1806.html
+[11]:https://www.hpe.com/us/en/insights/articles/how-to-avoid-an-it-career-dead-end-1806.html
+[12]:https://twitter.com/enterprisenxt
+[13]:https://www.hpe.com/us/en/insights/contributors/andy-lester.html
diff --git a/sources/tech/20180711 Open hardware meets open science in a multi-microphone hearing aid project.md b/sources/tech/20180711 Open hardware meets open science in a multi-microphone hearing aid project.md
new file mode 100644
index 0000000000..f6a348980d
--- /dev/null
+++ b/sources/tech/20180711 Open hardware meets open science in a multi-microphone hearing aid project.md
@@ -0,0 +1,69 @@
+Open hardware meets open science in a multi-microphone hearing aid project
+======
+
+
+
+Since [Opensource.com][1] first published the story of the [GNU/Linux hearing aid][2] research platform in 2010, there has been an explosion in the availability of miniature system boards, including the original BeagleBone in 2011 and the Raspberry Pi in 2012. These ARM processor devices built from cellphone chips differ from the embedded system reference boards of the past—not only by being far less expensive and more widely available—but also because they are powerful enough to run familiar GNU/Linux distributions and desktop applications.
+
+What took a laptop to accomplish in 2010 can now be achieved with a pocket-sized board costing a fraction as much. Because a hearing aid does not need a screen and a small ARM board's power consumption is far less than a typical laptop's, field trials can potentially run all day. Additionally, the system's lower weight is easier for the end user to wear.
+
+The [openMHA project][3]—from the [Carl von Ossietzky Universität Oldenburg][4] in Germany, [BatAndCat Sound Labs][5] in Palo Alto, California, and [HörTech gGmbH][6]—is an open source platform for improving hearing aids using real-time audio signal processing. For the next iteration of the research platform, openMHA is using the US$ 55 [BeagleBone Black][7] board with its 1GHz Cortex A8 CPU.
+
+The BeagleBone family of boards enjoys guaranteed long-term availability, thanks to its open hardware design that can be produced by anyone with the requisite knowledge. For example, BeagleBone hardware variations are available from community members including [SeeedStudio][8] and [SanCloud][9].
+
+![BeagleBone Black][11]
+
+The BeagleBone Black is open hardware finding its way into research labs.
+
+Spatial filtering techniques, including [beamforming][12] and [directional microphone arrays][13], can suppress distracting noise, focusing audio amplification on the point in space where the hearing aid wearer is looking, rather than off to the side where a truck might be thundering past. These neat tricks can use two or three microphones per ear, yet typical sound cards for embedded devices support only one or two input channels in total.
+
+Fortunately, the [McASP][14] communication peripheral in Texas Instruments chips offers multiple channels and support for the [I2S protocol][15], originally devised by Philips for short digital audio interconnects inside CD players. This means an add-on "cape" board can hook directly into the BeagleBone's audio system without using USB or other external interfaces. The direct approach helps reduce the signal processing delay into the range where it is undetectable by the hearing aid wearer.
+
+The openMHA project uses an audio cape developed by the [Hearing4all][16] project, which combines three stereo codecs to provide up to six input channels. Like the BeagleBone, the Cape4all is open hardware with design files available on [GitHub][17].
+
+The Cape4all, [presented recently][18] at the Linux Audio Conference in Berlin, Germany, runs at a sample rate from 24kHz to 96Khz with as few as 12 samples per period, leading to internal latencies in the sub-millisecond range. With hearing enhancement algorithms running, the complete round-trip latency from a microphone to an earpiece has been measured at 3.6 milliseconds (at 48KHz sample rate with 16 samples per period). Using the speed of sound for comparison, this latency is similar to listening to someone just over four feet away without a hearing aid.
+
+![Cape4all ][20]
+
+The Cape4all might be the first multi-microphone hearing aid on an open hardware platform.
+
+The next step for the openMHA project is to develop a [Bluetooth Low Energy][21] module that will enable remote control of the research device from a smartphone and perhaps route phone calls and media playback to the hearing aid. Consumer hearing aids support Bluetooth, so the openMHA research platform must do so, too.
+
+Also, instructions for running a [stereo hearing aid on the Raspberry Pi][22] were released by an openMHA user-project.
+
+As evidenced by the openMHA project, open source innovation has transformed digital hearing aid research from an esoteric branch of audiology into an accessible open science.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/open-hearing-aid-platform
+
+作者:[Daniel James,Christopher Obbard][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/daniel-james
+[1]:http://Opensource.com
+[2]:https://opensource.com/life/10/9/open-source-designing-next-generation-digital-hearing-aids
+[3]:http://www.openmha.org/
+[4]:https://www.uni-oldenburg.de/
+[5]:http://batandcat.com/
+[6]:http://www.hoertech.de/
+[7]:https://beagleboard.org/black
+[8]:https://www.seeedstudio.com/
+[9]:http://www.sancloud.co.uk
+[10]:/file/403046
+[11]:https://opensource.com/sites/default/files/uploads/1-beagleboneblack-600.jpg (BeagleBone Black)
+[12]:https://en.wikipedia.org/wiki/Beamforming
+[13]:https://en.wikipedia.org/wiki/Microphone_array
+[14]:https://en.wikipedia.org/wiki/McASP
+[15]:https://en.wikipedia.org/wiki/I%C2%B2S
+[16]:http://hearing4all.eu/EN/
+[17]:https://github.com/HoerTech-gGmbH/Cape4all
+[18]:https://lac.linuxaudio.org/2018/pages/event/35/
+[19]:/file/403051
+[20]:https://opensource.com/sites/default/files/uploads/2-beaglebone-wireless-with-cape4all-labelled-600.jpg (Cape4all )
+[21]:https://en.wikipedia.org/wiki/Bluetooth_Low_Energy
+[22]:http://www.openmha.org/userproject/2017/12/21/openMHA-on-raspberry-pi.html
diff --git a/sources/tech/20180716 Confessions of a recovering Perl hacker.md b/sources/tech/20180716 Confessions of a recovering Perl hacker.md
new file mode 100644
index 0000000000..48a904cf35
--- /dev/null
+++ b/sources/tech/20180716 Confessions of a recovering Perl hacker.md
@@ -0,0 +1,46 @@
+Confessions of a recovering Perl hacker
+======
+
+
+
+My name's MikeCamel, and I'm a Perl hacker.
+
+There, I've said it. That's the first step.
+
+My handle on IRC, Twitter and pretty much everywhere else in the world is "MikeCamel." This is because, back in the day, when there were no chat apps—no apps at all, in fact—I was in a technical "chatroom" and the name "Mike" had been taken. I looked around, and the first thing I noticed on my desk was the [Camel Book][1], the O'Reilly Perl Bible.
+
+I have the second edition now, but this was the first edition. Yesterday, I happened to pick up the second edition, the really thick one, to show someone on a video conference call, and it had a thin layer of dust on it. I was a little bit ashamed, but a little bit relieved as well.
+
+For years, I was a sysadmin. Just bits and pieces, from time to time. Nothing serious, you understand—mainly my systems, my friends' systems. Sometimes I'd admin systems owned by other people—even at work. I always had it under control, and I was always able to step away. There were whole weeks—well days—when I didn't administer a system at all. With the exception of remote systems, which felt different, somehow less serious.
+
+What pushed it over the edge, on reflection, was the Perl. This was the '90s—the 1990s, just to be clear—when Perl was young, and free, and didn't even pretend to be object-oriented. We all know it still isn't, but those youngsters—they like to pretend, and we old lags, well, we play along.
+
+The thing about Perl is that it just starts small, with a regexp here, a text-file line counter there. Nothing that couldn't have been managed quite easily in Bash or Sed or Awk. But once you've written a couple of scripts, you're in—there's no going back. Long-term Perl users remember how we started, and we see the newbs going the same way.
+
+I taught myself Perl in order to collate static web pages from five disparate FoxPro databases. I did it by starting at the beginning of the Camel Book and reading as much of it as I could before my brain started to hurt, then picking up a few pages back and carrying on. And then writing some Perl, which always failed, mainly because of lack of semicolons to start with, and then because I didn't really understand much of what I was doing. But I kept with it until I wasn't just writing scripts to collate databases, but scripts to load data into a single database and using CGI to serve pages in real time. My wife knew, and some of my colleagues knew, but I don't think they fully understood how deep I was in.
+
+You know that Perl has you when you start looking for admin tasks to automate with it. Tasks that don't need automating and that would be much, much faster if you performed them by hand. When you start scouring the web for three- or four-character commands that, when executed, alphabetise, spell-check, and decrypt three separate files in parallel and output them to STDERR, ROT13ed.
+
+I was lucky: I escaped in time. I always insisted on commenting my Perl. I never got to the very end of the Camel Book. Not in one reading, anyway. I never experimented with the darker side-effects; three or four separate operations per line was always enough for me. Over time, as my responsibilities moved more to programming, I cut back on the sysadmin tasks. Of course, that didn't stop the Perl use completely—it's amazing how often you can find an excuse to automate a task and how often Perl is the answer. But it reduced my Perl to manageable levels, levels that didn't affect my day-to-day functioning.
+
+I'd like to pretend that I've stopped, but you never really give up on Perl, and it never gives up on you.
+
+I'd like to pretend that I've stopped, but you never really give up on Perl, and it never gives up on you. My Camel Book (2nd ed.) is still around, even if it's a little dusty. I always check that the core modules are installed on any systems I run. And about five months ago, I found that my 10-year-old daughter had some mathematics homework that was susceptible to brute-forcing. Just a few lines. A couple of loops. No more than that. Nothing that I didn't feel went out of scope.
+
+I'd like to pretend that I've stopped, but you never really give up on Perl, and it never gives up on you. My Camel Book (2nd ed.) is still around, even if it's a little dusty. I always check that the core modules are installed on any systems I run. And about five months ago, I found that my 10-year-old daughter had some mathematics homework that was susceptible to brute-forcing. Just a few lines. A couple of loops. No more than that. Nothing that I didn't feel went out of scope.
+
+I discovered after she handed in the results that it hadn't produced the correct results, but I didn't mind. It was tight, it was elegant, it was beautiful. It was Perl. My Perl.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/confessions-recovering-perl-hacker
+
+作者:[Mike Bursell][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/mikecamel
+[1]:https://en.wikipedia.org/wiki/Programming_Perl
diff --git a/sources/tech/20180716 How To Find The Mounted Filesystem Type In Linux.md b/sources/tech/20180716 How To Find The Mounted Filesystem Type In Linux.md
new file mode 100644
index 0000000000..5005cf44f7
--- /dev/null
+++ b/sources/tech/20180716 How To Find The Mounted Filesystem Type In Linux.md
@@ -0,0 +1,259 @@
+How To Find The Mounted Filesystem Type In Linux
+======
+
+
+
+As you may already know, the Linux supports numerous filesystems, such as Ext4, ext3, ext2, sysfs, securityfs, FAT16, FAT32, NTFS, and many. The most commonly used filesystem is Ext4. Ever wondered what type of filesystem are you currently using in your Linux system? No? Worry not! We got your back. This guide explains how to find the mounted filesystem type in Unix-like operating systems.
+
+### Find The Mounted Filesystem Type In Linux
+
+There can be many ways to find the filesystem type in Linux. Here, I have given 8 different methods. Let us get started, shall we?
+
+#### Method 1 – Using findmnt command
+
+This is the most commonly used method to find out the type of a filesystem. The **findmnt** command will list all mounted filesystems or search for a filesystem. The findmnt command can be able to search in **/etc/fstab** , **/etc/mtab** or **/proc/self/mountinfo**.
+
+findmnt command comes pre-installed in most Linux distributions, because it is part of the package named **util-linux**. Just in case if it is not available, simply install this package and you’re good to go. For instance, you can install **util-linux** package in Debian-based systems using command:
+```
+$ sudo apt install util-linux
+
+```
+
+Let us go ahead and see how to use findmnt command to find out the mounted filesystems.
+
+If you run it without any arguments/options, it will list all mounted filesystems in a tree-like format as shown below.
+```
+$ findmnt
+
+```
+
+**Sample output:**
+
+![][2]
+
+As you can see, the findmnt command displays the target mount point (TARGET), source device (SOURCE), file system type (FSTYPE), and relevant mount options, like whether the filesystem is read/write or read-only. (OPTIONS). In my case, my root(/) filesystem type is EXT4.
+
+If you don’t like/want to display the output in tree-like format, use **-l** flag to display in simple, plain format.
+```
+$ findmnt -l
+
+```
+
+![][3]
+
+You can also list a particular type of filesystem, for example **ext4** , using **-t** option.
+```
+$ findmnt -t ext4
+TARGET SOURCE FSTYPE OPTIONS
+/ /dev/sda2 ext4 rw,relatime,commit=360
+└─/boot /dev/sda1 ext4 rw,relatime,commit=360,data=ordered
+
+```
+
+Findmnt can produce df style output as well.
+```
+$ findmnt --df
+
+```
+
+Or
+```
+$ findmnt -D
+
+```
+
+Sample output:
+```
+SOURCE FSTYPE SIZE USED AVAIL USE% TARGET
+dev devtmpfs 3.9G 0 3.9G 0% /dev
+run tmpfs 3.9G 1.1M 3.9G 0% /run
+/dev/sda2 ext4 456.3G 342.5G 90.6G 75% /
+tmpfs tmpfs 3.9G 32.2M 3.8G 1% /dev/shm
+tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
+bpf bpf 0 0 0 - /sys/fs/bpf
+tmpfs tmpfs 3.9G 8.4M 3.9G 0% /tmp
+/dev/loop0 squashfs 82.1M 82.1M 0 100% /var/lib/snapd/snap/core/4327
+/dev/sda1 ext4 92.8M 55.7M 30.1M 60% /boot
+tmpfs tmpfs 788.8M 32K 788.8M 0% /run/user/1000
+gvfsd-fuse fuse.gvfsd-fuse 0 0 0 - /run/user/1000/gvfs
+
+```
+
+You can also display filesystems for a specific device, or mountpoint too.
+
+Search for a device:
+```
+$ findmnt /dev/sda1
+TARGET SOURCE FSTYPE OPTIONS
+/boot /dev/sda1 ext4 rw,relatime,commit=360,data=ordered
+
+```
+
+Search for a mountpoint:
+```
+$ findmnt /
+TARGET SOURCE FSTYPE OPTIONS
+/ /dev/sda2 ext4 rw,relatime,commit=360
+
+```
+
+You can even find filesystems with specific label:
+```
+$ findmnt LABEL=Storage
+
+```
+
+For more details, refer the man pages.
+```
+$ man findmnt
+
+```
+
+The findmnt command is just enough to find the type of a mounted filesystem in Linux. It is created for that specific purpose only. However, there are also few other ways available to find out the filesystem type. If you’re interested to know, read on.
+
+#### Method 2 – Using blkid command
+
+The **blkid** command is used locate and print block device attributes. It is also part of the util-linux package, so you don’t bother to install it.
+
+To find out the type of a filesystem using blkid command, run:
+```
+$ blkid /dev/sda1
+
+```
+
+#### Method 3 – Using df command
+
+The **df** command is used to report filesystem disk space usage in Unix-like operating systems. To find the type of all mounted filesystems, simply run:
+```
+$ df -T
+
+```
+
+**Sample output:**
+
+![][4]
+
+For details about df command, refer the following guide.
+
+Also, check man pages.
+```
+$ man df
+
+```
+
+#### Method 4 – Using file command
+
+The **file** command determines the type of a specified file. It works just fine for files with no file extension.
+
+Run the following command to find the filesystem type of a partition:
+```
+$ sudo file -sL /dev/sda1
+[sudo] password for sk:
+/dev/sda1: Linux rev 1.0 ext4 filesystem data, UUID=83a1dbbf-1e15-4b45-94fe-134d3872af96 (needs journal recovery) (extents) (large files) (huge files)
+
+```
+
+Check man pages for more details:
+```
+$ man file
+
+```
+
+#### Method 5 – Using fsck command
+
+The **fsck** command is used to check the integrity of a filesystem or repair it. You can find the type of a filesystem by passing the partition as an argument like below.
+```
+$ fsck -N /dev/sda1
+fsck from util-linux 2.32
+[/usr/bin/fsck.ext4 (1) -- /boot] fsck.ext4 /dev/sda1
+
+```
+
+For more details, refer man pages.
+```
+$ man fsck
+
+```
+
+#### Method 6 – Using fstab Command
+
+**fstab** is a file that contains static information about the filesystems. This file usually contains the mount point, filesystem type and mount options.
+
+To view the type of a filesystem, simply run:
+```
+$ cat /etc/fstab
+
+```
+
+![][5]
+
+For more details, refer man pages.
+```
+$ man fstab
+
+```
+
+#### Method 7 – Using lsblk command
+
+The **lsblk** command displays the information about devices.
+
+To display info about mounted filesystems, simply run:
+```
+$ lsblk -f
+NAME FSTYPE LABEL UUID MOUNTPOINT
+loop0 squashfs /var/lib/snapd/snap/core/4327
+sda
+├─sda1 ext4 83a1dbbf-1e15-4b45-94fe-134d3872af96 /boot
+├─sda2 ext4 4d25ddb0-5b20-40b4-ae35-ef96376d6594 /
+└─sda3 swap 1f8f5e2e-7c17-4f35-97e6-8bce7a4849cb [SWAP]
+sr0
+
+```
+
+For more details, refer man pages.
+```
+$ man lsblk
+
+```
+
+#### Method 8 – Using mount command
+
+The **mount** command is used to mount a local or remote filesystems in Unix-like systems.
+
+To find out the type of a filesystem using mount command, do:
+```
+$ mount | grep "^/dev"
+/dev/sda2 on / type ext4 (rw,relatime,commit=360)
+/dev/sda1 on /boot type ext4 (rw,relatime,commit=360,data=ordered)
+
+```
+
+For more details, refer man pages.
+```
+$ man mount
+
+```
+
+And, that’s all for now folks. You now know 8 different Linux commands to find out the type of a mounted Linux filesystems. If you know any other methods, feel free to let me know in the comment section below. I will check and update this guide accordingly.
+
+More good stuffs to come. Stay tuned!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/how-to-find-the-mounted-filesystem-type-in-linux/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
+[1]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[2]:http://www.ostechnix.com/wp-content/uploads/2018/07/findmnt-1.png
+[3]:http://www.ostechnix.com/wp-content/uploads/2018/07/findmnt-2.png
+[4]:http://www.ostechnix.com/wp-content/uploads/2018/07/df.png
+[5]:http://www.ostechnix.com/wp-content/uploads/2018/07/fstab.png
diff --git a/sources/tech/20180716 Users, Groups and Other Linux Beasts- Part 2.md b/sources/tech/20180716 Users, Groups and Other Linux Beasts- Part 2.md
new file mode 100644
index 0000000000..b164bb6cf5
--- /dev/null
+++ b/sources/tech/20180716 Users, Groups and Other Linux Beasts- Part 2.md
@@ -0,0 +1,110 @@
+Users, Groups and Other Linux Beasts: Part 2
+======
+
+In this ongoing tour of Linux, we’ve looked at [how to manipulate folders/directories][1], and now we’re continuing our discussion of _permissions_ , _users_ and _groups_ , which are necessary to establish who can manipulate which files and directories. [Last time,][2] we showed how to create new users, and now we’re going to dive right back in:
+
+You can create new groups and then add users to them at will with the `groupadd` command. For example, using:
+```
+sudo groupadd photos
+
+```
+
+will create the _photos_ group.
+
+You’ll need to [create a directory][1] hanging off the root directory:
+```
+sudo mkdir /photos
+
+```
+
+If you run `ls -l /`, one of the lines will be:
+```
+drwxr-xr-x 1 root root 0 jun 26 21:14 photos
+
+```
+
+The first _root_ in the output is the user owner and the second _root_ is the group owner.
+
+To transfer the ownership of the _/photos_ directory to the _photos_ group, use
+```
+chgrp photos /photos
+
+```
+
+The `chgrp` command typically takes two parameters, the first parameter is the group that will take ownership of the file or directory and the second is the file or directory you want to give over to the the group.
+
+Next, run `ls -l /` and you'll see the line has changed to:
+```
+drwxr-xr-x 1 root photos 0 jun 26 21:14 photos
+
+```
+
+You have successfully transferred the ownership of your new directory over to the _photos_ group.
+
+Then, add your own user and the _guest_ user to the _photos_ group:
+```
+sudo usermod -a -G photos
+sudo usermod guest -a -G photos
+
+```
+
+You may have to log out and log back in to see the changes, but, when you do, running `groups` will show _photos_ as one of the groups you belong to.
+
+A couple of things to point out about the `usermod` command shown above. First: Be careful not to use the `-g` option instead of `-G`. The `-g` option changes your primary group and could lock you out of your stuff if you use it by accident. `-G`, on the other hand, _adds_ you to the groups listed and doesn't mess with the primary group. If you want to add your user to more groups than one, list them one after another, separated by commas, no spaces, after `-G`:
+```
+sudo usermod -a -G photos,pizza,spaceforce
+
+```
+
+Second: Be careful not to forget the `-a` parameter. The `-a` parameter stands for _append_ and attaches the list of groups you pass to `-G` to the ones you already belong to. This means that, if you don't include `-a`, the list of groups you already belong to, will be overwritten, again locking you out from stuff you need.
+
+Neither of these are catastrophic problems, but it will mean you will have to add your user back manually to all the groups you belonged to, which can be a pain, especially if you have lost access to the _sudo_ and _wheel_ group.
+
+### Permits, Please!
+
+There is still one more thing to do before you can copy images to the _/photos_ directory. Notice how, when you did `ls -l /` above, permissions for that folder came back as _drwxr-xr-x_.
+
+If you read [the article I recommended at the beginning of this post][3], you'll know that the first _d_ indicates that the entry in the file system is a directory, and then you have three sets of three characters ( _rwx_ , _r-x_ , _r-x_ ) that indicate the permissions for the user owner ( _rwx_ ) of the directory, then the group owner ( _r-x_ ), and finally the rest of the users ( _r-x_ ). This means that the only person who has write permissions so far, that is, the only person who can copy or create files in the _/photos_ directory, is the _root_ user.
+
+But [that article I mentioned also tells you how to change the permissions for a directory or file][3]:
+```
+sudo chmod g+w /photos
+
+```
+
+Running `ls -l /` after that will give you _/photos_ permissions as _drwxrwxr-x_ which is what you want: group members can now write into the directory.
+
+Now you can try and copy an image or, indeed, any other file to the directory and it should go through without a problem:
+```
+cp image.jpg /photos
+
+```
+
+The _guest_ user will also be able to read and write from the directory. They will also be able to read and write to it, and even move or delete files created by other users within the shared directory.
+
+### Conclusion
+
+The permissions and privileges system in Linux has been honed over decades. inherited as it is from the old Unix systems of yore. As such, it works very well and is well thought out. Becoming familiar with it is essential for any Linux sysadmin. In fact, you can't do much admining at all unless you understand it. But, it's not that hard.
+
+Next time, we'll be dive into files and see the different ways of creating, manipulating, and destroying them in creative ways. Always fun, that last one.
+
+See you then!
+
+Learn more about Linux through the free ["Introduction to Linux" ][4]course from The Linux Foundation and edX.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/learn/intro-to-linux/2018/7/users-groups-and-other-linux-beasts-part-2
+
+作者:[Paul Brown][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://www.linux.com/users/bro66
+[1]:https://www.linux.com/blog/learn/2018/5/manipulating-directories-linux
+[2]:https://www.linux.com/learn/intro-to-linux/2018/7/users-groups-and-other-linux-beasts
+[3]:https://www.linux.com/learn/understanding-linux-file-permissions
+[4]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180719 Building tiny container images.md b/sources/tech/20180719 Building tiny container images.md
new file mode 100644
index 0000000000..bdaef5f08c
--- /dev/null
+++ b/sources/tech/20180719 Building tiny container images.md
@@ -0,0 +1,362 @@
+Building tiny container images
+======
+
+
+
+When [Docker][1] exploded onto the scene a few years ago, it brought containers and container images to the masses. Although Linux containers existed before then, Docker made it easy to get started with a user-friendly command-line interface and an easy-to-understand way to build images using the Dockerfile format. But while it may be easy to jump in, there are still some nuances and tricks to building container images that are usable, even powerful, but still small in size.
+
+### First pass: Clean up after yourself
+
+Some of these examples involve the same kind of cleanup you would use with a traditional server, but more rigorously followed. Smaller image sizes are critical for quickly moving images around, and storing multiple copies of unnecessary data on disk is a waste of resources. Consequently, these techniques should be used more regularly than on a server with lots of dedicated storage.
+
+An example of this kind of cleanup is removing cached files from an image to recover space. Consider the difference in size between a base image with [Nginx][2] installed by `dnf` with and without the metadata and yum cache cleaned up:
+```
+# Dockerfile with cache
+
+FROM fedora:28
+
+LABEL maintainer Chris Collins
+
+
+
+RUN dnf install -y nginx
+
+
+
+-----
+
+
+
+# Dockerfile w/o cache
+
+FROM fedora:28
+
+LABEL maintainer Chris Collins
+
+
+
+RUN dnf install -y nginx \
+
+ && dnf clean all \
+
+ && rm -rf /var/cache/yum
+
+
+
+-----
+
+
+
+[chris@krang] $ docker build -t cache -f Dockerfile .
+
+[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}"
+
+| head -n 1
+
+cache: 464 MB
+
+
+
+[chris@krang] $ docker build -t no-cache -f Dockerfile-wo-cache .
+
+[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}" | head -n 1
+
+no-cache: 271 MB
+
+```
+
+That is a significant difference in size. The version with the `dnf` cache is almost twice the size of the image without the metadata and cache. Package manager cache, Ruby gem temp files, `nodejs` cache, even downloaded source tarballs are all perfect candidates for cleaning up.
+
+### Layers—a potential gotcha
+
+Unfortunately (or fortunately, as you’ll see later), based on the way layers work with containers, you cannot simply add a `RUN rm -rf /var/cache/yum` line to your Dockerfile and call it a day. Each instruction of a Dockerfile is stored in a layer, with changes between layers applied on top. So even if you were to do this:
+```
+RUN dnf install -y nginx
+
+RUN dnf clean all
+
+RUN rm -rf /var/cache/yum
+
+```
+
+...you’d still end up with three layers, one of which contains all the cache, and two intermediate layers that "remove" the cache from the image. But the cache is actually still there, just as when you mount a filesystem over the top of another one, the files are there—you just can’t see or access them.
+
+You’ll notice that the example in the previous section chains the cache cleanup in the same Dockerfile instruction where the cache is generated:
+```
+RUN dnf install -y nginx \
+
+ && dnf clean all \
+
+ && rm -rf /var/cache/yum
+
+```
+
+This is a single instruction and ends up being a single layer within the image. You’ll lose a bit of the Docker (*ahem*) cache this way, making a rebuild of the image slightly longer, but the cached data will not end up in your final image. As a nice compromise, just chaining related commands (e.g., `yum install` and `yum clean all`, or downloading, extracting and removing a source tarball, etc.) can save a lot on your final image size while still allowing you to take advantage of the Docker cache for quicker development.
+
+This layer "gotcha" is more subtle than it first appears, though. Because the image layers document the _changes_ to each layer, one upon another, it’s not just the existence of files that add up, but any change to the file. For example, _even changing the mode_ of the file creates a copy of that file in the new layer.
+
+For example, the output of `docker images` below shows information about two images. The first, `layer_test_1`, was created by adding a single 1GB file to a base CentOS image. The second image, `layer_test_2`, was created `FROM layer_test_1` and did nothing but change the mode of the 1GB file with `chmod u+x`.
+```
+layer_test_2 latest e11b5e58e2fc 7 seconds ago 2.35 GB
+
+layer_test_1 latest 6eca792a4ebe 2 minutes ago 1.27 GB
+
+```
+
+As you can see, the new image is more than 1GB larger than the first. Despite the fact that `layer_test_1` is only the first two layers of `layer_test_2`, there’s still an extra 1GB file floating around hidden inside the second image. This is true anytime you remove, move, or change any file during the image build process.
+
+### Purpose-built images vs. flexible images
+
+An anecdote: As my office heavily invested in [Ruby on Rails][3] applications, we began to embrace the use of containers. One of the first things we did was to create an official Ruby base image for all of our teams to use. For simplicity’s sake (and suffering under “this is the way we did it on our servers”), we used [rbenv][4] to install the latest four versions of Ruby into the image, allowing our developers to migrate all of their applications into containers using a single image. This resulted in a very large but flexible (we thought) image that covered all the bases of the various teams we were working with.
+
+This turned out to be wasted work. The effort required to maintain separate, slightly modified versions of a particular image was easy to automate, and selecting a specific image with a specific version actually helped to identify applications approaching end-of-life before a breaking change was introduced, wreaking havoc downstream. It also wasted resources: When we started to split out the different versions of Ruby, we ended up with multiple images that shared a single base and took up very little extra space if they coexisted on a server, but were considerably smaller to ship around than a giant image with multiple versions installed.
+
+That is not to say building flexible images is not helpful, but in this case, creating purpose-build images from a common base ended up saving both storage space and maintenance time, and each team could modify their setup however they needed while maintaining the benefit of the common base image.
+
+### Start without the cruft: Add what you need to a blank image
+
+As friendly and easy-to-use as the _Dockerfile_ is, there are tools available that offer the flexibility to create very small Docker-compatible container images without the cruft of a full operating system—even those as small as the standard Docker base images.
+
+[I’ve written about Buildah before][5], and I’ll mention it again because it is flexible enough to create an image from scratch using tools from your host to install packaged software and manipulate the image. Those tools then never need to be included in the image itself.
+
+Buildah replaces the `docker build` command. With it, you can mount the filesystem of your container image to your host machine and interact with it using tools from the host.
+
+Let’s try Buildah with the Nginx example from above (ignoring caches for now):
+```
+#!/usr/bin/env bash
+
+set -o errexit
+
+
+
+# Create a container
+
+container=$(buildah from scratch)
+
+
+
+# Mount the container filesystem
+
+mountpoint=$(buildah mount $container)
+
+
+
+# Install a basic filesystem and minimal set of packages, and nginx
+
+dnf install --installroot $mountpoint --releasever 28 glibc-minimal-langpack nginx --setopt install_weak_deps=false -y
+
+
+
+# Save the container to an image
+
+buildah commit --format docker $container nginx
+
+
+
+# Cleanup
+
+buildah unmount $container
+
+
+
+# Push the image to the Docker daemon’s storage
+
+buildah push nginx:latest docker-daemon:nginx:latest
+
+```
+
+You’ll notice we’re no longer using a Dockerfile to build the image, but a simple Bash script, and we’re building it from a scratch (or blank) image. The Bash script mounts the container’s root filesystem to a mount point on the host, and then uses the hosts’ command to install the packages. This way the package manager doesn’t even have to exist inside the container.
+
+Without extra cruft—all the extra stuff in the base image, like `dnf`, for example—the image weighs in at only 304 MB, more than 100 MB smaller than the Nginx image built with a Dockerfile above.
+```
+[chris@krang] $ docker images |grep nginx
+
+docker.io/nginx buildah 2505d3597457 4 minutes ago 304 MB
+
+```
+
+_Note: The image name has`docker.io` appended to it due to the way the image is pushed into the Docker daemon’s namespace, but it is still the image built locally with the build script above._
+
+That 100 MB is already a huge savings when you consider a base image is already around 300 MB on its own. Installing Nginx with a package manager brings in a ton of dependencies, too. For something compiled from source using tools from the host, the savings can be even greater because you can choose the exact dependencies and not pull in any extra files you don’t need.
+
+If you’d like to try this route, [Tom Sweeney][6] wrote a much more in-depth article, [Creating small containers with Buildah][7], which you should check out.
+
+Using Buildah to build images without a full operating system and included build tools can enable much smaller images than you would otherwise be able to create. For some types of images, we can take this approach even further and create images with _only_ the application itself included.
+
+### Create images with only statically linked binaries
+
+Following the same philosophy that leads us to ditch administrative and build tools inside images, we can go a step further. If we specialize enough and abandon the idea of troubleshooting inside of production containers, do we need Bash? Do we need the [GNU core utilities][8]? Do we _really_ need the basic Linux filesystem? You can do this with any compiled language that allows you to create binaries with [statically linked libraries][9]—where all the libraries and functions needed by the program are copied into and stored within the binary itself.
+
+This is a relatively popular way of doing things within the [Golang][10] community, so we’ll use a Go application to demonstrate.
+
+The Dockerfile below takes a small Go Hello-World application and compiles it in an image `FROM golang:1.8`:
+```
+FROM golang:1.8
+
+
+
+ENV GOOS=linux
+
+ENV appdir=/go/src/gohelloworld
+
+
+
+COPY ./ /go/src/goHelloWorld
+
+WORKDIR /go/src/goHelloWorld
+
+
+
+RUN go get
+
+RUN go build -o /goHelloWorld -a
+
+
+
+CMD ["/goHelloWorld"]
+
+```
+
+The resulting image, containing the binary, the source code, and the base image layer comes in at 716 MB. The only thing we actually need for our application is the compiled binary, however. Everything else is unused cruft that gets shipped around with our image.
+
+If we disable `cgo` with `CGO_ENABLED=0` when we compile, we can create a binary that doesn’t wrap C libraries for some of its functions:
+```
+GOOS=linux CGO_ENABLED=0 go build -a goHelloWorld.go
+
+```
+
+The resulting binary can be added to an empty, or "scratch" image:
+```
+FROM scratch
+
+COPY goHelloWorld /
+
+CMD ["/goHelloWorld"]
+
+```
+
+Let’s compare the difference in image size between the two:
+```
+[ chris@krang ] $ docker images
+
+REPOSITORY TAG IMAGE ID CREATED SIZE
+
+goHello scratch a5881650d6e9 13 seconds ago 1.55 MB
+
+goHello builder 980290a100db 14 seconds ago 716 MB
+
+```
+
+That’s a huge difference. The image built from `golang:1.8` with the `goHelloWorld` binary in it (tagged "builder" above) is _460_ times larger than the scratch image with just the binary. The entirety of the scratch image with the binary is only 1.55 MB. That means we’d be shipping around 713 MB of unnecessary data if we used the builder image.
+
+As mentioned above, this method of creating small images is used often in the Golang community, and there is no shortage of blog posts on the subject. [Kelsey Hightower][11] wrote [an article on the subject][12] that goes into more detail, including dealing with dependencies other than just C libraries.
+
+### Consider squashing, if it works for you
+
+There’s an alternative to chaining all the commands into layers in an attempt to save space: Squashing your image. When you squash an image, you’re really exporting it, removing all the intermediate layers, and saving a single layer with the current state of the image. This has the advantage of reducing that image to a much smaller size.
+
+Squashing layers used to require some creative workarounds to flatten an image—exporting the contents of a container and re-importing it as a single layer image, or using tools like `docker-squash`. Starting in version 1.13, Docker introduced a handy flag, `--squash`, to accomplish the same thing during the build process:
+```
+FROM fedora:28
+
+LABEL maintainer Chris Collins
+
+
+
+RUN dnf install -y nginx
+
+RUN dnf clean all
+
+RUN rm -rf /var/cache/yum
+
+
+
+[chris@krang] $ docker build -t squash -f Dockerfile-squash --squash .
+
+[chris@krang] $ docker images --format "{{.Repository}}: {{.Size}}" | head -n 1
+
+squash: 271 MB
+
+```
+
+Using `docker squash` with this multi-layer Dockerfile, we end up with another 271MB image, as we did with the chained instruction example. This works great for this use case, but there’s a potential gotcha.
+
+“What? ANOTHER gotcha?”
+
+Well, sort of—it’s the same issue as before, causing problems in another way.
+
+### Going too far: Too squashed, too small, too specialized
+
+Images can share layers. The base may be _x_ megabytes in size, but it only needs to be pulled/stored once and each image can use it. The effective size of all the images sharing layers is the base layers plus the diff of each specific change on top of that. In this way, thousands of images may take up only a small amount more than a single image.
+
+This is a drawback with squashing or specializing too much. When you squash an image into a single layer, you lose any opportunity to share layers with other images. Each image ends up being as large as the total size of its single layer. This might work well for you if you use only a few images and run many containers from them, but if you have many diverse images, it could end up costing you space in the long run.
+
+Revisiting the Nginx squash example, we can see it’s not a big deal for this case. We end up with Fedora, Nginx installed, no cache, and squashing that is fine. Nginx by itself is not incredibly useful, though. You generally need customizations to do anything interesting—e.g., configuration files, other software packages, maybe some application code. Each of these would end up being more instructions in the Dockerfile.
+
+With a traditional image build, you would have a single base image layer with Fedora, a second layer with Nginx installed (with or without cache), and then each customization would be another layer. Other images with Fedora and Nginx could share these layers.
+
+Need an image:
+```
+[ App 1 Layer ( 5 MB) ] [ App 2 Layer (6 MB) ]
+
+[ Nginx Layer ( 21 MB) ] ------------------^
+
+[ Fedora Layer (249 MB) ]
+
+```
+
+But if you squash the image, then even the Fedora base layer is squashed. Any squashed image based on Fedora has to ship around its own Fedora content, adding another 249 MB for _each image!_
+```
+[ Fedora + Nginx + App 1 (275 MB)] [ Fedora + Nginx + App 2 (276 MB) ]
+
+```
+
+This also becomes a problem if you build lots of highly specialized, super-tiny images.
+
+As with everything in life, moderation is key. Again, thanks to how layers work, you will find diminishing returns as your container images become smaller and more specialized and can no longer share base layers with other related images.
+
+Images with small customizations can share base layers. As explained above, the base may be _x_ megabytes in size, but it only needs to be pulled/stored once and each image can use it. The effective size of all the images is the base layers plus the diff of each specific change on top of that. In this way, thousands of images may take up only a small amount more than a single image.
+```
+[ specific app ] [ specific app 2 ]
+
+[ customizations ]--------------^
+
+[ base layer ]
+
+```
+
+If you go too far with your image shrinking and you have too many variations or specializations, you can end up with many images, none of which share base layers and all of which take up their own space on disk.
+```
+ [ specific app 1 ] [ specific app 2 ] [ specific app 3 ]
+
+```
+
+### Conclusion
+
+There are a variety of different ways to reduce the amount of storage space and bandwidth you spend working with container images, but the most effective way is to reduce the size of the images themselves. Whether you simply clean up your caches (avoiding leaving them orphaned in intermediate layers), squash all your layers into one, or add only static binaries in an empty image, it’s worth spending some time looking at where bloat might exist in your container images and slimming them down to an efficient size.
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/building-container-images
+
+作者:[Chris Collins][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/clcollins
+[1]:https://www.docker.com/
+[2]:https://www.nginx.com/
+[3]:https://rubyonrails.org/
+[4]:https://github.com/rbenv/rbenv
+[5]:https://opensource.com/article/18/6/getting-started-buildah
+[6]:https://twitter.com/TSweeneyRedHat
+[7]:https://opensource.com/article/18/5/containers-buildah
+[8]:https://www.gnu.org/software/coreutils/coreutils.html
+[9]:https://en.wikipedia.org/wiki/Static_library
+[10]:https://golang.org/
+[11]:https://twitter.com/kelseyhightower
+[12]:https://medium.com/@kelseyhightower/optimizing-docker-images-for-static-binaries-b5696e26eb07
diff --git a/sources/tech/20180720 A brief history of text-based games and open source.md b/sources/tech/20180720 A brief history of text-based games and open source.md
new file mode 100644
index 0000000000..2b8728fb39
--- /dev/null
+++ b/sources/tech/20180720 A brief history of text-based games and open source.md
@@ -0,0 +1,142 @@
+A brief history of text-based games and open source
+======
+
+
+
+The [Interactive Fiction Technology Foundation][1] (IFTF) is a non-profit organization dedicated to the preservation and improvement of technologies enabling the digital art form we call interactive fiction. When a Community Moderator for Opensource.com suggested an article about IFTF, the technologies and services it supports, and how it all intersects with open source, I found it a novel angle to the decades-long story I’ve so often told. The history of IF is longer than—but quite enmeshed with—the modern FOSS movement. I hope you’ll enjoy my sharing it here.
+
+### Definitions and history
+
+To me, the term interactive fiction includes any video game or digital artwork whose audience interacts with it primarily through text. The term originated in the 1980s when parser-driven text adventure games—epitomized in the United States by [Zork][2], [The Hitchhiker’s Guide to the Galaxy][3], and the rest of [Infocom][4]’s canon—defined home-computer entertainment. Its mainstream commercial viability had guttered by the 1990s, but online hobbyist communities carried on the tradition, releasing both games and game-creation tools.
+
+After a quarter century, interactive fiction now comprises a broad and sparkling variety of work, from puzzle-laden text adventures to sprawling and introspective hypertexts. Regular online competitions and festivals provide a great place to peruse and play new work: The English-language IF world enjoys annual events including [Spring Thing][5] and [IFComp][6], the latter a centerpiece of modern IF since 1995—which also makes it the longest-lived continually running game showcase event of its kind in any genre. [IFComp’s crop of judged-and-ranked entries from 2017][7] shows the amazing diversity in form, style, and subject matter that text-based games boast today.
+
+(I specify "English-language" above because IF communities tend to self-segregate by language, perhaps due to the technology's focus on writing. There are also annual IF events in [French][8] and [Italian][9], for example, and I've heard of at least one Chinese IF festival. Happily, these borders are porous; during the four years I managed IFComp, it has welcomed English-translated work from all international communities.)
+
+![counterfeit monkey game screenshot][11]
+
+Starting a new game of Emily Short's "Counterfeit Monkey," running on the interpreter Lectrote (both open source software).
+
+Also due to its focus on text, IF presents some of the most accessible platforms for both play and authorship. Almost anyone who can read digital text—including users of assistive technology such as text-to-speech software—can play most IF works. Likewise, IF creation is open to all writers willing to learn and work with its tools and techniques.
+
+This brings us to IF’s long relationship with open source, which has helped enable the art form’s availability since its commercial heyday. I'll provide an overview of contemporary open-source IF creation tools, and then discuss the ancient and sometimes curious tradition of IF works that share their source code.
+
+### The world of open source IF tools
+
+A number of development platforms, most of which are open source, are available to create traditional parser-driven IF in which the user types commands—for example, `go north,` `get lamp`, `pet the cat`, or `ask Zoe about quantum mechanics`—to interact with the game’s world. The early 1990s saw the emergence of several hacker-friendly parser-game development kits; those still in use today include [TADS][12], [Alan][13], and [Quest][14]—all open, with the latter two bearing FOSS licenses.
+
+But by far the most prominent of these is [Inform][15], first released by Graham Nelson in 1993 and now maintained by a team Nelson still leads. Inform source is semi-open, in an unusual fashion: Inform 6, the previous major version, [makes its source available through the Artistic License][16]. This has more immediate relevance than may be obvious, since the otherwise proprietary Inform 7 holds Inform 6 at its core, translating its [remarkable natural-language syntax][17] into its predecessor’s more C-like code before letting it compile the work down into machine code.
+
+![inform 7 IDE screenshot][19]
+
+The Inform 7 IDE, loaded up with documentation and a sample project.
+
+Inform games run on a virtual machine, a relic of the Infocom era when that publisher targeted a VM so that it could write a single game that would run on Apple II, Commodore 64, Atari 800, and other flavors of the "[home computer][20]." Fewer popular operating systems exist today, but Inform’s virtual machines—the relatively modern [Glulx][21] or the charmingly antique [Z-machine][22], a reverse-engineered clone of Infocom’s historical VM—let Inform-created work run on any computer with an Inform interpreter. Currently, popular cross-platform interpreters include desktop programs like [Lectrote][23] and [Gargoyle][24] or browser-based ones like [Quixe][25] and [Parchment][26]. All are open source.
+
+If the pace of Inform’s development has slowed in its maturity, it remains vital through an active and transparent ecosystem—just like any other popular open source project. In Inform’s case, this includes the aforementioned interpreters, [a collection of language extensions][27] (usually written in a mix of Inform 6 and 7), and of course, all the work created with it and shared with the world, sometimes with source included (I’ll return to that topic later in this article).
+
+IF creation tools invented in the 21st century tend to explore player interactions outside of the traditional parser, generating hypertext-driven work that any modern web browser can load. Chief among these is [Twine][28], originally developed by Chris Klimas in 2009 and under active development by many contributors today as [a GNU-licensed open source project][29]. (In fact, [Twine][30] can trace its OSS lineage back to [TiddlyWiki][31], the project from which Klimas initially derived it.)
+
+Twine represents a sort of maximally [open and accessible approach][30] to IF development: Beyond its own FOSS nature, it renders its output as self-contained websites, relying not on machine code requiring further specialized interpretation but the open and well-exercised standards of HTML, CSS, and JavaScript. As a creative tool, Twine can match its own exposed complexity to the creator’s skill level. Users with little or no programming knowledge can create simple but playable IF work, while those with more coding and design skills—including those developing these skills by making Twine games—can develop more sophisticated projects. Little wonder that Twine’s visibility and popularity in educational contexts has grown quite a bit in recent years.
+
+Other noteworthy open source IF development projects include the MIT-licensed [Undum][32] by Ian Millington, and [ChoiceScript][33] by Dan Fabulich and the [Choice of Games][34] team—both of which also target the web browser as the gameplay platform. Looking beyond strict development systems like these, web-based IF gives us a rich and ever-churning ecosystem of open source work, such as furkle’s [collection of Twine-extending tools][35] and Liza Daly’s [Windrift][36], a JavaScript framework purpose-built for her own IF games.
+
+### Programs, games, and game-programs
+
+Twine benefits from [a standing IFTF program dedicated to its support][37], allowing the public to help fund its maintenance and development. IFTF also directly supports two long-time public services, IFComp and the IF Archive, both of which depend upon and contribute back into open software and technologies.
+
+![Harmonia opening screen shot][39]
+
+The opening of Liza Daly's "Harmonia," created with the Windrift open source IF-creation framework.
+
+The Perl- and JavaScript-based application that runs the IFComp’s website has been [a shared-source project][40] since 2014, and it reflects [the stew of FOSS licenses used by its IF-specific sub-components][41], including the various code libraries that allow parser-driven competition entries to run in a web browser. [The IF Archive][42]—online since 1992 and [an IFTF project since 2017][43]—is a set of mirrored repositories based entirely on ancient and stable internet standards, with [a little open source Python script][44] to handle indexing.
+
+### At last, the fun part: Let's talk about open source text games
+
+The bulk of the archive [comprises games][45], of course—years and years of games, reflecting decades of evolving game-design trends and IF tool development.
+
+Lots of IF work shares its source code, and the community’s quick-start solution for finding it is simple: [Search the IFDB for the tag "source available"][46]. (The IFDB is yet another long-running IF community service, run privately by TADS creator Mike Roberts.) Users who are comfortable with a more bare-bones interface may also wish to browse [the `/games/source` directory][47] of the IF Archive, which groups content by development platform and written language (there's also a lot of work either too miscellaneous or too ancient to categorize floating at the top).
+
+A little bit of random sampling of these code-sharing games reveals an interesting dilemma: Unlike the wider world of open source software, the IF community lacks a generally agreed-upon way of licensing all the code that it generates. Unlike a software tool—including all the tools we use to build IF—an interactive fiction game is a work of art in the most literal sense, meaning that an open source license intended for software would fit it no better than it would any other work of prose or poetry. But then again, an IF game is also a piece of software, and it exhibits source-code patterns and techniques that its creator may legitimately wish to share with the world. What is an open source-aware IF creator to do?
+
+Some games address this by passing their code into the public domain, either through explicit license or—as in the case of [the original 42-year-old Adventure by Crowther and Woods][48]—through community fiat. Some try to split the difference, rolling their own license that allows for free re-use of a game’s exposed business logic but prohibits the creation of work derived specifically from its prose. This is the tack I took when I opened up the source of my own game, [The Warbler’s Nest][49]. Lord knows how well that’d stand up in court, but I didn’t have any better ideas at the time.
+
+Naturally, you can find work that simply puts everything under a single common license and never mind the naysayers. A prominent example is [Emily Short’s epic Counterfeit Monkey][50], released in its entirety under a Creative Commons 4.0 license. [CC frowns at its application to code][51], but you could argue that [the strangely prose-like nature of Inform 7 source][52] makes it at least a little more compatible with a CC license than a more traditional software project would be.
+
+### What now, adventurer?
+
+If you are eager to start exploring the world of interactive fiction, here are a few links to check out:
+
+
++ As mentioned above, IFDB and the IF Archive both present browsable interfaces to more than 40 years worth of collected interactive fiction work. Much of this is playable in a web browser, but some require additional interpreter programs. IFDB can help you find and install these.
+
+ IFComp’s annual results pages provide another view into the best of this free and archive-available work.
+
++ The Interactive Fiction Technology Foundation is a charitable non-profit organization that helps support Twine, IFComp, and the IF Archive, as well as improve the accessibility of IF, explore IF’s use in education, and more. Join its mailing list to receive IFTF’s monthly newsletter, peruse its blog, and browse some thematic merchandise.
+
++ John Paul Wohlscheid wrote this article about open-source IF tools earlier this year. It covers some platforms not mentioned here, so if you’re still hungry for more, have a look.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/interactive-fiction-tools
+
+作者:[Jason Mclntosh][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/jmac
+[1]:http://iftechfoundation.org/
+[2]:https://en.wikipedia.org/wiki/Zork
+[3]:https://en.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy_(video_game)
+[4]:https://en.wikipedia.org/wiki/Infocom
+[5]:http://www.springthing.net/
+[6]:http://ifcomp.org/
+[7]:https://ifcomp.org/comp/2017
+[8]:http://www.fiction-interactive.fr/
+[9]:http://www.oldgamesitalia.net/content/marmellata-davventura-2018
+[10]:/file/403396
+[11]:https://opensource.com/sites/default/files/uploads/monkey.png (counterfeit monkey game screenshot)
+[12]:http://tads.org/
+[13]:https://www.alanif.se/
+[14]:http://textadventures.co.uk/quest/
+[15]:http://inform7.com/
+[16]:https://github.com/DavidKinder/Inform6
+[17]:http://inform7.com/learn/man/RB_4_1.html#e307
+[18]:/file/403386
+[19]:https://opensource.com/sites/default/files/uploads/inform.png (inform 7 IDE screenshot)
+[20]:https://www.youtube.com/watch?v=bu55q_3YtOY
+[21]:http://ifwiki.org/index.php/Glulx
+[22]:http://ifwiki.org/index.php/Z-machine
+[23]:https://github.com/erkyrath/lectrote
+[24]:https://github.com/garglk/garglk/
+[25]:http://eblong.com/zarf/glulx/quixe/
+[26]:https://github.com/curiousdannii/parchment
+[27]:https://github.com/i7/extensions
+[28]:http://twinery.org/
+[29]:https://github.com/klembot/twinejs
+[30]:/article/18/7/twine-vs-renpy-interactive-fiction
+[31]:https://tiddlywiki.com/
+[32]:https://github.com/idmillington/undum
+[33]:https://github.com/dfabulich/choicescript
+[34]:https://www.choiceofgames.com/
+[35]:https://github.com/furkle
+[36]:https://github.com/lizadaly/windrift
+[37]:http://iftechfoundation.org/committees/twine/
+[38]:/file/403391
+[39]:https://opensource.com/sites/default/files/uploads/harmonia.png (Harmonia opening screen shot)
+[40]:https://github.com/iftechfoundation/ifcomp
+[41]:https://github.com/iftechfoundation/ifcomp/blob/master/LICENSE.md
+[42]:https://www.ifarchive.org/
+[43]:http://blog.iftechfoundation.org/2017-06-30-iftf-is-adopting-the-if-archive.html
+[44]:https://github.com/iftechfoundation/ifarchive-ifmap-py
+[45]:https://www.ifarchive.org/indexes/if-archiveXgames
+[46]:http://ifdb.tads.org/search?sortby=ratu&searchfor=%22source+available%22
+[47]:https://www.ifarchive.org/indexes/if-archiveXgamesXsource.html
+[48]:http://ifdb.tads.org/viewgame?id=fft6pu91j85y4acv
+[49]:https://github.com/jmacdotorg/warblers-nest/
+[50]:https://github.com/i7/counterfeit-monkey
+[51]:https://creativecommons.org/faq/#can-i-apply-a-creative-commons-license-to-software
+[52]:https://github.com/i7/counterfeit-monkey/blob/master/Counterfeit%20Monkey.materials/Extensions/Counterfeit%20Monkey/Liquids.i7x
diff --git a/sources/tech/20180723 Setting Up a Timer with systemd in Linux.md b/sources/tech/20180723 Setting Up a Timer with systemd in Linux.md
new file mode 100644
index 0000000000..27841dec61
--- /dev/null
+++ b/sources/tech/20180723 Setting Up a Timer with systemd in Linux.md
@@ -0,0 +1,165 @@
+Setting Up a Timer with systemd in Linux
+======
+
+
+
+Previously, we saw how to enable and disable systemd services [by hand][1], [at boot time and on power down][2], [when a certain device is activated][3], and [when something changes in the filesystem][4].
+
+Timers add yet another way of starting services, based on... well, time. Although similar to cron jobs, systemd timers are slightly more flexible. Let's see how they work.
+
+### "Run when"
+
+Let's expand the [Minetest][5] [service you set up][1] in [the first two articles of this series][2] as our first example on how to use timer units. If you haven't read those articles yet, you may want to go and give them a look now.
+
+So you will "improve" your Minetest set up by creating a timer that will run the game's server 1 minute after boot up has finished instead of right away. The reason for this could be that, as you want your service to do other stuff, like send emails to the players telling them the game is available, you will want to make sure other services (like the network) are fully up and running before doing anything fancy.
+
+Jumping in at the deep end, your _minetest.timer_ unit will look like this:
+```
+# minetest.timer
+[Unit]
+Description=Runs the minetest.service 1 minute after boot up
+
+[Timer]
+OnBootSec=1 m
+Unit=minetest.service
+
+[Install]
+WantedBy=basic.target
+
+```
+
+Not hard at all.
+
+As usual, you have a `[Unit]` section with a description of what the unit does. Nothing new there. The `[Timer]` section is new, but it is pretty self-explanatory: it contains information on when the service will be triggered and the service to trigger. In this case, the `OnBootSec` is the directive you need to tell systemd to run the service after boot has finished.
+
+Other directives you could use are:
+
+ * `OnActiveSec=`, which tells systemd how long to wait after the timer itself is activated before starting the service.
+ * `OnStartupSec=`, on the other hand, tells systemd how long to wait after systemd was started before starting the service.
+ * `OnUnitActiveSec=` tells systemd how long to wait after the service the timer is activating was last activated.
+ * `OnUnitInactiveSec=` tells systemd how long to wait after the service the timer is activating was last deactivated.
+
+
+
+Continuing down the _minetest.timer_ unit, the `basic.target` is usually used as a synchronization point for late boot services. This means it makes _minetest.timer_ wait until local mount points and swap devices are mounted, sockets, timers, path units and other basic initialization processes are running before letting _minetest.timer_ start. As we explained in [the second article on systemd units][2], _targets_ are like the old run levels and can be used to put your machine into one state or another, or, like here, to tell your service to wait until a certain state has been reached.
+
+The _minetest.service_ you developed in the first two articles [ended up][2] looking like this:
+```
+# minetest.service
+[Unit]
+Description= Minetest server
+Documentation= https://wiki.minetest.net/Main_Page
+
+[Service]
+Type= simple
+User=
+
+ExecStart= /usr/games/minetest --server
+ExecStartPost= /home//bin/mtsendmail.sh "Ready to rumble?" "Minetest Starting up"
+
+TimeoutStopSec= 180
+ExecStop= /home//bin/mtsendmail.sh "Off to bed. Nightie night!" "Minetest Stopping in 2 minutes"
+ExecStop= /bin/sleep 120
+ExecStop= /bin/kill -2 $MAINPID
+
+[Install]
+WantedBy= multi-user.target
+
+```
+
+There’s nothing you need to change here. But you do have to change _mtsendmail.sh_ (your email sending script) from this:
+```
+#!/bin/bash
+# mtsendmail
+sleep 20
+echo $1 | mutt -F /home//.muttrc -s "$2" my_minetest@mailing_list.com
+sleep 10
+
+```
+
+to this:
+```
+#!/bin/bash
+# mtsendmail.sh
+echo $1 | mutt -F /home/paul/.muttrc -s "$2" pbrown@mykolab.com
+
+```
+
+What you are doing is stripping out those hacky pauses in the Bash script. Systemd does the waiting now.
+
+### Making it work
+
+To make sure things work, disable _minetest.service_ :
+```
+sudo systemctl disable minetest
+
+```
+
+so it doesn't get started when the system starts; and, instead, enable _minetest.timer_ :
+```
+sudo systemctl enable minetest.timer
+
+```
+
+Now you can reboot you server machine and, when you run `sudo journalctl -u minetest.*` you will see how, first the _minetest.timer_ unit gets executed and then the _minetest.service_ starts up after a minute... more or less.
+
+![minetest timer][7]
+
+Figure 1: The minetest.service gets started one minute after the minetest.timer... more or less.
+
+[Used with permission][8]
+
+### A Matter of Time
+
+A couple of clarifications about why the _minetest.timer_ entry in the systemd's Journal shows its start time as 09:08:33, while the _minetest.service_ starts at 09:09:18, that is less than a minute later: First, remember we said that the `OnBootSec=` directive calculates when to start a service from when boot is complete. By the time _minetest.timer_ comes along, boot has finished a few seconds ago.
+
+The other thing is that systemd gives itself a margin of error (by default, 1 minute) to run stuff. This helps distribute the load when several resource-intensive processes are running at the same time: by giving itself a minute, systemd can wait for some processes to power down. This also means that _minetest.service_ will start somewhere between the 1 minute and 2 minute mark after boot is completed, but when exactly within that range is anybody's guess.
+
+For the record, [you can change the margin of error with `AccuracySec=` directive][9].
+
+Another thing you can do is check when all the timers on your system are scheduled to run or the last time the ran:
+```
+systemctl list-timers --all
+
+```
+
+![check timer][11]
+
+Figure 2: Check when your timers are scheduled to fire or when they fired last.
+
+[Used with permission][8]
+
+The final thing to take into consideration is the format you should use to express the periods of time. Systemd is very flexible in that respect: `2 h`, `2 hours` or `2hr` will all work to express a 2 hour delay. For seconds, you can use `seconds`, `second`, `sec`, and `s`, the same way as for minutes you can use `minutes`, `minute`, `min`, and `m`. You can see a full list of time units systemd understands by checking `man systemd.time`.
+
+### Next Time
+
+You'll see how to use calendar dates and times to run services at regular intervals and how to combine timers and device units to run services at defined point in time after you plug in some hardware.
+
+See you then!
+
+Learn more about Linux through the free ["Introduction to Linux" ][12]course from The Linux Foundation and edX.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/learn/intro-to-linux/2018/7/setting-timer-systemd-linux
+
+作者:[Paul Brown][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://www.linux.com/users/bro66
+[1]:https://www.linux.com/blog/learn/intro-to-linux/2018/5/writing-systemd-services-fun-and-profit
+[2]:https://www.linux.com/blog/learn/2018/5/systemd-services-beyond-starting-and-stopping
+[3]:https://www.linux.com/blog/intro-to-linux/2018/6/systemd-services-reacting-change
+[4]:https://www.linux.com/blog/learn/intro-to-linux/2018/6/systemd-services-monitoring-files-and-directories
+[5]:https://www.minetest.net/
+[6]:/files/images/minetest-timer-1png
+[7]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/minetest-timer-1.png?itok=TG0xJvYM (minetest timer)
+[8]:/licenses/category/used-permission
+[9]:https://www.freedesktop.org/software/systemd/man/systemd.timer.html#AccuracySec=
+[10]:/files/images/minetest-timer-2png
+[11]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/minetest-timer-2.png?itok=pYxyVx8- (check timer)
+[12]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180723 System Snapshot And Restore Utility For Linux.md b/sources/tech/20180723 System Snapshot And Restore Utility For Linux.md
new file mode 100644
index 0000000000..26630a372a
--- /dev/null
+++ b/sources/tech/20180723 System Snapshot And Restore Utility For Linux.md
@@ -0,0 +1,237 @@
+System Snapshot And Restore Utility For Linux
+======
+
+
+**CYA** , stands for **C** over **Y** our **A** ssets, is a free, open source system snapshot and restore utility for any Unix-like operating systems that uses BASH shell. Cya is portable and supports many popular filesystems such as EXT2/3/4, XFS, UFS, GPFS, reiserFS, JFS, BtrFS, and ZFS etc. Please note that **Cya will not backup the actual user data**. It only backups and restores the operating system itself and not your actual user data. **Cya is a system restore utility**. By default, it will backup all key directories like /bin/, /lib/, /usr/, /var/ and several others. You can, however, define your own directories and files path to include in the backup, so Cya will pick those up as well. Also, it is possible define some directories/files to skip from the backup. For example, you can skip /var/logs/ if you don’t log files. Cya actually uses **Rsync** backup method under the hood. However, Cya is super easier than Rsync when creating rolling backups.
+
+When restoring your operating system, Cya will rollback the OS using your backup profile which you created earlier. You can either restore the entire system or any specific directories only. Also, you can easily access the backup files even without a complete rollback using your terminal or file manager. ANother notable feature is we can generate a custom recovery script to automate the mounting of your system partition(s) when you restore off a live CD, USB, or network image. In a nutshell, CYA can help you to restore your system to previous states when you end-up with a broken system caused by software update, configuration changes, intrusions/hacks, etc.
+
+### Installing CYA
+
+Installing CYA is very easy. All you have to do is download Cya binary and put it in your system path.
+```
+$ git clone https://github.com/cleverwise/cya.git
+
+```
+
+This will clone the latest cya version in a directory called cya in your current working directory.
+
+Next, copy the cya binary to your path or wherever you want.
+```
+$ sudo cp cya/cya /usr/local/bin/
+
+```
+
+CYA as been installed. Now let us go ahead and create snapshots.
+
+### Creating Snapshots
+
+Before creating any snapshots/backups, create a recovery script using command:
+```
+$ cya script
+☀ Cover Your Ass(ets) v2.2 ☀
+
+ACTION ⯮ Generating Recovery Script
+
+Generating Linux recovery script ...
+Checking sudo permissions...
+Complete
+
+IMPORTANT: This script will ONLY mount / and /home. Thus if you are storing data on another mount point open the recovery.sh script and add the additional mount point command where necessary. This is also a best guess and should be tested before an emergency to verify it works as desired.
+
+
+‣ Disclaimer: CYA offers zero guarantees as improper usage can cause undesired results
+‣ Notice: Proper usage can correct unauthorized changes to system from attacks
+
+```
+
+Save the resulting **recovery.sh** file in your USB drive which we are going to use it later when restoring backups. This script will help you to setup a chrooted environment and mount drives when you rollback your system.
+
+Now, let us create snapshots.
+
+To create a standard rolling backup, run:
+```
+$ cya save
+
+```
+
+The above command will keep **three backups** before overwriting.
+
+**Sample output:**
+```
+☀ Cover Your Ass(ets) v2.2 ☀
+
+ACTION ⯮ Standard Backup
+
+Checking sudo permissions...
+[sudo] password for sk:
+We need to create /home/cya/points/1 ... done
+Backing up /bin/ ... complete
+Backing up /boot/ ... complete
+Backing up /etc/ ... complete
+.
+.
+.
+Backing up /lib/ ... complete
+Backing up /lib64/ ... complete
+Backing up /opt/ ... complete
+Backing up /root/ ... complete
+Backing up /sbin/ ... complete
+Backing up /snap/ ... complete
+Backing up /usr/ ... complete
+Backing up /initrd.img ... complete
+Backing up /initrd.img.old ... complete
+Backing up /vmlinuz ... complete
+Backing up /vmlinuz.old ... complete
+Write out date file ... complete
+Update rotation file ... complete
+
+‣ Disclaimer: CYA offers zero guarantees as improper usage can cause undesired results
+‣ Notice: Proper usage can correct unauthorized changes to system from attacks
+
+```
+
+You can view the contents of the newly created snapshot, under **/home/cya/points/** location.
+```
+$ ls /home/cya/points/1/
+bin cya-date initrd.img lib opt sbin usr vmlinuz
+boot etc initrd.img.old lib64 root snap var vmlinuz.old
+
+```
+
+To create a backup with a custom name that will not be overwritten, run:
+```
+$ cya keep name BACKUP_NAME
+
+```
+
+Replace **BACKUP_NAME** with your own name.
+
+To create a backup with a custom name that will overwrite, do:
+```
+$ cya keep name BACKUP_NAME overwrite
+
+```
+
+To create a backup and archive and compress it, run:
+```
+$ cya keep name BACKUP_NAME archive
+
+```
+
+This command will store the backups in **/home/cya/archives** location.
+
+By default, CYA will store its configuration in **/home/cya/** directory and the snapshots with a custom name will be stored in **/home/cya/points/BACKUP_NAME** location. You can, however, change these settings by editing the CYA configuration file stored at **/home/cya/cya.conf**.
+
+Like I already said, CYA will not backup user data by default. It will only backup the important system files. You can, however, include your own directories or files along with system files. Say for example, if you wanted to add the directory named **/home/sk/Downloads** directory in the backup, edit **/home/cya/cya.conf** file:
+```
+$ vi /home/cya/cya.conf
+
+```
+
+Define your directory data path that you wanted to include in the backup like below.
+```
+MYDATA_mybackup="/home/sk/Downloads/ /mnt/backup/sk/"
+
+```
+
+Please be mindful that both source and destination directories should end with a trailing slash. As per the above configuration, CYA will copy all the contents of **/home/sk/Downloads/** directory and save them in **/mnt/backup/sk/** (assuming you already created this) directory. Here **mybackup** is the profile name. Save and close the file.
+
+Now to backup the contents of /home/sk/Downloads/ directory, you need to enter the profile name (i.e mybackup in my case) with the **cya mydata** command like below:
+```
+$ cya mydata mybackup
+
+```
+
+Similarly, you can include multiple user data with a different profile names. All profile names must be unique.
+
+### Exclude directories
+
+Some times, you may not want to backup all system files. You might want to exclude some unimportant such as log files. For example, if you don’t want to include **/var/tmp/** and **/var/logs/** directories, add the following in **/home/cya/cya.conf** file.
+```
+EXCLUDE_/var/=”tmp/ logs/”
+
+```
+
+Similarly, you can specify all directories one by one that you want to exclude from the backup. Once done, save and close the file.
+
+### Add specific files to the backup
+
+Instead of backing up whole directories, you can include a specific files from a directory. To do so, add the path of your files one by one in **/home/cya/cya.conf** file.
+```
+BACKUP_FILES="/home/sk/Downloads/ostechnix.txt"
+
+```
+
+### Restore your system
+
+Remember, we already create a recovery script named **recovery.sh** and saved it in an USB drive? Yeah, we will need it now to restore our broken system.
+
+Boot your system with any live bootable CD/DVD, USB drive. The developer of CYA recommends to use a live boot environment from same major version as your installed environment! For example if you use Ubuntu 18.04 system, then use Ubuntu 18.04 live media.
+
+Once you’re in the live system, mount the USB drive that contains the recovery.sh script. Once you mounted the drive(s), your system’s **/** and **/home** will be mounted to the **/mnt/cya** directory. This is made really easy and handled automatically by the **recovery.sh** script for Linux users.
+
+Then, start the restore process using command:
+```
+$ sudo /mnt/cya/home/cya/cya restore
+
+```
+
+Just follow the onscreen instructions. Once the restoration is done, remove the live media and unmount the drives and finally, reboot your system.
+
+What if you don’t have or lost recovery script? No problem, we still can restore our broken system.
+
+Boot the live media. From the live session, create a directory to mount the drive(s).
+```
+$ sudo mkdir -p /mnt/cya
+
+```
+
+Then, mount your **/** and **/home** (if on another partition) into the **/mnt/cya** directory.
+```
+$ sudo mount /dev/sda1 /mnt/cya
+
+$ sudo mount /dev/sda3 /mnt/cya/home
+
+```
+
+Replace /dev/sda1 and /dev/sda3 with your correct partitions (Use **fdisk -l** command to find your partitions).
+
+Finally, start the restoration process using command:
+```
+$ sudo /mnt/cya/home/cya/cya restore
+
+```
+
+Once the recovery is completed, unmount all mounted partitions and remove install media and reboot your system.
+
+At this stage, you might get a working system. I deleted some important libraries in Ubuntu 18.04 LTS server. I successfully restored it to the working state by using CYA utility.
+
+### Schedule CYA backup
+
+It is always recommended to use crontab to schedule the CYA snapshot process at regular interval. You can setup a cron job using root or setup a user that doesn’t need to enter a sudo password.
+
+The example entry below will run cya at every Monday at 2:05 am with output dumped into /dev/null.
+```
+5 2 * * 1 /home/USER/bin/cya save >/dev/null 2>&1
+
+```
+
+And, that’s all for now. Unlike Systemback and other system restore utilities, Cya is not a distribution-specific restore utility. It supports many Linux operating systems that uses BASH. It is one of the must-have applications in your arsenal. Install it right away and create snapshots. You won’t regret when you accidentally crashed your Linux system.
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/cya-system-snapshot-and-restore-utility-for-linux/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
diff --git a/sources/tech/20180724 75 Most Used Essential Linux Applications of 2018.md b/sources/tech/20180724 75 Most Used Essential Linux Applications of 2018.md
new file mode 100644
index 0000000000..919182ba1f
--- /dev/null
+++ b/sources/tech/20180724 75 Most Used Essential Linux Applications of 2018.md
@@ -0,0 +1,988 @@
+75 Most Used Essential Linux Applications of 2018
+======
+
+**2018** has been an awesome year for a lot of applications, especially those that are both free and open source. And while various Linux distributions come with a number of default apps, users are free to take them out and use any of the free or paid alternatives of their choice.
+
+Today, we bring you a [list of Linux applications][3] that have been able to make it to users’ Linux installations almost all the time despite the butt-load of other alternatives.
+
+To simply put, any app on this list is among the most used in its category, and if you haven’t already tried it out you are probably missing out. Enjoy!
+
+### Backup Tools
+
+#### Rsync
+
+[Rsync][4] is an open source bandwidth-friendly utility tool for performing swift incremental file transfers and it is available for free.
+```
+$ rsync [OPTION...] SRC... [DEST]
+
+```
+
+To know more examples and usage, read our article “[10 Practical Examples of Rsync Command][5]” to learn more about it.
+
+#### Timeshift
+
+[Timeshift][6] provides users with the ability to protect their system by taking incremental snapshots which can be reverted to at a different date – similar to the function of Time Machine in Mac OS and System restore in Windows.
+
+
+
+### BitTorrent Client
+
+
+
+#### Deluge
+
+[Deluge][7] is a beautiful cross-platform BitTorrent client that aims to perfect the **μTorrent** experience and make it available to users for free.
+
+Install **Deluge** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:deluge-team/ppa
+$ sudo apt-get update
+$ sudo apt-get install deluge
+
+```
+
+#### qBittorent
+
+[qBittorent][8] is an open source BitTorrent protocol client that aims to provide a free alternative to torrent apps like μTorrent.
+
+Install **qBittorent** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:qbittorrent-team/qbittorrent-stable
+$ sudo apt-get update
+$ sudo apt-get install qbittorrent
+
+```
+
+#### Transmission
+
+[Transmission][9] is also a BitTorrent client with awesome functionalities and a major focus on speed and ease of use. It comes preinstalled with many Linux distros.
+
+Install **Transmission** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:transmissionbt/ppa
+$ sudo apt-get update
+$ sudo apt-get install transmission-gtk transmission-cli transmission-common transmission-daemon
+
+```
+
+### Cloud Storage
+
+
+
+#### Dropbox
+
+The [Dropbox][10] team rebranded their cloud service earlier this year to provide an even better performance and app integration for their clients. It starts with 2GB of storage for free.
+
+Install **Dropbox** on **Ubuntu** and **Debian** , using following commands.
+```
+$ cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86" | tar xzf - [On 32-Bit]
+$ cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf - [On 64-Bit]
+$ ~/.dropbox-dist/dropboxd
+
+```
+
+#### Google Drive
+
+[Google Drive][11] is Google’s cloud service solution and my guess is that it needs no introduction. Just like with **Dropbox** , you can sync files across all your connected devices. It starts with 15GB of storage for free and this includes Gmail, Google photos, Maps, etc.
+
+Check out: [5 Google Drive Clients for Linux][12]
+
+#### Mega
+
+[Mega][13] stands out from the rest because apart from being extremely security-conscious, it gives free users 50GB to do as they wish! Its end-to-end encryption ensures that they can’t access your data, and if you forget your recovery key, you too wouldn’t be able to.
+
+[**Download MEGA Cloud Storage for Ubuntu][14]
+
+### Commandline Editors
+
+
+
+#### Vim
+
+[Vim][15] is an open source clone of vi text editor developed to be customizable and able to work with any type of text.
+
+Install **Vim** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:jonathonf/vim
+$ sudo apt update
+$ sudo apt install vim
+
+```
+
+#### Emacs
+
+[Emacs][16] refers to a set of highly configurable text editors. The most popular variant, GNU Emacs, is written in Lisp and C to be self-documenting, extensible, and customizable.
+
+Install **Emacs** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:kelleyk/emacs
+$ sudo apt update
+$ sudo apt install emacs25
+
+```
+
+#### Nano
+
+[Nano][17] is a feature-rich CLI text editor for power users and it has the ability to work with different terminals, among other functionalities.
+
+Install **Nano** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:n-muench/programs-ppa
+$ sudo apt-get update
+$ sudo apt-get install nano
+
+```
+
+### Download Manager
+
+
+
+#### Aria2
+
+[Aria2][18] is an open source lightweight multi-source and multi-protocol command line-based downloader with support for Metalinks, torrents, HTTP/HTTPS, SFTP, etc.
+
+Install **Aria2** on **Ubuntu** and **Debian** , using following command.
+```
+$ sudo apt-get install aria2
+
+```
+
+#### uGet
+
+[uGet][19] has earned its title as the **#1** open source download manager for Linux distros and it features the ability to handle any downloading task you can throw at it including using multiple connections, using queues, categories, etc.
+
+Install **uGet** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:plushuang-tw/uget-stable
+$ sudo apt update
+$ sudo apt install uget
+
+```
+
+#### XDM
+
+[XDM][20], **Xtreme Download Manager** is an open source downloader written in Java. Like any good download manager, it can work with queues, torrents, browsers, and it also includes a video grabber and a smart scheduler.
+
+Install **XDM** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:noobslab/apps
+$ sudo apt-get update
+$ sudo apt-get install xdman
+
+```
+
+### Email Clients
+
+
+
+#### Thunderbird
+
+[Thunderbird][21] is among the most popular email applications. It is free, open source, customizable, feature-rich, and above all, easy to install.
+
+Install **Thunderbird** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:ubuntu-mozilla-security/ppa
+$ sudo apt-get update
+$ sudo apt-get install thunderbird
+
+```
+
+#### Geary
+
+[Geary][22] is an open source email client based on WebKitGTK+. It is free, open-source, feature-rich, and adopted by the GNOME project.
+
+Install **Geary** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:geary-team/releases
+$ sudo apt-get update
+$ sudo apt-get install geary
+
+```
+
+#### Evolution
+
+[Evolution][23] is a free and open source email client for managing emails, meeting schedules, reminders, and contacts.
+
+Install **Evolution** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:gnome3-team/gnome3-staging
+$ sudo apt-get update
+$ sudo apt-get install evolution
+
+```
+
+### Finance Software
+
+
+
+#### GnuCash
+
+[GnuCash][24] is a free, cross-platform, and open source software for financial accounting tasks for personal and small to mid-size businesses.
+
+Install **GnuCash** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo sh -c 'echo "deb http://archive.getdeb.net/ubuntu $(lsb_release -sc)-getdeb apps" >> /etc/apt/sources.list.d/getdeb.list'
+$ sudo apt-get update
+$ sudo apt-get install gnucash
+
+```
+
+#### KMyMoney
+
+[KMyMoney][25] is a finance manager software that provides all important features found in the commercially-available, personal finance managers.
+
+Install **KMyMoney** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:claydoh/kmymoney2-kde4
+$ sudo apt-get update
+$ sudo apt-get install kmymoney
+
+```
+
+### IDE Editors
+
+
+
+#### Eclipse IDE
+
+[Eclipse][26] is the most widely used Java IDE containing a base workspace and an impossible-to-overemphasize configurable plug-in system for personalizing its coding environment.
+
+For installation, read our article “[How to Install Eclipse Oxygen IDE in Debian and Ubuntu][27]”
+
+#### Netbeans IDE
+
+A fan-favourite, [Netbeans][28] enables users to easily build applications for mobile, desktop, and web platforms using Java, PHP, HTML5, JavaScript, and C/C++, among other languages.
+
+For installation, read our article “[How to Install Netbeans Oxygen IDE in Debian and Ubuntu][29]”
+
+#### Brackets
+
+[Brackets][30] is an advanced text editor developed by Adobe to feature visual tools, preprocessor support, and a design-focused user flow for web development. In the hands of an expert, it can serve as an IDE in its own right.
+
+Install **Brackets** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:webupd8team/brackets
+$ sudo apt-get update
+$ sudo apt-get install brackets
+
+```
+
+#### Atom IDE
+
+[Atom IDE][31] is a more robust version of Atom text editor achieved by adding a number of extensions and libraries to boost its performance and functionalities. It is, in a sense, Atom on steroids.
+
+Install **Atom** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install snapd
+$ sudo snap install atom --classic
+
+```
+
+#### Light Table
+
+[Light Table][32] is a self-proclaimed next-generation IDE developed to offer awesome features like data value flow stats and coding collaboration.
+
+Install **Light Table** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:dr-akulavich/lighttable
+$ sudo apt-get update
+$ sudo apt-get install lighttable-installer
+
+```
+
+#### Visual Studio Code
+
+[Visual Studio Code][33] is a source code editor created by Microsoft to offer users the best-advanced features in a text editor including syntax highlighting, code completion, debugging, performance statistics and graphs, etc.
+
+[**Download Visual Studio Code for Ubuntu][34]
+
+### Instant Messaging
+
+
+
+#### Pidgin
+
+[Pidgin][35] is an open source instant messaging app that supports virtually all chatting platforms and can have its abilities extended using extensions.
+
+Install **Pidgin** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:jonathonf/backports
+$ sudo apt-get update
+$ sudo apt-get install pidgin
+
+```
+
+#### Skype
+
+[Skype][36] needs no introduction and its awesomeness is available for any interested Linux user.
+
+Install **Skype** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt install snapd
+$ sudo snap install skype --classic
+
+```
+
+#### Empathy
+
+[Empathy][37] is a messaging app with support for voice, video chat, text, and file transfers over multiple several protocols. It also allows you to add other service accounts to it and interface with all of them through it.
+
+Install **Empathy** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install empathy
+
+```
+
+### Linux Antivirus
+
+#### ClamAV/ClamTk
+
+[ClamAV][38] is an open source and cross-platform command line antivirus app for detecting Trojans, viruses, and other malicious codes. [ClamTk][39] is its GUI front-end.
+
+Install **ClamAV/ClamTk** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install clamav
+$ sudo apt-get install clamtk
+
+```
+
+### Linux Desktop Environments
+
+#### Cinnamon
+
+[Cinnamon][40] is a free and open-source derivative of **GNOME3** and it follows the traditional desktop metaphor conventions.
+
+Install **Cinnamon** desktop on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:embrosyn/cinnamon
+$ sudo apt update
+$ sudo apt install cinnamon-desktop-environment lightdm
+
+```
+
+#### Mate
+
+The [Mate][41] Desktop Environment is a derivative and continuation of **GNOME2** developed to offer an attractive UI on Linux using traditional metaphors.
+
+Install **Mate** desktop on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt install tasksel
+$ sudo apt update
+$ sudo tasksel install ubuntu-mate-desktop
+
+```
+
+#### GNOME
+
+[GNOME][42] is a Desktop Environment comprised of several free and open-source applications and can run on any Linux distro and on most BSD derivatives.
+
+Install **Gnome** desktop on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt install tasksel
+$ sudo apt update
+$ sudo tasksel install ubuntu-desktop
+
+```
+
+#### KDE
+
+[KDE][43] is developed by the KDE community to provide users with a graphical solution to interfacing with their system and performing several computing tasks.
+
+Install **KDE** desktop on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt install tasksel
+$ sudo apt update
+$ sudo tasksel install kubuntu-desktop
+
+```
+
+### Linux Maintenance Tools
+
+#### GNOME Tweak Tool
+
+The [GNOME Tweak Tool][44] is the most popular tool for customizing and tweaking GNOME3 and GNOME Shell settings.
+
+Install **GNOME Tweak Tool** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt install gnome-tweak-tool
+
+```
+
+#### Stacer
+
+[Stacer][45] is a free, open-source app for monitoring and optimizing Linux systems.
+
+Install **Stacer** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:oguzhaninan/stacer
+$ sudo apt-get update
+$ sudo apt-get install stacer
+
+```
+
+#### BleachBit
+
+[BleachBit][46] is a free disk space cleaner that also works as a privacy manager and system optimizer.
+
+[**Download BleachBit for Ubuntu][47]
+
+### Linux Terminals
+
+#### GNOME Terminal
+
+[GNOME Terminal][48] is GNOME’s default terminal emulator.
+
+Install **Gnome Terminal** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install gnome-terminal
+
+```
+
+#### Konsole
+
+[Konsole][49] is a terminal emulator for KDE.
+
+Install **Konsole** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install konsole
+
+```
+
+#### Terminator
+
+[Terminator][50] is a feature-rich GNOME Terminal-based terminal app built with a focus on arranging terminals, among other functions.
+
+Install **Terminator** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install terminator
+
+```
+
+#### Guake
+
+[Guake][51] is a lightweight drop-down terminal for the GNOME Desktop Environment.
+
+Install **Guake** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install guake
+
+```
+
+### Multimedia Editors
+
+#### Ardour
+
+[Ardour][52] is a beautiful Digital Audio Workstation (DAW) for recording, editing, and mixing audio professionally.
+
+Install **Ardour** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:dobey/audiotools
+$ sudo apt-get update
+$ sudo apt-get install ardour
+
+```
+
+#### Audacity
+
+[Audacity][53] is an easy-to-use cross-platform and open source multi-track audio editor and recorder; arguably the most famous of them all.
+
+Install **Audacity** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:ubuntuhandbook1/audacity
+$ sudo apt-get update
+$ sudo apt-get install audacity
+
+```
+
+#### GIMP
+
+[GIMP][54] is the most popular open source Photoshop alternative and it is for a reason. It features various customization options, 3rd-party plugins, and a helpful user community.
+
+Install **Gimp** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:otto-kesselgulasch/gimp
+$ sudo apt update
+$ sudo apt install gimp
+
+```
+
+#### Krita
+
+[Krita][55] is an open source painting app that can also serve as an image manipulating tool and it features a beautiful UI with a reliable performance.
+
+Install **Krita** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:kritalime/ppa
+$ sudo apt update
+$ sudo apt install krita
+
+```
+
+#### Lightworks
+
+[Lightworks][56] is a powerful, flexible, and beautiful tool for editing videos professionally. It comes feature-packed with hundreds of amazing effects and presets that allow it to handle any editing task that you throw at it and it has 25 years of experience to back up its claims.
+
+[**Download Lightworks for Ubuntu][57]
+
+#### OpenShot
+
+[OpenShot][58] is an award-winning free and open source video editor known for its excellent performance and powerful capabilities.
+
+Install **Openshot** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:openshot.developers/ppa
+$ sudo apt update
+$ sudo apt install openshot-qt
+
+```
+
+#### PiTiV
+
+[Pitivi][59] is a beautiful video editor that features a beautiful code base, awesome community, is easy to use, and allows for hassle-free collaboration.
+
+Install **PiTiV** on **Ubuntu** and **Debian** , using following commands.
+```
+$ flatpak install --user https://flathub.org/repo/appstream/org.pitivi.Pitivi.flatpakref
+$ flatpak install --user http://flatpak.pitivi.org/pitivi.flatpakref
+$ flatpak run org.pitivi.Pitivi//stable
+
+```
+
+### Music Players
+
+#### Rhythmbox
+
+[Rhythmbox][60] posses the ability to perform all music tasks you throw at it and has so far proved to be a reliable music player that it ships with Ubuntu.
+
+Install **Rhythmbox** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:fossfreedom/rhythmbox
+$ sudo apt-get update
+$ sudo apt-get install rhythmbox
+
+```
+
+#### Lollypop
+
+[Lollypop][61] is a beautiful, relatively new, open source music player featuring a number of advanced options like online radio, scrubbing support and party mode. Yet, it manages to keep everything simple and easy to manage.
+
+Install **Lollypop** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:gnumdk/lollypop
+$ sudo apt-get update
+$ sudo apt-get install lollypop
+
+```
+
+#### Amarok
+
+[Amarok][62] is a robust music player with an intuitive UI and tons of advanced features bundled into a single unit. It also allows users to discover new music based on their genre preferences.
+
+Install **Amarok** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get update
+$ sudo apt-get install amarok
+
+```
+
+#### Clementine
+
+[Clementine][63] is an Amarok-inspired music player that also features a straight-forward UI, advanced control features, and the ability to let users search for and discover new music.
+
+Install **Clementine** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:me-davidsansome/clementine
+$ sudo apt-get update
+$ sudo apt-get install clementine
+
+```
+
+#### Cmus
+
+[Cmus][64] is arguably the most efficient CLI music player, Cmus is fast and reliable, and its functionality can be increased using extensions.
+
+Install **Cmus** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:jmuc/cmus
+$ sudo apt-get update
+$ sudo apt-get install cmus
+
+```
+
+### Office Suites
+
+#### Calligra Suite
+
+The [Calligra Suite][65] provides users with a set of 8 applications which cover working with office, management, and graphics tasks.
+
+Install **Calligra Suite** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install calligra
+
+```
+
+#### LibreOffice
+
+[LibreOffice][66] the most actively developed office suite in the open source community, LibreOffice is known for its reliability and its functions can be increased using extensions.
+
+Install **LibreOffice** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:libreoffice/ppa
+$ sudo apt update
+$ sudo apt install libreoffice
+
+```
+
+#### WPS Office
+
+[WPS Office][67] is a beautiful office suite alternative with a more modern UI.
+
+[**Download WPS Office for Ubuntu][68]
+
+### Screenshot Tools
+
+#### Shutter
+
+[Shutter][69] allows users to take screenshots of their desktop and then edit them using filters and other effects coupled with the option to upload and share them online.
+
+Install **Shutter** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository -y ppa:shutter/ppa
+$ sudo apt update
+$ sudo apt install shutter
+
+```
+
+#### Kazam
+
+[Kazam][70] screencaster captures screen content to output a video and audio file supported by any video player with VP8/WebM and PulseAudio support.
+
+Install **Kazam** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:kazam-team/unstable-series
+$ sudo apt update
+$ sudo apt install kazam python3-cairo python3-xlib
+
+```
+
+#### Gnome Screenshot
+
+[Gnome Screenshot][71] was once bundled with Gnome utilities but is now a standalone app. It can be used to take screencasts in a format that is easily shareable.
+
+Install **Gnome Screenshot** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get update
+$ sudo apt-get install gnome-screenshot
+
+```
+
+### Screen Recorders
+
+#### SimpleScreenRecorder
+
+[SimpleScreenRecorder][72] was created to be better than the screen-recording apps available at the time of its creation and has now turned into one of the most efficient and easy-to-use screen recorders for Linux distros.
+
+Install **SimpleScreenRecorder** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:maarten-baert/simplescreenrecorder
+$ sudo apt-get update
+$ sudo apt-get install simplescreenrecorder
+
+```
+
+#### recordMyDesktop
+
+[recordMyDesktop][73] is an open source session recorder that is also capable of recording desktop session audio.
+
+Install **recordMyDesktop** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get update
+$ sudo apt-get install gtk-recordmydesktop
+
+```
+
+### Text Editors
+
+#### Atom
+
+[Atom][74] is a modern and customizable text editor created and maintained by GitHub. It is ready for use right out of the box and can have its functionality enhanced and its UI customized using extensions and themes.
+
+Install **Atom** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install snapd
+$ sudo snap install atom --classic
+
+```
+
+#### Sublime Text
+
+[Sublime Text][75] is easily among the most awesome text editors to date. It is customizable, lightweight (even when bulldozed with a lot of data files and extensions), flexible, and remains free to use forever.
+
+Install **Sublime Text** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install snapd
+$ sudo snap install sublime-text
+
+```
+
+#### Geany
+
+[Geany][76] is a memory-friendly text editor with basic IDE features designed to exhibit shot load times and extensible functions using libraries.
+
+Install **Geany** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get update
+$ sudo apt-get install geany
+
+```
+
+#### Gedit
+
+[Gedit][77] is famous for its simplicity and it comes preinstalled with many Linux distros because of its function as an excellent general purpose text editor.
+
+Install **Gedit** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get update
+$ sudo apt-get install gedit
+
+```
+
+### To-Do List Apps
+
+#### Evernote
+
+[Evernote][78] is a cloud-based note-taking productivity app designed to work perfectly with different types of notes including to-do lists and reminders.
+
+There is no any official evernote app for Linux, so check out other third party [6 Evernote Alternative Clients for Linux][79].
+
+#### Everdo
+
+[Everdo][78] is a beautiful, security-conscious, low-friction Getting-Things-Done app productivity app for handling to-dos and other note types. If Evernote comes off to you in an unpleasant way, Everdo is a perfect alternative.
+
+[**Download Everdo for Ubuntu][80]
+
+#### Taskwarrior
+
+[Taskwarrior][81] is an open source and cross-platform command line app for managing tasks. It is famous for its speed and distraction-free environment.
+
+Install **Taskwarrior** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get update
+$ sudo apt-get install taskwarrior
+
+```
+
+### Video Players
+
+#### Banshee
+
+[Banshee][82] is an open source multi-format-supporting media player that was first developed in 2005 and has only been getting better since.
+
+Install **Banshee** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:banshee-team/ppa
+$ sudo apt-get update
+$ sudo apt-get install banshee
+
+```
+
+#### VLC
+
+[VLC][83] is my favourite video player and it’s so awesome that it can play almost any audio and video format you throw at it. You can also use it to play internet radio, record desktop sessions, and stream movies online.
+
+Install **VLC** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:videolan/stable-daily
+$ sudo apt-get update
+$ sudo apt-get install vlc
+
+```
+
+#### Kodi
+
+[Kodi][84] is among the world’s most famous media players and it comes as a full-fledged media centre app for playing all things media whether locally or remotely.
+
+Install **Kodi** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo apt-get install software-properties-common
+$ sudo add-apt-repository ppa:team-xbmc/ppa
+$ sudo apt-get update
+$ sudo apt-get install kodi
+
+```
+
+#### SMPlayer
+
+[SMPlayer][85] is a GUI for the award-winning **MPlayer** and it is capable of handling all popular media formats; coupled with the ability to stream from YouTube, Chromcast, and download subtitles.
+
+Install **SMPlayer** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:rvm/smplayer
+$ sudo apt-get update
+$ sudo apt-get install smplayer
+
+```
+
+### Virtualization Tools
+
+#### VirtualBox
+
+[VirtualBox][86] is an open source app created for general-purpose OS virtualization and it can be run on servers, desktops, and embedded systems.
+
+Install **VirtualBox** on **Ubuntu** and **Debian** , using following commands.
+```
+$ wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add -
+$ wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add -
+$ sudo apt-get update
+$ sudo apt-get install virtualbox-5.2
+$ virtualbox
+
+```
+
+#### VMWare
+
+[VMware][87] is a digital workspace that provides platform virtualization and cloud computing services to customers and is reportedly the first to successfully virtualize x86 architecture systems. One of its products, VMware workstations allows users to run multiple OSes in a virtual memory.
+
+For installation, read our article “[How to Install VMware Workstation Pro on Ubuntu][88]“.
+
+### Web Browsers
+
+#### Chrome
+
+[Google Chrome][89] is undoubtedly the most popular browser. Known for its speed, simplicity, security, and beauty following Google’s Material Design trend, Chrome is a browser that web developers cannot do without. It is also free to use and open source.
+
+Install **Google Chrome** on **Ubuntu** and **Debian** , using following commands.
+```
+$ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
+$ sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
+$ sudo apt-get update
+$ sudo apt-get install google-chrome-stable
+
+```
+
+#### Firefox
+
+[Firefox Quantum][90] is a beautiful, speed, task-ready, and customizable browser capable of any browsing task that you throw at it. It is also free, open source, and packed with developer-friendly tools that are easy for even beginners to get up and running with.
+
+Install **Firefox Quantum** on **Ubuntu** and **Debian** , using following commands.
+```
+$ sudo add-apt-repository ppa:mozillateam/firefox-next
+$ sudo apt update && sudo apt upgrade
+$ sudo apt install firefox
+
+```
+
+#### Vivaldi
+
+[Vivaldi][91] is a free and open source Chrome-based project that aims to perfect Chrome’s features with a couple of more feature additions. It is known for its colourful panels, memory-friendly performance, and flexibility.
+
+[**Download Vivaldi for Ubuntu][91]
+
+That concludes our list for today. Did I skip a famous title? Tell me about it in the comments section below.
+
+Don’t forget to share this post and to subscribe to our newsletter to get the latest publications from FossMint.
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.fossmint.com/most-used-linux-applications/
+
+作者:[Martins D. Okoi][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://www.fossmint.com/author/dillivine/
+[1]:https://plus.google.com/share?url=https://www.fossmint.com/most-used-linux-applications/ (Share on Google+)
+[2]:https://www.linkedin.com/shareArticle?mini=true&url=https://www.fossmint.com/most-used-linux-applications/ (Share on LinkedIn)
+[3]:https://www.fossmint.com/awesome-linux-software/
+[4]:https://rsync.samba.org/
+[5]:https://www.tecmint.com/rsync-local-remote-file-synchronization-commands/
+[6]:https://github.com/teejee2008/timeshift
+[7]:https://deluge-torrent.org/
+[8]:https://www.qbittorrent.org/
+[9]:https://transmissionbt.com/
+[10]:https://www.dropbox.com/
+[11]:https://www.google.com/drive/
+[12]:https://www.fossmint.com/best-google-drive-clients-for-linux/
+[13]:https://mega.nz/
+[14]:https://mega.nz/sync!linux
+[15]:https://www.vim.org/
+[16]:https://www.gnu.org/s/emacs/
+[17]:https://www.nano-editor.org/
+[18]:https://aria2.github.io/
+[19]:http://ugetdm.com/
+[20]:http://xdman.sourceforge.net/
+[21]:https://www.thunderbird.net/
+[22]:https://github.com/GNOME/geary
+[23]:https://github.com/GNOME/evolution
+[24]:https://www.gnucash.org/
+[25]:https://kmymoney.org/
+[26]:https://www.eclipse.org/ide/
+[27]:https://www.tecmint.com/install-eclipse-oxygen-ide-in-ubuntu-debian/
+[28]:https://netbeans.org/
+[29]:https://www.tecmint.com/install-netbeans-ide-in-ubuntu-debian-linux-mint/
+[30]:http://brackets.io/
+[31]:https://ide.atom.io/
+[32]:http://lighttable.com/
+[33]:https://code.visualstudio.com/
+[34]:https://code.visualstudio.com/download
+[35]:https://www.pidgin.im/
+[36]:https://www.skype.com/
+[37]:https://wiki.gnome.org/Apps/Empathy
+[38]:https://www.clamav.net/
+[39]:https://dave-theunsub.github.io/clamtk/
+[40]:https://github.com/linuxmint/cinnamon-desktop
+[41]:https://mate-desktop.org/
+[42]:https://www.gnome.org/
+[43]:https://www.kde.org/plasma-desktop
+[44]:https://github.com/nzjrs/gnome-tweak-tool
+[45]:https://github.com/oguzhaninan/Stacer
+[46]:https://www.bleachbit.org/
+[47]:https://www.bleachbit.org/download
+[48]:https://github.com/GNOME/gnome-terminal
+[49]:https://konsole.kde.org/
+[50]:https://gnometerminator.blogspot.com/p/introduction.html
+[51]:http://guake-project.org/
+[52]:https://ardour.org/
+[53]:https://www.audacityteam.org/
+[54]:https://www.gimp.org/
+[55]:https://krita.org/en/
+[56]:https://www.lwks.com/
+[57]:https://www.lwks.com/index.php?option=com_lwks&view=download&Itemid=206
+[58]:https://www.openshot.org/
+[59]:http://www.pitivi.org/
+[60]:https://wiki.gnome.org/Apps/Rhythmbox
+[61]:https://gnumdk.github.io/lollypop-web/
+[62]:https://amarok.kde.org/en
+[63]:https://www.clementine-player.org/
+[64]:https://cmus.github.io/
+[65]:https://www.calligra.org/tour/calligra-suite/
+[66]:https://www.libreoffice.org/
+[67]:https://www.wps.com/
+[68]:http://wps-community.org/downloads
+[69]:http://shutter-project.org/
+[70]:https://launchpad.net/kazam
+[71]:https://gitlab.gnome.org/GNOME/gnome-screenshot
+[72]:http://www.maartenbaert.be/simplescreenrecorder/
+[73]:http://recordmydesktop.sourceforge.net/about.php
+[74]:https://atom.io/
+[75]:https://www.sublimetext.com/
+[76]:https://www.geany.org/
+[77]:https://wiki.gnome.org/Apps/Gedit
+[78]:https://everdo.net/
+[79]:https://www.fossmint.com/evernote-alternatives-for-linux/
+[80]:https://everdo.net/linux/
+[81]:https://taskwarrior.org/
+[82]:http://banshee.fm/
+[83]:https://www.videolan.org/
+[84]:https://kodi.tv/
+[85]:https://www.smplayer.info/
+[86]:https://www.virtualbox.org/wiki/VirtualBox
+[87]:https://www.vmware.com/
+[88]:https://www.tecmint.com/install-vmware-workstation-in-linux/
+[89]:https://www.google.com/chrome/
+[90]:https://www.mozilla.org/en-US/firefox/
+[91]:https://vivaldi.com/
diff --git a/sources/tech/20180724 Building a network attached storage device with a Raspberry Pi.md b/sources/tech/20180724 Building a network attached storage device with a Raspberry Pi.md
new file mode 100644
index 0000000000..3144efd4ee
--- /dev/null
+++ b/sources/tech/20180724 Building a network attached storage device with a Raspberry Pi.md
@@ -0,0 +1,284 @@
+Building a network attached storage device with a Raspberry Pi
+======
+
+
+
+In this three-part series, I'll explain how to set up a simple, useful NAS (network attached storage) system. I use this kind of setup to store my files on a central system, creating incremental backups automatically every night. To mount the disk on devices that are located in the same network, NFS is installed. To access files offline and share them with friends, I use [Nextcloud][1].
+
+This article will cover the basic setup of software and hardware to mount the data disk on a remote device. In the second article, I will discuss a backup strategy and set up a cron job to create daily backups. In the third and last article, we will install Nextcloud, a tool for easy file access to devices synced offline as well as online using a web interface. It supports multiple users and public file-sharing so you can share pictures with friends, for example, by sending a password-protected link.
+
+The target architecture of our system looks like this:
+
+
+### Hardware
+
+Let's get started with the hardware you need. You might come up with a different shopping list, so consider this one an example.
+
+The computing power is delivered by a [Raspberry Pi 3][2], which comes with a quad-core CPU, a gigabyte of RAM, and (somewhat) fast ethernet. Data will be stored on two USB hard drives (I use 1-TB disks); one is used for the everyday traffic, the other is used to store backups. Be sure to use either active USB hard drives or a USB hub with an additional power supply, as the Raspberry Pi will not be able to power two USB drives.
+
+### Software
+
+The operating system with the highest visibility in the community is [Raspbian][3] , which is excellent for custom projects. There are plenty of [guides][4] that explain how to install Raspbian on a Raspberry Pi, so I won't go into details here. The latest official supported version at the time of this writing is [Raspbian Stretch][5] , which worked fine for me.
+
+At this point, I will assume you have configured your basic Raspbian and are able to connect to the Raspberry Pi by `ssh`.
+
+### Prepare the USB drives
+
+To achieve good performance reading from and writing to the USB hard drives, I recommend formatting them with ext4. To do so, you must first find out which disks are attached to the Raspberry Pi. You can find the disk devices in `/dev/sd/`. Using the command `fdisk -l`, you can find out which two USB drives you just attached. Please note that all data on the USB drives will be lost as soon as you follow these steps.
+```
+pi@raspberrypi:~ $ sudo fdisk -l
+
+
+
+<...>
+
+
+
+Disk /dev/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
+
+Units: sectors of 1 * 512 = 512 bytes
+
+Sector size (logical/physical): 512 bytes / 512 bytes
+
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+
+Disklabel type: dos
+
+Disk identifier: 0xe8900690
+
+
+
+Device Boot Start End Sectors Size Id Type
+
+/dev/sda1 2048 1953525167 1953523120 931.5G 83 Linux
+
+
+
+
+
+Disk /dev/sdb: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
+
+Units: sectors of 1 * 512 = 512 bytes
+
+Sector size (logical/physical): 512 bytes / 512 bytes
+
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+
+Disklabel type: dos
+
+Disk identifier: 0x6aa4f598
+
+
+
+Device Boot Start End Sectors Size Id Type
+
+/dev/sdb1 * 2048 1953521663 1953519616 931.5G 83 Linux
+
+```
+
+As those devices are the only 1TB disks attached to the Raspberry Pi, we can easily see that `/dev/sda` and `/dev/sdb` are the two USB drives. The partition table at the end of each disk shows how it should look after the following steps, which create the partition table and format the disks. To do this, repeat the following steps for each of the two devices by replacing `sda` with `sdb` the second time (assuming your devices are also listed as `/dev/sda` and `/dev/sdb` in `fdisk`).
+
+First, delete the partition table of the disk and create a new one containing only one partition. In `fdisk`, you can use interactive one-letter commands to tell the program what to do. Simply insert them after the prompt `Command (m for help):` as follows (you can also use the `m` command anytime to get more information):
+```
+pi@raspberrypi:~ $ sudo fdisk /dev/sda
+
+
+
+Welcome to fdisk (util-linux 2.29.2).
+
+Changes will remain in memory only, until you decide to write them.
+
+Be careful before using the write command.
+
+
+
+
+
+Command (m for help): o
+
+Created a new DOS disklabel with disk identifier 0x9c310964.
+
+
+
+Command (m for help): n
+
+Partition type
+
+ p primary (0 primary, 0 extended, 4 free)
+
+ e extended (container for logical partitions)
+
+Select (default p): p
+
+Partition number (1-4, default 1):
+
+First sector (2048-1953525167, default 2048):
+
+Last sector, +sectors or +size{K,M,G,T,P} (2048-1953525167, default 1953525167):
+
+
+
+Created a new partition 1 of type 'Linux' and of size 931.5 GiB.
+
+
+
+Command (m for help): p
+
+
+
+Disk /dev/sda: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
+
+Units: sectors of 1 * 512 = 512 bytes
+
+Sector size (logical/physical): 512 bytes / 512 bytes
+
+I/O size (minimum/optimal): 512 bytes / 512 bytes
+
+Disklabel type: dos
+
+Disk identifier: 0x9c310964
+
+
+
+Device Boot Start End Sectors Size Id Type
+
+/dev/sda1 2048 1953525167 1953523120 931.5G 83 Linux
+
+
+
+Command (m for help): w
+
+The partition table has been altered.
+
+Syncing disks.
+
+```
+
+Now we will format the newly created partition `/dev/sda1` using the ext4 filesystem:
+```
+pi@raspberrypi:~ $ sudo mkfs.ext4 /dev/sda1
+
+mke2fs 1.43.4 (31-Jan-2017)
+
+Discarding device blocks: done
+
+
+
+<...>
+
+
+
+Allocating group tables: done
+
+Writing inode tables: done
+
+Creating journal (1024 blocks): done
+
+Writing superblocks and filesystem accounting information: done
+
+```
+
+After repeating the above steps, let's label the new partitions according to their usage in your system:
+```
+pi@raspberrypi:~ $ sudo e2label /dev/sda1 data
+
+pi@raspberrypi:~ $ sudo e2label /dev/sdb1 backup
+
+```
+
+Now let's get those disks mounted to store some data. My experience, based on running this setup for over a year now, is that USB drives are not always available to get mounted when the Raspberry Pi boots up (for example, after a power outage), so I recommend using autofs to mount them when needed.
+
+First install autofs and create the mount point for the storage:
+```
+pi@raspberrypi:~ $ sudo apt install autofs
+
+pi@raspberrypi:~ $ sudo mkdir /nas
+
+```
+
+Then mount the devices by adding the following line to `/etc/auto.master`:
+```
+/nas /etc/auto.usb
+
+```
+
+Create the file `/etc/auto.usb` if not existing with the following content, and restart the autofs service:
+```
+data -fstype=ext4,rw :/dev/disk/by-label/data
+
+backup -fstype=ext4,rw :/dev/disk/by-label/backup
+
+pi@raspberrypi3:~ $ sudo service autofs restart
+
+```
+
+Now you should be able to access the disks at `/nas/data` and `/nas/backup`, respectively. Clearly, the content will not be too thrilling, as you just erased all the data from the disks. Nevertheless, you should be able to verify the devices are mounted by executing the following commands:
+```
+pi@raspberrypi3:~ $ cd /nas/data
+
+pi@raspberrypi3:/nas/data $ cd /nas/backup
+
+pi@raspberrypi3:/nas/backup $ mount
+
+<...>
+
+/etc/auto.usb on /nas type autofs (rw,relatime,fd=6,pgrp=463,timeout=300,minproto=5,maxproto=5,indirect)
+
+<...>
+
+/dev/sda1 on /nas/data type ext4 (rw,relatime,data=ordered)
+
+/dev/sdb1 on /nas/backup type ext4 (rw,relatime,data=ordered)
+
+```
+
+First move into the directories to make sure autofs mounts the devices. Autofs tracks access to the filesystems and mounts the needed devices on the go. Then the `mount` command shows that the two devices are actually mounted where we wanted them.
+
+Setting up autofs is a bit fault-prone, so do not get frustrated if mounting doesn't work on the first try. Give it another chance, search for more detailed resources (there is plenty of documentation online), or leave a comment.
+
+### Mount network storage
+
+Now that you have set up the basic network storage, we want it to be mounted on a remote Linux machine. We will use the network file system (NFS) for this. First, install the NFS server on the Raspberry Pi:
+```
+pi@raspberrypi:~ $ sudo apt install nfs-kernel-server
+
+```
+
+Next we need to tell the NFS server to expose the `/nas/data` directory, which will be the only device accessible from outside the Raspberry Pi (the other one will be used for backups only). To export the directory, edit the file `/etc/exports` and add the following line to allow all devices with access to the NAS to mount your storage:
+```
+/nas/data *(rw,sync,no_subtree_check)
+
+```
+
+For more information about restricting the mount to single devices and so on, refer to `man exports`. In the configuration above, anyone will be able to mount your data as long as they have access to the ports needed by NFS: `111` and `2049`. I use the configuration above and allow access to my home network only for ports 22 and 443 using the routers firewall. That way, only devices in the home network can reach the NFS server.
+
+To mount the storage on a Linux computer, run the commands:
+```
+you@desktop:~ $ sudo mkdir /nas/data
+
+you@desktop:~ $ sudo mount -t nfs :/nas/data /nas/data
+
+```
+
+Again, I recommend using autofs to mount this network device. For extra help, check out [How to use autofs to mount NFS shares][6].
+
+Now you are able to access files stored on your own RaspberryPi-powered NAS from remote devices using the NFS mount. In the next part of this series, I will cover how to automatically back up your data to the second hard drive using `rsync`. To save space on the device while still doing daily backups, you will learn how to create incremental backups with `rsync`.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/network-attached-storage-Raspberry-Pi
+
+作者:[Manuel Dewald][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/ntlx
+[1]:https://nextcloud.com/
+[2]:https://www.raspberrypi.org/products/raspberry-pi-3-model-b/
+[3]:https://www.raspbian.org/
+[4]:https://www.raspberrypi.org/documentation/installation/installing-images/
+[5]:https://www.raspberrypi.org/blog/raspbian-stretch/
+[6]:https://opensource.com/article/18/6/using-autofs-mount-nfs-shares
diff --git a/sources/tech/20180724 How To Mount Google Drive Locally As Virtual File System In Linux.md b/sources/tech/20180724 How To Mount Google Drive Locally As Virtual File System In Linux.md
new file mode 100644
index 0000000000..3f804ffe9e
--- /dev/null
+++ b/sources/tech/20180724 How To Mount Google Drive Locally As Virtual File System In Linux.md
@@ -0,0 +1,265 @@
+How To Mount Google Drive Locally As Virtual File System In Linux
+======
+
+
+
+[**Google Drive**][1] is the one of the popular cloud storage provider on the planet. As of 2017, over 800 million users are actively using this service worldwide. Even though the number of users have dramatically increased, Google haven’t released a Google drive client for Linux yet. But it didn’t stop the Linux community. Every now and then, some developers had brought few google drive clients for Linux operating system. In this guide, we will see three unofficial google drive clients for Linux. Using these clients, you can mount Google drive locally as a virtual file system and access your drive files in your Linux box. Read on.
+
+### 1. Google-drive-ocamlfuse
+
+The **google-drive-ocamlfuse** is a FUSE filesystem for Google Drive, written in OCaml. For those wondering, FUSE, stands for **F** ilesystem in **Use** rspace, is a project that allows the users to create virtual file systems in user level. **google-drive-ocamlfuse** allows you to mount your Google Drive on Linux system. It features read/write access to ordinary files and folders, read-only access to Google docks, sheets, and slides, support for multiple google drive accounts, duplicate file handling, access to your drive trash directory, and more.
+
+#### Installing google-drive-ocamlfuse
+
+google-drive-ocamlfuse is available in the [**AUR**][2], so you can install it using any AUR helper programs, for example [**Yay**][3].
+```
+$ yay -S google-drive-ocamlfuse
+
+```
+
+On Ubuntu:
+```
+$ sudo add-apt-repository ppa:alessandro-strada/ppa
+$ sudo apt-get update
+$ sudo apt-get install google-drive-ocamlfuse
+
+```
+
+To install latest beta version, do:
+```
+$ sudo add-apt-repository ppa:alessandro-strada/google-drive-ocamlfuse-beta
+$ sudo apt-get update
+$ sudo apt-get install google-drive-ocamlfuse
+
+```
+
+#### Usage
+
+Once installed, run the following command to launch **google-drive-ocamlfuse** utility from your Terminal:
+```
+$ google-drive-ocamlfuse
+
+```
+
+When you run this first time, the utility will open your web browser and ask your permission to authorize your google drive files. Once you gave authorization, all necessary config files and folders it needs to mount your google drive will be automatically created.
+
+![][5]
+
+After successful authentication, you will see the following message in your Terminal.
+```
+Access token retrieved correctly.
+
+```
+
+You’re good to go now. Close the web browser and then create a mount point to mount your google drive files.
+```
+$ mkdir ~/mygoogledrive
+
+```
+
+Finally, mount your google drive using command:
+```
+$ google-drive-ocamlfuse ~/mygoogledrive
+
+```
+
+Congratulations! You can access access your files either from Terminal or file manager.
+
+From **Terminal** :
+```
+$ ls ~/mygoogledrive
+
+```
+
+From **File manager** :
+
+![][6]
+
+If you have more than one account, use **label** option to distinguish different accounts like below.
+```
+$ google-drive-ocamlfuse -label label [mountpoint]
+
+```
+
+Once you’re done, unmount the FUSE flesystem using command:
+```
+$ fusermount -u ~/mygoogledrive
+
+```
+
+For more details, refer man pages.
+```
+$ google-drive-ocamlfuse --help
+
+```
+
+Also, do check the [**official wiki**][7] and the [**project GitHub repository**][8] for more details.
+
+### 2. GCSF
+
+**GCSF** is a FUSE filesystem based on Google Drive, written using **Rust** programming language. The name GCSF has come from the Romanian word “ **G** oogle **C** onduce **S** istem de **F** ișiere”, which means “Google Drive Filesystem” in English. Using GCSF, you can mount your Google drive as a local virtual file system and access the contents from the Terminal or file manager. You might wonder how it differ from other Google Drive FUSE projects, for example **google-drive-ocamlfuse**. The developer of GCSF replied to a similar [comment on Reddit][9] “GCSF tends to be faster in several cases (listing files recursively, reading large files from Drive). The caching strategy it uses also leads to very fast reads (x4-7 improvement compared to google-drive-ocamlfuse) for files that have been cached, at the cost of using more RAM“.
+
+#### Installing GCSF
+
+GCSF is available in the [**AUR**][10], so the Arch Linux users can install it using any AUR helper, for example [**Yay**][3].
+```
+$ yay -S gcsf-git
+
+```
+
+For other distributions, do the following.
+
+Make sure you have installed Rust on your system.
+
+Make sure **pkg-config** and the **fuse** packages are installed. They are available in the default repositories of most Linux distributions. For example, on Ubuntu and derivatives, you can install them using command:
+```
+$ sudo apt-get install -y libfuse-dev pkg-config
+
+```
+
+Once all dependencies installed, run the following command to install GCSF:
+```
+$ cargo install gcsf
+
+```
+
+#### Usage
+
+First, we need to authorize our google drive. To do so, simply run:
+```
+$ gcsf login ostechnix
+
+```
+
+You must specify a session name. Replace **ostechnix** with your own session name. You will see an output something like below with an URL to authorize your google drive account.
+
+![][11]
+
+Just copy and navigate to the above URL from your browser and click **allow** to give permission to access your google drive contents. Once you gave the authentication you will see an output like below.
+```
+Successfully logged in. Credentials saved to "/home/sk/.config/gcsf/ostechnix".
+
+```
+
+GCSF will create a configuration file in **$XDG_CONFIG_HOME/gcsf/gcsf.toml** , which is usually defined as **$HOME/.config/gcsf/gcsf.toml**. Credentials are stored in the same directory.
+
+Next, create a directory to mount your google drive contents.
+```
+$ mkdir ~/mygoogledrive
+
+```
+
+Then, edit **/etc/fuse.conf** file:
+```
+$ sudo vi /etc/fuse.conf
+
+```
+
+Uncomment the following line to allow non-root users to specify the allow_other or allow_root mount options.
+```
+user_allow_other
+
+```
+
+Save and close the file.
+
+Finally, mount your google drive using command:
+```
+$ gcsf mount ~/mygoogledrive -s ostechnix
+
+```
+
+Sample output:
+```
+INFO gcsf > Creating and populating file system...
+INFO gcsf > File sytem created.
+INFO gcsf > Mounting to /home/sk/mygoogledrive
+INFO gcsf > Mounted to /home/sk/mygoogledrive
+INFO gcsf::gcsf::file_manager > Checking for changes and possibly applying them.
+INFO gcsf::gcsf::file_manager > Checking for changes and possibly applying them.
+
+```
+
+Again, replace **ostechnix** with your session name. You can view the existing sessions using command:
+```
+$ gcsf list
+Sessions:
+- ostechnix
+
+```
+
+You can now access your google drive contents either from the Terminal or from File manager.
+
+From **Terminal** :
+```
+$ ls ~/mygoogledrive
+
+```
+
+From **File manager** :
+
+![][12]
+
+If you don’t know where your Google drive is mounted, use **df** or **mount** command as shown below.
+```
+$ df -h
+Filesystem Size Used Avail Use% Mounted on
+udev 968M 0 968M 0% /dev
+tmpfs 200M 1.6M 198M 1% /run
+/dev/sda1 20G 7.5G 12G 41% /
+tmpfs 997M 0 997M 0% /dev/shm
+tmpfs 5.0M 4.0K 5.0M 1% /run/lock
+tmpfs 997M 0 997M 0% /sys/fs/cgroup
+tmpfs 200M 40K 200M 1% /run/user/1000
+GCSF 15G 857M 15G 6% /home/sk/mygoogledrive
+
+$ mount | grep GCSF
+GCSF on /home/sk/mygoogledrive type fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000,allow_other)
+
+```
+
+Once done, unmount the google drive using command:
+```
+$ fusermount -u ~/mygoogledrive
+
+```
+
+Check the [**GCSF GitHub repository**][13] for more details.
+
+### 3. Tuxdrive
+
+**Tuxdrive** is yet another unofficial google drive client for Linux. We have written a detailed guide about Tuxdrive a while ago. Please check the following link.
+
+Of course, there were few other unofficial google drive clients available in the past, such as Grive2, Syncdrive. But it seems that they are discontinued now. I will keep updating this list when I come across any active google drive clients.
+
+And, that’s all for now, folks. Hope this was useful. More good stuffs to come. Stay tuned!
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/how-to-mount-google-drive-locally-as-virtual-file-system-in-linux/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
+[1]:https://www.google.com/drive/
+[2]:https://aur.archlinux.org/packages/google-drive-ocamlfuse/
+[3]:https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
+[4]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[5]:http://www.ostechnix.com/wp-content/uploads/2018/07/google-drive.png
+[6]:http://www.ostechnix.com/wp-content/uploads/2018/07/google-drive-2.png
+[7]:https://github.com/astrada/google-drive-ocamlfuse/wiki/Configuration
+[8]:https://github.com/astrada/google-drive-ocamlfuse
+[9]:https://www.reddit.com/r/DataHoarder/comments/8vlb2v/google_drive_as_a_file_system/e1oh9q9/
+[10]:https://aur.archlinux.org/packages/gcsf-git/
+[11]:http://www.ostechnix.com/wp-content/uploads/2018/07/google-drive-3.png
+[12]:http://www.ostechnix.com/wp-content/uploads/2018/07/google-drive-4.png
+[13]:https://github.com/harababurel/gcsf
diff --git a/sources/tech/20180725 Best Online Linux Terminals and Online Bash Editors.md b/sources/tech/20180725 Best Online Linux Terminals and Online Bash Editors.md
new file mode 100644
index 0000000000..7f430c3d59
--- /dev/null
+++ b/sources/tech/20180725 Best Online Linux Terminals and Online Bash Editors.md
@@ -0,0 +1,212 @@
+Best Online Linux Terminals and Online Bash Editors
+======
+No matter whether you want to practice Linux commands or just analyze/test your shell scripts online, there’s always a couple of online Linux terminals and online bash compilers available.
+
+This is particularly helpful when you are using the Windows operating system. Though you can [install Linux inside Windows using Windows Subsystem for Linux][1], using online Linux terminals are often more convenient for a quick test.
+
+![Websites that allow to use Linux Terminal online][2]
+
+But where can you find free Linux console? Which online Linux shell should you use?
+
+Fret not, to save you the hassle, here, we have compiled a list of the best online Linux terminals and a separate list of best online bash compilers for you to look at.
+
+**Note:** All of the online terminals support several browsers that include Google Chrome, Mozilla Firefox, Opera and Microsoft Edge.
+
+### Best Online Linux Terminals To Practice Linux Commands
+
+In the first part, I’ll list the online Linux terminals. These websites allow you to run the regular Linux commands in a web browser so that you can practice or test them. Some websites may require you to register and login to save your sessions.
+
+#### 1. JSLinux
+
+![online linux terminal - jslinux][3]
+
+JSLinux is more like a complete Linux emulator instead of just offering you the terminal. As the name suggests, it has been entirely written in JavaScript. You get to choose a console-based system or a GUI-based online Linux system. However, in this case, you would want to launch the console-based system to practice Linux commands. To be able to connect your account, you need to sign up first.
+
+JSLinux also lets you upload files to the virtual machine. At its core, it utilizes [Buildroot][4] (a tool that helps you to build a complete Linux system for an embedded system).
+
+[Try JSLinux Terminal][5]
+
+#### 2. Copy.sh
+
+![copysh online linux terminal][6]
+
+Copy.sh offers one of the best online Linux terminals which is fast and reliable to test and run Linux commands.
+
+Copy.sh is also on [GitHub][7] – and it is being actively maintained, which is a good thing. It also supports other Operating Systems, which includes:
+
+ * Windows 98
+ * KolibriOS
+ * FreeDOS
+ * Windows 1.01
+ * Archlinux
+
+
+
+[Try Copy.sh Terminal][8]
+
+#### 3. Webminal
+
+![webminal online linux terminal][9]
+
+Webminal is an impressive online Linux terminal – and my personal favorite when it comes to a recommendation for beginners to practice Linux commands online.
+
+The website offers several lessons to learn from while you type in the commands in the same window. So, you do not need to refer to another site for the lessons and then switch back or split the screen in order to practice commands. It’s all right there – in a single tab on the browser.
+
+[Try Webminal Terminal][10]
+
+#### 4. Tutorialspoint Unix Terminal
+
+![tutorialspoint linux terminal][11]
+
+You might be aware of Tutorialspoint – which happens to be one of the most popular websites with high quality (yet free) online tutorials for just about any programming language (and more).
+
+So, for obvious reasons, they provide a free online Linux console for you to practice commands while referring to their site as a resource at the same time. You also get the ability to upload files. It is quite simple but an effective online terminal. Also, it doesn’t stop there, it offers a lot of different online terminals as well in its [Coding Ground][12] page.
+
+[Try Unix Terminal Online][13]
+
+#### 5. JS/UIX
+
+![js uix online linux terminal][14]
+
+JS/UIX is yet another online Linux terminal which is written entirely in JavaScript without any plug-ins. It contains an online Linux virtual machine, virtual file-system, shell, and so on.
+
+You can go through its manual page for the list of commands implemented.
+
+[Try JS/UX Terminal][15]
+
+#### 6. CB.VU
+
+![online linux terminal][16]
+
+If you are in for a treat with FreeBSD 7.1 stable version, cb.vu is a quite simple solution for that.
+
+Nothing fancy, just try out the Linux commands you want and get the output. Unfortunately, you do not get the ability to upload files here.
+
+[Try CB.VU Terminal][17]
+
+#### 7. Linux Containers
+
+![online linux terminal][18]
+
+Linux Containers lets you run a demo server with a 30-minute countdown on which acts as one of the best online Linux terminals. In fact, it’s a project sponsored by Canonical.
+
+[Try Linux LXD][19]
+
+#### 8. Codeanywhere
+
+![online linux terminal][20]
+
+Codeanywhere is a service which offers cross-platform cloud IDEs. However, in order to run a free Linux virtual machine, you just need to sign up and choose the free plan. And, then, proceed to create a new connection while setting up a container with an OS of your choice. Finally, you will have a free Linux console at your disposal.
+
+[Try Codeanywhere Editor][21]
+
+### Best Online Bash Editors
+
+Wait a sec! Are the online Linux terminals not good enough for Bash scripting? They are. But creating bash scripts in terminal editors and then executing them is not as convinient as using an online Bash editor.
+
+These bash editors allow you to easily write shell scripts online and you can run them to check if it works or not.
+
+Let’s see here can you run shell scripts online.
+
+#### Tutorialspoint Bash Compiler
+
+![online bash compiler][22]
+
+As mentioned above, Tutorialspoint also offers an online Bash compiler. It is a very simple bash compiler to execute bash shell online.
+
+[Try Tutorialspoint Bash Compiler][23]
+
+#### JDOODLE
+
+![online bash compiler][24]
+
+Yet another useful online bash editor to test Bash scripts is JDOODLE. It also offers other IDEs, but we’ll focus on bash script execution here. You get to set the command line arguments and the stdin inputs, and would normally get the result of your code.
+
+[Try JDOODLE Bash Script Online Tester][25]
+
+#### Paizo.io
+
+![paizo online bash editor][26]
+
+Paizo.io is a good bash online editor that you can try for free. To utilize some of its advanced features like task scheduling, you need to first sign up. It also supports real-time collaboration, but that’s still in the experimental phase.
+
+[Try Paizo.io Bash Editor][27]
+
+#### ShellCheck
+
+![shell check bash check][28]
+
+An interesting Bash editor which lets you find bugs in your shell script. It is available on [GitHub][29] as well. In addition, you can install ShellCheck locally on [supported platforms][30].
+
+[Try ShellCheck][31]
+
+#### Rextester
+
+![rextester bash editor][32]
+
+If you only want a dead simple online bash compiler, Rextester should be your choice. It also supports other programming languages.
+
+[Try Rextester][33]
+
+#### Learn Shell
+
+![online bash shell editor][34]
+
+Just like [Webminal][35], Learnshell provides you with the content (or resource) to learn shell programming and you could also run/try your code at the same time. It covers the basics and a few advanced topics as well.
+
+[Try Learn Shell Programming][36]
+
+### Wrapping Up
+
+Now that you know of the most reliable and fast online Linux terminals & online bash editors, learn, experiment, and play with the code!
+
+We might have missed any of your favorite online Linux terminals or maybe the best online bash compiler which you happen to use? Let us know your thoughts in the comments below.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/online-linux-terminals/
+
+作者:[Ankush Das][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/ankush/
+[1]:https://itsfoss.com/install-bash-on-windows/
+[2]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/online-linux-terminals.jpeg
+[3]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/jslinux-online-linux-terminal.jpg
+[4]:https://buildroot.org/
+[5]:https://bellard.org/jslinux/
+[6]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/copy-sh-online-linux-terminal.jpg
+[7]:https://github.com/copy/v86
+[8]:https://copy.sh/v86/?profile=linux26
+[9]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/webminal.jpg
+[10]:http://www.webminal.org/terminal/
+[11]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/coding-ground-tutorialspoint-online-linux-terminal.jpg
+[12]:https://www.tutorialspoint.com/codingground.htm
+[13]:https://www.tutorialspoint.com/unix_terminal_online.php
+[14]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/JS-UIX-online-linux-terminal.jpg
+[15]:http://www.masswerk.at/jsuix/index.html
+[16]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/cb-vu-online-linux-terminal.jpg
+[17]:http://cb.vu/
+[18]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/linux-containers-terminal.jpg
+[19]:https://linuxcontainers.org/lxd/try-it/
+[20]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/codeanywhere-terminal.jpg
+[21]:https://codeanywhere.com/editor/
+[22]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/tutorialspoint-bash-compiler.jpg
+[23]:https://www.tutorialspoint.com/execute_bash_online.php
+[24]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/jdoodle-online-bash-editor.jpg
+[25]:https://www.jdoodle.com/test-bash-shell-script-online
+[26]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/paizo-io-bash-editor.jpg
+[27]:https://paiza.io/en/projects/new?language=bash
+[28]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/shell-check-bash-analyzer.jpg
+[29]:https://github.com/koalaman/shellcheck
+[30]:https://github.com/koalaman/shellcheck#user-content-installing
+[31]:https://www.shellcheck.net/#
+[32]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/rextester-bash-editor.jpg
+[33]:http://rextester.com/l/bash_online_compiler
+[34]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/learnshell-online-bash-shell.jpg
+[35]:http://www.webminal.org/
+[36]:http://www.learnshell.org/
diff --git a/sources/tech/20180725 Build an interactive CLI with Node.js.md b/sources/tech/20180725 Build an interactive CLI with Node.js.md
new file mode 100644
index 0000000000..6ec13f1cfc
--- /dev/null
+++ b/sources/tech/20180725 Build an interactive CLI with Node.js.md
@@ -0,0 +1,531 @@
+Build an interactive CLI with Node.js
+======
+
+
+
+Node.js can be very useful when it comes to building command-line interfaces (CLIs). In this post, I'll teach you how to use [Node.js][1] to build a CLI that asks some questions and creates a file based on the answers.
+
+### Get started
+
+Let's start by creating a brand new [npm][2] package. (Npm is the JavaScript package manager.)
+```
+mkdir my-script
+
+cd my-script
+
+npm init
+
+```
+
+Npm will ask some questions. After that, we need to install some packages.
+```
+npm install --save chalk figlet inquirer shelljs
+
+```
+
+Here's what these packages do:
+
+ * **Chalk:** Terminal string styling done right
+ * **Figlet:** A program for making large letters out of ordinary text
+ * **Inquirer:** A collection of common interactive command-line user interfaces
+ * **ShellJS:** Portable Unix shell commands for Node.js
+
+
+
+### Make an index.js file
+
+Now we'll create an `index.js` file with the following content:
+```
+#!/usr/bin/env node
+
+
+
+const inquirer = require("inquirer");
+
+const chalk = require("chalk");
+
+const figlet = require("figlet");
+
+const shell = require("shelljs");
+
+```
+
+### Plan the CLI
+
+It's always good to plan what a CLI needs to do before writing any code. This CLI will do just one thing: **create a file**.
+
+The CLI will ask two questions—what is the filename and what is the extension?—then create the file, and show a success message with the created file path.
+```
+// index.js
+
+
+
+const run = async () => {
+
+ // show script introduction
+
+ // ask questions
+
+ // create the file
+
+ // show success message
+
+};
+
+
+
+run();
+
+```
+
+The first function is the script introduction. Let's use `chalk` and `figlet` to get the job done.
+```
+const init = () => {
+
+ console.log(
+
+ chalk.green(
+
+ figlet.textSync("Node JS CLI", {
+
+ font: "Ghost",
+
+ horizontalLayout: "default",
+
+ verticalLayout: "default"
+
+ })
+
+ )
+
+ );
+
+}
+
+
+
+const run = async () => {
+
+ // show script introduction
+
+ init();
+
+
+
+ // ask questions
+
+ // create the file
+
+ // show success message
+
+};
+
+
+
+run();
+
+```
+
+Second, we'll write a function that asks the questions.
+```
+const askQuestions = () => {
+
+ const questions = [
+
+ {
+
+ name: "FILENAME",
+
+ type: "input",
+
+ message: "What is the name of the file without extension?"
+
+ },
+
+ {
+
+ type: "list",
+
+ name: "EXTENSION",
+
+ message: "What is the file extension?",
+
+ choices: [".rb", ".js", ".php", ".css"],
+
+ filter: function(val) {
+
+ return val.split(".")[1];
+
+ }
+
+ }
+
+ ];
+
+ return inquirer.prompt(questions);
+
+};
+
+
+
+// ...
+
+
+
+const run = async () => {
+
+ // show script introduction
+
+ init();
+
+
+
+ // ask questions
+
+ const answers = await askQuestions();
+
+ const { FILENAME, EXTENSION } = answers;
+
+
+
+ // create the file
+
+ // show success message
+
+};
+
+```
+
+Notice the constants FILENAME and EXTENSIONS that came from `inquirer`.
+
+The next step will create the file.
+```
+const createFile = (filename, extension) => {
+
+ const filePath = `${process.cwd()}/${filename}.${extension}`
+
+ shell.touch(filePath);
+
+ return filePath;
+
+};
+
+
+
+// ...
+
+
+
+const run = async () => {
+
+ // show script introduction
+
+ init();
+
+
+
+ // ask questions
+
+ const answers = await askQuestions();
+
+ const { FILENAME, EXTENSION } = answers;
+
+
+
+ // create the file
+
+ const filePath = createFile(FILENAME, EXTENSION);
+
+
+
+ // show success message
+
+};
+
+```
+
+And last but not least, we'll show the success message along with the file path.
+```
+const success = (filepath) => {
+
+ console.log(
+
+ chalk.white.bgGreen.bold(`Done! File created at ${filepath}`)
+
+ );
+
+};
+
+
+
+// ...
+
+
+
+const run = async () => {
+
+ // show script introduction
+
+ init();
+
+
+
+ // ask questions
+
+ const answers = await askQuestions();
+
+ const { FILENAME, EXTENSION } = answers;
+
+
+
+ // create the file
+
+ const filePath = createFile(FILENAME, EXTENSION);
+
+
+
+ // show success message
+
+ success(filePath);
+
+};
+
+```
+
+Let's test the script by running `node index.js`. Here's what we get:
+
+### The full code
+
+Here is the final code:
+```
+#!/usr/bin/env node
+
+
+
+const inquirer = require("inquirer");
+
+const chalk = require("chalk");
+
+const figlet = require("figlet");
+
+const shell = require("shelljs");
+
+
+
+const init = () => {
+
+ console.log(
+
+ chalk.green(
+
+ figlet.textSync("Node JS CLI", {
+
+ font: "Ghost",
+
+ horizontalLayout: "default",
+
+ verticalLayout: "default"
+
+ })
+
+ )
+
+ );
+
+};
+
+
+
+const askQuestions = () => {
+
+ const questions = [
+
+ {
+
+ name: "FILENAME",
+
+ type: "input",
+
+ message: "What is the name of the file without extension?"
+
+ },
+
+ {
+
+ type: "list",
+
+ name: "EXTENSION",
+
+ message: "What is the file extension?",
+
+ choices: [".rb", ".js", ".php", ".css"],
+
+ filter: function(val) {
+
+ return val.split(".")[1];
+
+ }
+
+ }
+
+ ];
+
+ return inquirer.prompt(questions);
+
+};
+
+
+
+const createFile = (filename, extension) => {
+
+ const filePath = `${process.cwd()}/${filename}.${extension}`
+
+ shell.touch(filePath);
+
+ return filePath;
+
+};
+
+
+
+const success = filepath => {
+
+ console.log(
+
+ chalk.white.bgGreen.bold(`Done! File created at ${filepath}`)
+
+ );
+
+};
+
+
+
+const run = async () => {
+
+ // show script introduction
+
+ init();
+
+
+
+ // ask questions
+
+ const answers = await askQuestions();
+
+ const { FILENAME, EXTENSION } = answers;
+
+
+
+ // create the file
+
+ const filePath = createFile(FILENAME, EXTENSION);
+
+
+
+ // show success message
+
+ success(filePath);
+
+};
+
+
+
+run();
+
+```
+
+### Use the script anywhere
+
+To execute this script anywhere, add a `bin` section in your `package.json` file and run `npm link`.
+```
+{
+
+ "name": "creator",
+
+ "version": "1.0.0",
+
+ "description": "",
+
+ "main": "index.js",
+
+ "scripts": {
+
+ "test": "echo \"Error: no test specified\" && exit 1",
+
+ "start": "node index.js"
+
+ },
+
+ "author": "",
+
+ "license": "ISC",
+
+ "dependencies": {
+
+ "chalk": "^2.4.1",
+
+ "figlet": "^1.2.0",
+
+ "inquirer": "^6.0.0",
+
+ "shelljs": "^0.8.2"
+
+ },
+
+ "bin": {
+
+ "creator": "./index.js"
+
+ }
+
+}
+
+```
+
+Running `npm link` makes this script available anywhere.
+
+That's what happens when you run this command:
+```
+/usr/bin/creator -> /usr/lib/node_modules/creator/index.js
+
+/usr/lib/node_modules/creator -> /home/hugo/code/creator
+
+```
+
+It links the `index.js` file as an executable. This is only possible because of the first line of the CLI script: `#!/usr/bin/env node`.
+
+Now we can run this script by calling:
+```
+$ creator
+
+```
+
+### Wrapping up
+
+As you can see, Node.js makes it very easy to build nice command-line tools! If you want to go even further, check this other packages:
+
+ * [meow][3] – a simple command-line helper
+ * [yargs][4] – a command-line opt-string parser
+ * [pkg][5] – package your Node.js project into an executable
+
+
+
+Tell us about your experience building a CLI in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/node-js-interactive-cli
+
+作者:[Hugo Dias][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/hugodias
+[1]:https://nodejs.org/en/
+[2]:https://www.npmjs.com/
+[3]:https://github.com/sindresorhus/meow
+[4]:https://github.com/yargs/yargs
+[5]:https://github.com/zeit/pkg
diff --git a/sources/tech/20180727 4 Ways to Customize Xfce and Give it a Modern Look.md b/sources/tech/20180727 4 Ways to Customize Xfce and Give it a Modern Look.md
new file mode 100644
index 0000000000..c4372724f7
--- /dev/null
+++ b/sources/tech/20180727 4 Ways to Customize Xfce and Give it a Modern Look.md
@@ -0,0 +1,145 @@
+4 Ways to Customize Xfce and Give it a Modern Look
+======
+**Brief: Xfce is a great lightweight desktop environment with one drawback. It looks sort of old. But you don’t have to stick with the default looks. Let’s see various ways you can customize Xfce to give it a modern and beautiful look.**
+
+![Customize Xfce desktop envirnment][1]
+
+To start with, Xfce is one of the most [popular desktop environments][2]. Being a lightweight DE, you can run Xfce on very low resource and it still works great. This is one of the reasons why many [lightweight Linux distributions][3] use Xfce by default.
+
+Some people prefer it even on a high-end device stating its simplicity, easy of use and non-resource hungry nature as the main reasons.
+
+[Xfce][4] is in itself minimal and provides just what you need. The one thing that bothers is its look and feel which feel old. However, you can easily customize Xfce to look modern and beautiful without reaching the limit where a Unity/GNOME session eats up system resources.
+
+### 4 ways to Customize Xfce desktop
+
+Let’s see some of the ways by which we can improve the look and feel of your Xfce desktop environment.
+
+The default Xfce desktop environment looks something like this :
+
+![Xfce default screen][5]
+
+As you can see, the default Xfce desktop is kinda boring. We will use some themes, icon packs and change the default dock to make it look fresh and a bit revealing.
+
+#### 1. Change themes in Xfce
+
+The first thing we will do is pick up a theme from [xfce-look.org][6]. My favorite Xfce theme is [XFCE-D-PRO][7].
+
+You can download the theme from [here][8] and extract it somewhere.
+
+You can copy this extracted file to **.theme** folder in your home directory. If the folder is not present by default, you can create one and the same goes for icons which needs a **.icons** folder in the home directory.
+
+Open **Settings > Appearance > Style** to select the theme, log out and login to see the change. Adwaita-dark from default is also a nice one.
+
+![Appearance Xfce][9]
+
+You can use any [good GTK theme][10] on Xfce.
+
+#### 2. Change icons in Xfce
+
+Xfce-look.org also provides icon themes which you can download, extract and put it in your home directory under **.icons** directory. Once you have added the icon theme in the .icons directory, go to **Settings > Appearance > Icons** to select that icon theme.
+
+![Moka icon theme][11]
+
+I have installed [Moka icon set][12] that looks awesome.
+
+![Moka theme][13]
+
+You can also refer to our list of [awesome icon themes][14].
+
+##### **Optional: Installing themes through Synaptic**
+
+If you want to avoid the manual search and copying of the files, install Synaptic Manager in your system. You can look for some best themes over web and icon sets, and using synaptic manager you can search and install it.
+```
+sudo apt-get install synaptic
+
+```
+
+**Searching and installing theme/icons through Synaptic**
+
+Open synaptic and click on **Search**. Enter your desired theme, and it will display the list of matching items. Mark all the additional required changes and click on **Apply**. This will download the theme and then install it.
+
+![Arc Theme][15]
+
+Once done, you can open the **Appearance** option to select the desired theme.
+
+In my opinion, this is not the best way to install themes in Xfce.
+
+#### 3. Change wallpapers in Xfce
+
+Again, the default Xfce wallpaper is not bad at all. But you can change the wallpaper to something that matches with your icons and themes.
+
+To change wallpapers in Xfce, right click on the desktop and click on Desktop Settings. You can change the desktop background from your custom collection or the defaults one given.
+
+Right click on the desktop and click on **Desktop Settings**. Choose **Background** from the folder option, and choose any one of the default backgrounds or a custom one.
+
+![Changing desktop wallpapers][16]
+
+#### 4. Change the dock in Xfce
+
+The default dock is nice and pretty much does what it is for. But again, it looks a bit boring.
+
+![Docky][17]
+
+However, if you want your dock to be better and with a little more customization options, you can install another dock.
+
+Plank is one of the simplest and lightweight docks and is highly configurable.
+
+To install Plank use the command below:
+
+`sudo apt-get install plank`
+
+If Plank is not available in the default repository, you can install it from this PPA.
+```
+sudo add-apt-repository ppa:ricotz/docky
+sudo apt-get update
+sudo apt-get install plank
+
+```
+
+Before you use Plank, you should remove the default dock by right-clicking in it and under Panel Settings, clicking on delete.
+
+Once done, go to **Accessory > Plank** to launch Plank dock.
+
+![Plank][18]
+
+Plank picks up icons from the one you are using. So if you change the icon themes, you’ll see the change is reflected in the dock also.
+
+### Wrapping Up
+
+XFCE is a lightweight, fast and highly customizable. If you are limited on system resource, it serves good and you can easily customize it to look better. Here’s how my screen looks after applying these steps.
+
+![XFCE desktop][19]
+
+This is just with half an hour of effort. You can make it look much better with different themes/icons customization. Feel free to share your customized XFCE desktop screen in the comments and the combination of themes and icons you are using.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/customize-xfce/
+
+作者:[Ambarish Kumar][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/ambarish/
+[1]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/xfce-customization.jpeg
+[2]:https://itsfoss.com/best-linux-desktop-environments/
+[3]:https://itsfoss.com/lightweight-linux-beginners/
+[4]:https://xfce.org/
+[5]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/06/1-1-800x410.jpg
+[6]:http://xfce-look.org
+[7]:https://www.xfce-look.org/p/1207818/XFCE-D-PRO
+[8]:https://www.xfce-look.org/p/1207818/startdownload?file_id=1523730502&file_name=XFCE-D-PRO-1.6.tar.xz&file_type=application/x-xz&file_size=105328&url=https%3A%2F%2Fdl.opendesktop.org%2Fapi%2Ffiles%2Fdownloadfile%2Fid%2F1523730502%2Fs%2F6019b2b57a1452471eac6403ae1522da%2Ft%2F1529360682%2Fu%2F%2FXFCE-D-PRO-1.6.tar.xz
+[9]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/4.jpg
+[10]:https://itsfoss.com/best-gtk-themes/
+[11]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/6.jpg
+[12]:https://snwh.org/moka
+[13]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/11-800x547.jpg
+[14]:https://itsfoss.com/best-icon-themes-ubuntu-16-04/
+[15]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/5-800x531.jpg
+[16]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/7-800x546.jpg
+[17]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/8.jpg
+[18]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/9.jpg
+[19]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/10-800x447.jpg
diff --git a/sources/tech/20180727 Download Subtitles Via Right Click From File Manager Or Command Line With OpenSubtitlesDownload.py.md b/sources/tech/20180727 Download Subtitles Via Right Click From File Manager Or Command Line With OpenSubtitlesDownload.py.md
new file mode 100644
index 0000000000..9d4c7fedd7
--- /dev/null
+++ b/sources/tech/20180727 Download Subtitles Via Right Click From File Manager Or Command Line With OpenSubtitlesDownload.py.md
@@ -0,0 +1,221 @@
+Download Subtitles Via Right Click From File Manager Or Command Line With OpenSubtitlesDownload.py
+======
+**If you're looking for a quick way to download subtitles from OpenSubtitles.org from your Linux desktop or server, give[OpenSubtitlesDownload.py][1] a try. This neat Python tool can be used as a Nautilus, Nemo or Caja script, or from the command line.**
+
+
+
+The Python script **searches for subtitles on OpenSubtitles.org using the video hash sum to find exact matches** , and thus avoid out of sync subtitles. In case no match is found, it then tries to perform a search based on the video file name, although such subtitles may not always be in sync.
+
+OpenSubtitlesDownload.py has quite a few cool features, including **support for more than 60 languages,** and it can query both multiple subtitle languages and videos in the same time (so it **supports mass subtitle search and download** ).
+
+The **optional graphical user interface** (uses Zenity for Gnome and Kdialog for KDE) can display multiple subtitle matches and by digging into its settings you can enable the display of some extra information, like the subtitles download count, rating, language, and more.
+
+Other OpenSubtitlesDownload.py features include:
+
+ * Option to download subtitles automatically if only one is available, choose the one you want otherwise.
+ * Option to rename downloaded subtitles to match source video file. Possibility to append the language code to the file name (ex: movie_en.srt).
+
+
+
+The Python tool does not yet support downloading subtitles for movies within a directory recursively, but this is a planned feature.
+
+In case you encounter errors when downloading a large number of subtitles, you should be aware that OpenSubtitles has a daily subtitle download limit (it appears it was 200 subtitles downloads / day a while back, I'm not sure if it changed). For VIP users it's 1000 subtitles per day, but OpenSubtitlesDownload.py does not allow logging it to an OpenSubtitles account and thus, you can't take advantage of a VIP account while using this tool.
+
+### Installing and using OpenSubtitlesDownload.py as a Nautilus, Nemo or Caja script
+
+The instructions below explain how to install OpenSubtitlesDownload.py as a script for Caja, Nemo or Nautilus file managers. Thanks to this you'll be able to right click (context menu) one or multiple video files in your file manager, select `Scripts > OpenSubtitlesDownload.py` and the script will search for and download subtitles from OpenSubtitles.org for your video files.
+
+This is OpenSubtitlesDownload.py used as a Nautilus script:
+
+
+
+And as a Nemo script:
+
+
+
+To install OpenSubtitlesDownload.py as a Nautilus, Nemo or Caja script, see the instructions below.
+
+1\. Install the dependencies required by OpenSubtitlesDownload.py
+
+You'll need to install `gzip` , `wget` and `zenity` before using OpenSubtitlesDownload.py. The instructions below assume you already have Python (both Python 2 and 3 will do it), as well as `ps` and `grep` available.
+
+In Debian, Ubuntu, or Linux Mint, install `gzip` , `wget` and `zenity` using this command:
+```
+sudo apt install gzip wget zenity
+
+```
+
+2\. Now you can download the OpenSubtitlesDownload.py
+```
+wget https://raw.githubusercontent.com/emericg/OpenSubtitlesDownload/master/OpenSubtitlesDownload.py
+
+```
+
+3\. Use the commands below to move the downloaded OpenSubtitlesDownload.py script to the file manager scripts folder and make it executable (use the commands for your current file manager - Nautilus, Nemo or Caja):
+
+ * Nautilus (default Gnome, Unity and Solus OS file manager):
+
+
+```
+mkdir -p ~/.local/share/nautilus/scripts
+mv OpenSubtitlesDownload.py ~/.local/share/nautilus/scripts/
+chmod u+x ~/.local/share/nautilus/scripts/OpenSubtitlesDownload.py
+
+```
+
+ * Nemo (default Cinnamon file manager):
+
+
+```
+mkdir -p ~/.local/share/nemo/scripts
+mv OpenSubtitlesDownload.py ~/.local/share/nemo/scripts/
+chmod u+x ~/.local/share/nemo/scripts/OpenSubtitlesDownload.py
+
+```
+
+ * Caja (default MATE file manager):
+
+
+```
+mkdir -p ~/.config/caja/scripts
+mv OpenSubtitlesDownload.py ~/.config/caja/scripts/
+chmod u+x ~/.config/caja/scripts/OpenSubtitlesDownload.py
+
+```
+
+4\. Configure OpenSubtitlesDownload.py
+
+Since it's running as a file manager script, without any arguments, you'll need to modify the script if you want to change some of its settings, like enabling the GUI, changing the subtitles language, and so on. These are optional of course, and you can use it directly to automatically download subtitles using its default settings.
+
+To Configure OpenSubtitlesDownload.py, you'll need to open it with a text editor. The script path should now be:
+
+ * Nautilus:
+
+`~/.local/share/nautilus/scripts`
+
+ * Nemo:
+
+`~/.local/share/nemo/scripts`
+
+ * Caja:
+
+`~/.config/caja/scripts`
+
+
+
+
+Navigate to that folder using your file manager and open the OpenSubtitlesDownload.py file with a text editor.
+
+Here's what you may want to change in this file:
+
+ * To change the subtitle language, search for `opt_languages = ['eng']` and change the language from `['eng']` (English) to `['fre']` (French), or whatever language you want to use. The ISO codes for each language supported by OpenSubtitles.org are available on [this][2] page (use the code in the first column).
+
+ * If you want a GUI to present you with all subtitles options and let you choose which to download, find the `opt_selection_mode = 'default'` setting and change it to `'manual'` . You'll not want to change this to 'manual' (or better yet, change it to 'auto') if you want to download multiple subtitles in the same time and avoid having a window popup for each video!
+
+ * To force the Gnome GUI to be used, search for `opt_gui = 'auto'` and change `'auto'` to `'gnome'`
+
+ * You can also enable multiple info columns in the GUI:
+
+ * Search for `opt_selection_rating = 'off'` and change it to `'auto'` to display user ratings if available
+
+ * Search for `opt_selection_count = 'off'` and change it to `'auto'` to display the subtitle number of downloads if available
+
+
+**You can find a list of OpenSubtitlesDownload.py settings with explanations by visiting[this page][3].**
+
+And you're done. OpenSubtitlesDownload.py should now appear in Nautilus, Nemo or Caja, when right clicking a file and selecting Scripts. Clicking OpenSubtitlesDownload.py should search and download subtitles for the selected video(s).
+
+### Installing and using OpenSubtitlesDownload.py from the command line
+
+1\. Install the dependencies required by OpenSubtitlesDownload.py (command line only)
+
+You'll need to install `gzip` and `wget` . On Debian, Ubuntu or Linux Mint you can install these packages by using this command:
+```
+sudo apt install wget gzip
+
+```
+
+2\. Install the `/usr/local/bin/` and set it so it uses the command line interface by default:
+```
+wget https://raw.githubusercontent.com/emericg/OpenSubtitlesDownload/master/OpenSubtitlesDownload.py -O opensubtitlesdownload
+sed -i "s/opt_gui = 'auto'/opt_gui = 'cli'/" opensubtitlesdownload
+sudo install opensubtitlesdownload /usr/local/bin/
+
+```
+
+Now you can start using it. To use the script with automatic selection and download of the best available subtitle, type:
+```
+opensubtitlesdownload --auto /path/to/video.mkv
+
+```
+
+You can specify the language by appending `--lang LANG` , where `LANG` is the ISO code for a language supported by OpenSubtitles.org, available on
+```
+opensubtitlesdownload --lang SPA /home/logix/Videos/Sintel.2010.720p.mkv
+
+```
+
+Which provides this output (it allows you to choose the best subtitle since we didn't use `--auto` only, nor did we append `--select manual` to allow manual selection):
+```
+>> Title: Sintel
+>> Filename: Sintel.2010.720p.mkv
+>> Available subtitles:
+[1] "Sintel (2010).spa.srt" > "Language: Spanish"
+[2] "sintel_es.srt" > "Language: Spanish"
+[3] "Sintel.2010.720p.x264-VODO-spa.srt" > "Language: Spanish"
+[0] Cancel search
+>> Enter your choice (0-3): 1
+>> Downloading 'Spanish' subtitles for 'Sintel'
+2018-07-27 14:37:04 URL:http://dl.opensubtitles.org/en/download/src-api/vrf-19c10c57/sid-8rL5O0xhUw2BgKG6lvsVBM0p00f/filead/1955318590.gz [936/936] -> "-" [1]
+
+```
+
+These are all the available options:
+```
+$ opensubtitlesdownload --help
+usage: OpenSubtitlesDownload.py [-h] [-g GUI] [--cli] [-s SEARCH] [-t SELECT]
+ [-a] [-v] [-l [LANG]]
+ filePathListArg [filePathListArg ...]
+
+This software is designed to help you find and download subtitles for your favorite videos!
+
+
+ -h, --help show this help message and exit
+ -g GUI, --gui GUI Select the GUI you want from: auto, kde, gnome, cli (default: auto)
+ --cli Force CLI mode
+ -s SEARCH, --search SEARCH
+ Search mode: hash, filename, hash_then_filename, hash_and_filename (default: hash_then_filename)
+ -t SELECT, --select SELECT
+ Selection mode: manual, default, auto
+ -a, --auto Force automatic selection and download of the best subtitles found
+ -v, --verbose Force verbose output
+ -l [LANG], --lang [LANG]
+ Specify the language in which the subtitles should be downloaded (default: eng).
+ Syntax:
+ -l eng,fre: search in both language
+ -l eng -l fre: download both language
+
+```
+
+**The theme used for the screenshots in this article is called[Canta][4].**
+
+**You may also be interested in:[How To Replace Nautilus With Nemo File Manager On Ubuntu 18.04 Gnome Desktop (Complete Guide)][5]**
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxuprising.com/2018/07/download-subtitles-via-right-click-from.html
+
+作者:[Logix][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://plus.google.com/118280394805678839070
+[1]:https://emericg.github.io/OpenSubtitlesDownload/
+[2]:http://www.opensubtitles.org/addons/export_languages.php
+[3]:https://github.com/emericg/OpenSubtitlesDownload/wiki/Adjust-settings
+[4]:https://www.linuxuprising.com/2018/04/canta-is-amazing-material-design-gtk.html
+[5]:https://www.linuxuprising.com/2018/07/how-to-replace-nautilus-with-nemo-file.html
+[6]:https://raw.githubusercontent.com/emericg/OpenSubtitlesDownload/master/OpenSubtitlesDownload.py
diff --git a/sources/tech/20180727 How to analyze your system with perf and Python.md b/sources/tech/20180727 How to analyze your system with perf and Python.md
new file mode 100644
index 0000000000..ccc66b04a7
--- /dev/null
+++ b/sources/tech/20180727 How to analyze your system with perf and Python.md
@@ -0,0 +1,1481 @@
+pinewall translating
+
+How to analyze your system with perf and Python
+======
+
+
+
+Modern computers are ever increasing in performance and capacity. This matters little if that increasing capacity is not well utilized. Following is a description of the motivation and work behind "curt," a new tool for Linux systems for measuring and breaking down system utilization by process, by task, and by CPU using the `perf` command's Python scripting capabilities.
+
+I had the privilege of presenting this topic at [Texas Linux Fest 2018][1], and here I've gone a bit deeper into the details, included links to further information, and expanded the scope of my talk.
+
+### System utilization
+
+In discussing computation, let's begin with some assertions:
+
+ 1. Every computational system is equally fast at doing nothing.
+ 2. Computational systems were created to do things.
+ 3. A computational system is better at doing things when it is doing something than when it is doing nothing.
+
+
+
+Modern computational systems have many streams of execution:
+
+ * Often, very large systems are created by literally wiring together smaller systems. At IBM, these smaller systems are sometimes called CECs (short for Central Electronics Complexes and pronounced "keks").
+ * There are multiple sockets for processor modules in each system.
+ * There are sometimes multiple chips per socket (in the form of dual-chip modules—DCMs—or multi-chip modules—MCMs).
+ * There are multiple cores per chip.
+ * There are multiple threads per core.
+
+
+
+In sum, there are potentially thousands of execution threads across a single computational system.
+
+Ideally, all these execution streams are 100% busy doing useful work. One measure of **utilization** for an individual execution stream (CPU thread) is the percentage of time that thread has tasks scheduled and running. (Note that I didn't say "doing useful work." Creating a tool that measures useful work is left as an exercise for the reader.) By extension, **system utilization** is the overall percentage of time that all execution streams of a system have tasks scheduled and running. Similarly, utilization can be defined with respect to an individual task. **Task utilization** is the percentage of the lifetime of the task that was spent actively running on any CPU thread. By extension, **process utilization** is the collective utilization of its tasks.
+
+### Utilization measurement tools
+
+There are tools that measure system utilization: `uptime`, `vmstat`, `mpstat`, `nmon`, etc. There are tools that measure individual process utilization: `time`. There are not many tools that measure system-wide per-process and per-task utilization. One such command is `curt` on AIX. According to [IBM's Knowledge Center][2]: "The `curt` command takes an AIX trace file as input and produces a number of statistics related to processor (CPU) utilization and process/thread/pthread activity."
+
+The AIX `curt` command reports system-wide, per-processor, per-process, and per-task statistics for application processing (user time), system calls (system time), hypervisor calls, kernel threads, interrupts, and idle time.
+
+This seems like a good model for a similar command for a Linux system.
+
+### Utilization data
+
+Before starting to create any tools for utilization analysis, it is important to know what data is required. Since utilization is directly related to whether a task is actively running or not, related scheduling events are required: When is the task made to run, and when is it paused? Tracking on which CPU the task runs is important, so migration events are required for implicit migrations. There are also certain system calls that force explicit migrations. Creation and deletion of tasks are obviously important. Since we want to understand user time, system time, hypervisor time, and interrupt time, events that show the transitions between those task states are required.
+
+The Linux kernel contains "tracepoints" for all those events. It is possible to enable tracing for those events directly in the kernel's `debugfs` filesystem, usually mounted at `/sys/kernel/debug`, in the `tracing` directory (`/sys/kernel/debug/tracing`).
+
+An easier way to record tracing data is with the Linux `perf` command.
+
+### The perf command
+
+`perf` is a very powerful userspace command for tracing or counting both hardware and software events.
+
+Software events are predefined in the kernel, can be predefined in userspace code, and can be dynamically created (as "probes") in kernel or userspace code.
+
+`perf` can do much more than just trace and count, though.
+
+#### perf stat
+
+The `stat` subcommand of `perf` will run a command, count some events commonly found interesting, and produce a simple report:
+```
+Performance counter stats for './load 100000':
+
+ 90537.006424 task-clock:u (msec) # 1.000 CPUs utilized
+ 0 context-switches:u # 0.000 K/sec
+ 0 cpu-migrations:u # 0.000 K/sec
+ 915 page-faults:u # 0.010 K/sec
+ 386,836,206,133 cycles:u # 4.273 GHz (66.67%)
+ 3,488,523,420 stalled-cycles-frontend:u # 0.90% frontend cycles idle (50.00%)
+ 287,222,191,827 stalled-cycles-backend:u # 74.25% backend cycles idle (50.00%)
+ 291,102,378,513 instructions:u # 0.75 insn per cycle
+ # 0.99 stalled cycles per insn (66.67%)
+ 43,730,320,236 branches:u # 483.010 M/sec (50.00%)
+ 822,030,340 branch-misses:u # 1.88% of all branches (50.00%)
+
+ 90.539972837 seconds time elapsed
+```
+
+#### perf record, perf report, and perf annotate
+
+For much more interesting analysis, the `perf` command can also be used to record events and information associated with the task state at the time the event occurred:
+```
+$ perf record ./some-command
+[ perf record: Woken up 55 times to write data ]
+[ perf record: Captured and wrote 13.973 MB perf.data (366158 samples) ]
+$ perf report --stdio --show-nr-samples --percent-limit 4
+# Samples: 366K of event 'cycles:u'
+# Event count (approx.): 388851358382
+#
+# Overhead Samples Command Shared Object Symbol
+# ........ ............ ....... ................. ................................................
+#
+ 62.31% 228162 load load [.] main
+ 19.29% 70607 load load [.] sum_add
+ 18.33% 67117 load load [.] sum_sub
+```
+
+This example shows a program that spends about 60% of its running time in the function `main` and about 20% each in subfunctions `sum_sub` and `sum_add`. Note that the default event used by `perf record` is "cycles." Later examples will show how to use `perf record` with other events.
+
+`perf report` can further report runtime statistics by source code line (if the compilation was performed with the `-g` flag to produce debug information):
+```
+$ perf report --stdio --show-nr-samples --percent-limit 4 --sort=srcline
+# Samples: 366K of event 'cycles:u'
+# Event count (approx.): 388851358382
+#
+# Overhead Samples Source:Line
+# ........ ............ ...................................
+#
+ 19.40% 71031 load.c:58
+ 16.16% 59168 load.c:18
+ 15.11% 55319 load.c:14
+ 13.30% 48690 load.c:66
+ 13.23% 48434 load.c:70
+ 4.58% 16767 load.c:62
+ 4.01% 14677 load.c:56
+```
+
+Further, `perf annotate` can show statistics for each instruction of the program:
+```
+$ perf annotate --stdio
+Percent | Source code & Disassembly of load for cycles:u (70607 samples)
+------------------------------------------------------------------------------
+ : 0000000010000774 :
+ : int sum_add(int sum, int value) {
+ 12.60 : 10000774: std r31,-8(r1)
+ 0.02 : 10000778: stdu r1,-64(r1)
+ 0.00 : 1000077c: mr r31,r1
+ 41.90 : 10000780: mr r10,r3
+ 0.00 : 10000784: mr r9,r4
+ 0.05 : 10000788: stw r10,32(r31)
+ 23.78 : 1000078c: stw r9,36(r31)
+ : return (sum + value);
+ 0.76 : 10000790: lwz r10,32(r31)
+ 0.00 : 10000794: lwz r9,36(r31)
+ 14.75 : 10000798: add r9,r10,r9
+ 0.00 : 1000079c: extsw r9,r9
+ : }
+ 6.09 : 100007a0: mr r3,r9
+ 0.02 : 100007a4: addi r1,r31,64
+ 0.03 : 100007a8: ld r31,-8(r1)
+ 0.00 : 100007ac: blr
+```
+
+(Note: this code is not optimized.)
+
+#### perf top
+
+Similar to the `top` command, which displays (at a regular update interval) the processes using the most CPU time, `perf top` will display the functions using the most CPU time among all processes on the system, a nice leap in granularity.
+
+
+
+#### perf list
+
+The examples thus far have used the default event, run cycles. There are hundreds and perhaps thousands of events of different types. `perf list` will show them all. Following are just a few examples:
+```
+$ perf list
+ instructions [Hardware event]
+ context-switches OR cs [Software event]
+ L1-icache-loads [Hardware cache event]
+ mem_access OR cpu/mem_access/ [Kernel PMU event]
+cache:
+ pm_data_from_l2
+ [The processor's data cache was reloaded from local core's L2 due to a demand load]
+floating point:
+ pm_fxu_busy
+ [fxu0 busy and fxu1 busy]
+frontend:
+ pm_br_mpred_cmpl
+ [Number of Branch Mispredicts]
+memory:
+ pm_data_from_dmem
+ [The processor's data cache was reloaded from another chip's memory on the same Node or Group (Distant) due to a demand load]
+ pm_data_from_lmem
+ [The processor's data cache was reloaded from the local chip's Memory due to a demand load]
+ rNNN [Raw hardware event descriptor]
+ raw_syscalls:sys_enter [Tracepoint event]
+ syscalls:sys_enter_chmod [Tracepoint event]
+ sdt_libpthread:pthread_create [SDT event]
+```
+
+Events labeled as `Hardware event`, `Hardware cache event`, `Kernel PMU event`, and most (if not all) of the events under the categories like `cache`, `floating point`, `frontend`, and `memory` are hardware events counted by the hardware and triggered each time a certain count is reached. Once triggered, an entry is made into the kernel trace buffer with the current state of the associated task. `Raw hardware event` codes are alphanumeric encodings of the hardware events. These are mostly needed when the hardware is newer than the kernel and the user needs to enable events that are new for that hardware. Users will rarely, if ever, need to use raw event codes.
+
+Events labeled `Tracepoint event` are embedded in the kernel. These are triggered when that section of code is executed by the kernel. There are "syscalls" events for every system call supported by the kernel. `raw_syscalls` events are triggered for every system call. Since there is a limit to the number of events being actively traced, the `raw_syscalls` events may be more practical when a large number of system calls need to be traced.
+
+Events labeled `SDT event` are for software-defined tracepoints (SDTs). These can be embedded in application or library code and enabled as needed. When enabled, they behave just like other events: When that section of code is executed (by any task being traced on the system), an entry is made in the kernel trace buffer with the current state of the associated task. This is a very powerful capability that can prove very useful.
+
+#### perf buildid-cache and perf probe
+
+Enabling SDTs is easy. First, make the SDTs for a certain library known to `perf`:
+```
+$ perf buildid-cache -v --add /lib/powerpc64le-linux-gnu/libpthread.so.0
+$ perf list | grep libpthread
+[…]
+ sdt_libpthread:pthread_create [SDT event]
+[…]
+```
+
+Then, turn SDT definitions into available tracepoints:
+```
+$ /usr/bin/sudo perf probe sdt_libpthread:pthread_create
+Added new event:
+ sdt_libpthread:pthread_create (on %pthread_create in /lib/powerpc64le-linux-gnu/libpthread-2.27.so)
+You can now use it in all perf tools, such as:
+ perf record -e sdt_libpthread:pthread_create -aR sleep 1
+$ perf record -a -e sdt_libpthread:pthread_create ./test
+[ perf record: Woken up 1 times to write data ]
+[ perf record: Captured and wrote 0.199 MB perf.data (9 samples) ]
+```
+
+Note that any location in an application or library can be made into a tracepoint. To find functions in an application that can be made into tracepoints, use `perf probe` with `–funcs`:
+```
+$ perf probe –x ./load --funcs
+[…]
+main
+sum_add
+sum_sub
+```
+
+To enable the function `main` of the `./load` application as a tracepoint:
+```
+/usr/bin/sudo perf probe –x ./load main
+Added new event:
+ probe_load:main (on main in /home/pc/projects/load-2.1pc/load)
+You can now use it in all perf tools, such as:
+ perf record –e probe_load:main –aR sleep 1
+$ perf list | grep load:main
+ probe_load:main [Tracepoint event]
+$ perf record –e probe_load:main ./load
+[ perf record: Woken up 1 times to write data ]
+[ perf record: Captured and wrote 0.024 MB perf.data (1 samples) ]
+```
+
+#### perf script
+
+Continuing the previous example, `perf script` can be used to walk through the `perf.data` file and output the contents of each record:
+```
+$ perf script
+ Load 16356 [004] 80526.760310: probe_load:main: (4006a2)
+```
+
+### Processing perf trace data
+
+The preceding discussion and examples show that `perf` can collect the data required for system utilization analysis. However, how can that data be processed to produce the desired results?
+
+#### perf eBPF
+
+A relatively new and emerging technology with `perf` is called [eBPF][3]. BPF is an acronym for Berkeley Packet Filter, and it is a C-like language originally for, not surprisingly, network packet filtering in the kernel. eBPF is an acronym for extended BPF, a similar, but more robust C-like language based on BPF.
+
+Recent versions of `perf` can be used to incorporate compiled eBPF code into the kernel to securely and intelligently handle events for any number of purposes, with some limitations.
+
+The capability is very powerful and quite useful for real-time, continuous updates of event-related data and statistics.
+
+However, as this capability is emerging, support is mixed on current releases of Linux distributions. It's a bit complicated (or, put differently, I have not figured it out yet). It's also only for online use; there is no offline capability. For these reasons, I won't cover it further here.
+
+#### perf data file
+
+`perf record` produces a `perf.data` file. The file is a structured binary file, is not particularly well documented, has no programming interface for access, and is unclear on what compatibility guarantees exist. For these reasons, I chose not to directly use the `perf.data` file.
+
+#### perf script
+
+One of the last examples above showed how `perf script` is used for walking through the `perf.data` file and emitting basic information about each record there. This is an appropriate model for what would be needed to process the file and track the state changes and compute the statistics required for system utilization analysis.
+
+`perf script` has several modes of operation, including several higher-level scripts that come with `perf` that produce statistics based on the trace data in a `perf.data` file.
+```
+$ perf script -l
+List of available trace scripts:
+ rw-by-pid system-wide r/w activity
+ rwtop [interval] system-wide r/w top
+ wakeup-latency system-wide min/max/avg wakeup latency
+ failed-syscalls [comm] system-wide failed syscalls
+ rw-by-file r/w activity for a program, by file
+ failed-syscalls-by-pid [comm] system-wide failed syscalls, by pid
+ intel-pt-events print Intel PT Power Events and PTWRITE
+ syscall-counts-by-pid [comm] system-wide syscall counts, by pid
+ export-to-sqlite [database name] [columns] [calls] export perf data to a sqlite3 database
+ futex-contention futext contention measurement
+ sctop [comm] [interval] syscall top
+ event_analyzing_sample analyze all perf samples
+ net_dropmonitor display a table of dropped frames
+ compaction-times [-h] [-u] [-p|-pv] [-t | [-m] [-fs] [-ms]] [pid|pid-range|comm-regex] display time taken by mm compaction
+ export-to-postgresql [database name] [columns] [calls] export perf data to a postgresql database
+ stackcollapse produce callgraphs in short form for scripting use
+ netdev-times [tx] [rx] [dev=] [debug] display a process of packet and processing time
+ syscall-counts [comm] system-wide syscall counts
+ sched-migration sched migration overview
+$ perf script failed-syscalls-by-pid /bin/ls
+
+syscall errors:
+
+comm [pid] count
+------------------------------ ----------
+
+ls [18683]
+ syscall: access
+ err = ENOENT 1
+ syscall: statfs
+ err = ENOENT 1
+ syscall: ioctl
+ err = ENOTTY 3
+```
+
+What do these scripts look like? Let's find out.
+```
+$ locate failed-syscalls-by-pid
+/usr/libexec/perf-core/scripts/python/failed-syscalls-by-pid.py
+[…]
+$ rpm –qf /usr/libexec/perf-core/scripts/python/failed-syscalls-by-pid.py
+perf-4.14.0-46.el7a.x86_64
+$ $ ls /usr/libexec/perf-core/scripts
+perl python
+$ perf script -s lang
+
+Scripting language extensions (used in perf script -s [spec:]script.[spec]):
+
+ Perl [Perl]
+ pl [Perl]
+ Python [Python]
+ py [Python]
+```
+
+So, these scripts come with `perf`, and both Python and Perl are supported languages.
+
+Note that for the entirety of this content, I will refer exclusively to Python.
+
+#### perf scripts
+
+How do these scripts do what they do? Here are important extracts from `/usr/libexec/perf-core/scripts/python/failed-syscalls-by-pid.py`:
+```
+def raw_syscalls__sys_exit(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, id, ret):
+[…]
+ if ret < 0:
+[…]
+ syscalls[common_comm][common_pid][id][ret] += 1
+```
+
+The function `raw_syscalls__sys_exit` has parameters for all the data for the associated event. The rest of the function only increments a counter associated with the command, process ID, and system call. The rest of the code doesn't do that much. Most of the complexity is in the function signature for the event-handling routine.
+
+Fortunately, `perf` makes it easy to figure out the proper signatures for various tracepoint event-handling functions.
+
+#### perf script –gen-script
+
+For the `raw_syscalls` events, we can generate a trace containing just those events:
+```
+$ perf list | grep raw_syscalls
+ raw_syscalls:sys_enter [Tracepoint event]
+ raw_syscalls:sys_exit [Tracepoint event]
+$ perf record -e 'raw_syscalls:*' /bin/ls >/dev/null
+[ perf record: Woken up 1 times to write data ]
+[ perf record: Captured and wrote 0.025 MB perf.data (176 samples) ]
+```
+
+We can then have `perf` generate a script that contains sample implementations of event-handling functions for the events in the `perf.data` file:
+```
+$ perf script --gen-script python
+generated Python script: perf-script.py
+```
+
+What do we find in the script?
+```
+def raw_syscalls__sys_exit(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, id, ret):
+[…]
+def raw_syscalls__sys_enter(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, id, args):
+```
+
+Both event-handling functions are specified with their signatures. Nice!
+
+Note that this script works with `perf script –s`:
+```
+$ perf script -s ./perf-script.py
+in trace_begin
+raw_syscalls__sys_exit 7 94571.445908134 21117 ls id=0, ret=0
+raw_syscalls__sys_enter 7 94571.445942946 21117 ls id=45, args=���?bc���?�
+[…]
+```
+
+Now we have a template on which to base writing a Python script to parse the events of interest for reporting system utilization.
+
+### perf scripting
+
+The Python scripts generated by `perf script –gen-script` are not directly executable. They must be invoked by `perf`:
+```
+$ perf script –s ./perf-script.py
+```
+
+What's really going on here?
+
+ 1. First, `perf` starts. The `script` subcommand's `-s` option indicates that an external script will be used.
+
+ 2. `perf` establishes a Python runtime environment.
+
+ 3. `perf` loads the specified script.
+
+ 4. `perf` runs the script. The script can perform normal initialization and even handle command line arguments, although passing the arguments is slightly awkward, requiring a `--` separator between the arguments for `perf` and for the script:
+ ```
+ $ perf script -s ./perf-script.py -- --script-arg1 [...]
+
+ ```
+
+ 5. `perf` processes each record of the trace file, calling the appropriate event-handling function in the script. Those event-handling functions can do whatever they need to do.
+
+
+
+
+### Utilization
+
+It appears that `perf` scripting has sufficient capabilities for a workable solution. What sort of information is required to generate the statistics for system utilization?
+
+ * Task creation (`fork`, `pthread_create`)
+ * Task termination (`exit`)
+ * Task replacement (`exec`)
+ * Task migration, explicit or implicit, and current CPU
+ * Task scheduling
+ * System calls
+ * Hypervisor calls
+ * Interrupts
+
+
+
+It can be helpful to understand what portion of time a task spends in various system calls, handling interrupts, or making explicit calls out to the hypervisor. Each of these categories of time can be considered a "state" for the task, and the methods of transitioning from one state to another need to be tracked:
+
+
+
+The most important point of the diagram is that there are events for each state transition.
+
+ * Task creation: `clone` system call
+ * Task termination: `sched:sched_process_exit`
+ * Task replacement: `sched:sched_process_exec`
+ * Task migration: `sched_setaffinity` system call (explicit), `sched:sched_migrate_task` (implicit)
+ * Task scheduling: `sched:sched_switch`
+ * System calls: `raw_syscalls:sys_enter`, `raw_syscalls:sys_exit`
+ * Hypervisor calls: (POWER-specific) `powerpc:hcall_entry`, `powerpc:hcall_exit`
+ * Interrupts: `irq:irq_handler_entry`, `irq:irq_handler_exit`
+
+
+
+### The curt command for Linux
+
+`perf` provides a suitable infrastructure with which to capture the necessary data for system utilization. There are a sufficient set of events available for tracing in the Linux kernel. The Python scripting capabilities permit a powerful and flexible means of processing the trace data. It's time to write the tool.
+
+#### High-level design
+
+In processing each event, the relevant state of the affected tasks must be updated:
+
+ * New task? Create and initialize data structures to track the task's state
+ * Command
+ * Process ID
+ * Task ID
+ * Migration count (0)
+ * Current CPU
+ * New CPU for this task? Create and initialize data structures for CPU-specific data
+ * User time (0)
+ * System time (0)
+ * Hypervisor time (0)
+ * Interrupt time (0)
+ * Idle time (0)
+ * New transaction for this task? Create and initialize data structures for transaction-specific data
+ * Elapsed time (0)
+ * Count (0)
+ * Minimum (maxint), maximum (0)
+ * Existing task?
+ * Accumulate time for the previous state
+ * Transaction ending? Accumulate time for the transaction, adjust minimum, maximum values
+ * Set new state
+ * Save current time (time current state entered)
+ * Migration? Increment migration count
+
+
+
+#### High-level example
+
+For a `raw_syscalls:sys_enter` event:
+
+ * If this task has not been seen before, allocate and initialize a new task data structure
+ * If the CPU is new for this task, allocate and initialize a new CPU data structure
+ * If this system call is new for this task, allocate and initialize a new call data structure
+ * In the task data structure:
+ * Accumulate the time since the last state change in a bucket for the current state ("user")
+ * Set the new state ("system")
+ * Save the current timestamp as the start of this time period for the new state
+
+
+
+#### Edge cases
+
+##### sys_exit as a task's first event
+
+If the first event in the trace for a task is `raw_syscalls:sys_exit`:
+
+ * There is no matching `raw_syscalls:sys_enter` with which to determine the start time of this system call.
+ * The accumulated time since the start of the trace was all spent in the system call and needs to be added to the overall elapsed time spent in all calls to this system call.
+ * The elapsed time of this system call is unknown.
+ * It would be inaccurate to account for this elapsed time in the average, minimum, or maximum statistics for this system call.
+
+
+
+In this case, the tool creates a separate bucket called "pending" for time spent in the system call that cannot be accounted for in the average, minimum, or maximum.
+
+A "pending" bucket is required for all transactional events (system calls, hypervisor calls, and interrupts).
+
+##### sys_enter as a task's last event
+
+Similarly, If the last event in the trace for a task is `raw_syscalls:sys_enter`:
+
+ * There is no matching `raw_syscalls:sys_exit` with which to determine the end time of this system call.
+ * The accumulated time from the start of the system call to the end of the trace was all spent in the system call and needs to be added to the overall elapsed time spent in all calls to this system call.
+ * The elapsed time of this system call is unknown.
+ * It would be inaccurate to account for this elapsed time in the average, minimum, or maximum statistics for this system call.
+
+
+
+This elapsed time is also accumulated in the "pending" bucket.
+
+A "pending" bucket is required for all transactional events (system calls, hypervisor calls, and interrupts).
+
+Since this condition can only be discovered at the end of the trace, a final "wrap-up" step is required in the tool where the statistics for all known tasks are completed based on their final states.
+
+##### Indeterminable state
+
+It is possible that a very busy task (or a short trace) will never see an event for a task from which the task's state can be determined. For example, if only `sched:sched_switch` or `sched:sched_task_migrate` events are seen for a task, it is impossible to determine that task's state. However, the task is known to exist and to be running.
+
+Since the actual state cannot be determined, the runtime for the task is accumulated in a separate bucket, arbitrarily called "busy-unknown." For completeness, this time is also displayed in the final report.
+
+##### Invisible tasks
+
+For very, very busy tasks (or a short trace), it is possible that a task was actively running during the entire time the trace was being collected, but no events for that task appear in the trace. It was never migrated, paused, or forced to wait.
+
+Such tasks cannot be known to exist by the tool and will not appear in the report.
+
+#### curt.py Python classes
+
+##### Task
+
+ * One per task
+ * Holds all task-specific data (command, process ID, state, CPU, list of CPU data structures [see below], migration count, lists of per-call data structures [see below])
+ * Maintains task state
+
+
+
+##### Call
+
+ * One per unique transaction, per task (for example, one for the "open" system call, one for the "close" system call, one for IRQ 27, etc.)
+ * Holds call-specific data (e.g., start timestamp, count, elapsed time, minimum, maximum)
+ * Allocated as needed (lazy allocation)
+ * Stored within a task in a Python dictionary indexed by the unique identifier of the call (e.g., system call code, IRQ number, etc.)
+
+
+
+##### CPU
+
+ * One per CPU on which this task has been observed to be running
+ * Holds per-CPU task data (e.g., user time, system time, hypervisor call time, interrupt time)
+ * Allocated as needed (lazy allocation)
+ * Stored within a task in a Python dictionary indexed by the CPU number
+
+
+
+#### curt.py event processing example
+
+As previously discussed, `perf script` will iterate over all events in the trace and call the appropriate event-handling function for each event.
+
+A first attempt at an event-handling function for `sys_exit`, given the high-level example above, might be:
+```
+tasks = {}
+
+def raw_syscalls__sys_enter(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, args):
+
+ # convert the multiple timestamp values into a single value
+ timestamp = nsecs(common_secs, common_nsecs)
+
+ # find this task's data structure
+ try:
+ task = tasks[common_pid]
+ except:
+ # new task!
+ task = Task()
+ # save the command string
+ task.comm = common_comm
+ # save the new task in the global list (dictionary) of tasks
+ tasks[common_pid] = task
+
+ if common_cpu not in task.cpus:
+ # new CPU!
+ task.cpu = common_cpu
+ task.cpus[common_cpu] = CPU()
+
+ # compute time spent in the previous state ('user')
+ delta = timestamp – task.timestamp
+ # accumulate 'user' time for this task/CPU
+ task.cpus[task.cpu].user += delta
+ if id not in task.syscalls:
+ # new system call for this task!
+ task.syscalls[id] = Call()
+
+ # change task's state
+ task.mode = 'sys'
+
+ # save the timestamp for the last event (this one) for this task
+ task.timestamp = timestamp
+
+def raw_syscalls__sys_exit(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, ret):
+
+ # convert the multiple timestamp values into a single value
+ timestamp = nsecs(common_secs, common_nsecs)
+
+ # get the task data structure
+ task = tasks[common_pid]
+
+ # compute elapsed time for this system call
+ delta = task.timestamp - timestamp
+
+ # accumulate time for this task/system call
+ task.syscalls[id].elapsed += delta
+ # increment the tally for this task/system call
+ task.syscalls[id].count += 1
+ # adjust statistics
+ if delta < task.syscalls[id].min:
+ task.syscalls[id].min = delta
+ if delta > task.syscalls[id].max:
+ task.syscalls[id].max = delta
+
+ # accumulate time for this task's state on this CPU
+ task.cpus[common_cpu].system += delta
+
+ # change task's state
+ task.mode = 'user'
+
+ # save the timestamp for the last event (this one) for this task
+ task.timestamp = timestamp
+```
+
+### Handling the edge cases
+
+Following are some of the edge cases that are possible and must be handled.
+
+#### Sys_exit as first event
+
+As a system-wide trace can be started at an arbitrary time, it is certainly possible that the first event for a task is `raw_syscalls:sys_exit`. This requires adding the same code for new task discovery from the event-handling function for `raw_syscalls:sys_enter` to the handler for `raw_syscalls:sys_exit`. This:
+```
+ # get the task data structure
+ task = tasks[common_pid]
+```
+
+becomes this:
+```
+ # find this task's data structure
+ try:
+ task = tasks[common_pid]
+ except:
+ # new task!
+ task = Task()
+ # save the command string
+ task.comm = common_comm
+ # save the new task in the global list (dictionary) of tasks
+ tasks[common_pid] = task
+```
+
+Another issue is that it is impossible to properly accumulate the data for this system call since there is no timestamp for the start of the system call. The time from the start of the trace until this event has been spent by this task in the system call. It would be inaccurate to ignore this time. It would also be inaccurate to incorporate this time such that it is used to compute the average, minimum, or maximum. The only reasonable option is to accumulate this separately, calling it "pending" system time. To accurately compute this time, the timestamp of the first event of the trace must be known. Since any event could be the first event in the trace, every event must conditionally save its timestamp if it is the first event. A global variable is required:
+```
+start_timestamp = 0
+
+```
+
+And every event-handling function must conditionally save its timestamp:
+```
+ # convert the multiple timestamp values into a single value
+ timestamp = nsecs(common_secs, common_nsecs)
+
+ If start_timestamp = 0:
+ start_timestamp = timestamp
+```
+
+So, the event-handling function for `raw_syscalls:sys_exit` becomes:
+```
+def raw_syscalls__sys_exit(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, ret):
+
+ # convert the multiple timestamp values into a single value
+ timestamp = nsecs(common_secs, common_nsecs)
+
+ If start_timestamp = 0:
+ start_timestamp = timestamp
+
+ # find this task's data structure
+ try:
+ task = tasks[common_pid]
+
+ # compute elapsed time for this system call
+ delta = task.timestamp - timestamp
+
+ # accumulate time for this task/system call
+ task.syscalls[id].elapsed += delta
+ # increment the tally for this task/system call
+ task.syscalls[id].count += 1
+ # adjust statistics
+ if delta < task.syscalls[id].min:
+ task.syscalls[id].min = delta
+ if delta > task.syscalls[id].max:
+ task.syscalls[id].max = delta
+
+ except:
+ # new task!
+ task = Task()
+ # save the command string
+ task.comm = common_comm
+ # save the new task in the global list (dictionary) of tasks
+ tasks[common_pid] = task
+
+ # compute elapsed time for this system call
+ delta = start_timestamp - timestamp
+
+ # accumulate time for this task/system call
+ task.syscalls[id].pending += delta
+
+ # accumulate time for this task's state on this CPU
+ task.cpus[common_cpu].system += delta
+
+ # change task's state
+ task.mode = 'user'
+
+ # save the timestamp for the last event (this one) for this task
+ task.timestamp = timestamp
+```
+### Sys_enter as last event
+
+A similar issue to having `sys_exit` as the first event for a task is when `sys_enter` is the last event seen for a task. The time spent in the system call must be accumulated for completeness but can't accurately impact the average, minimum, nor maximum. This time will also be accumulated in for a separate "pending" state.
+
+To accurately determine the elapsed time of the pending system call, from `sys_entry` to the end of the trace period, the timestamp of the final event in the trace file is required. Unfortunately, there is no way to know which event is the last event until that event has already been processed. So, all events must save their respective timestamps in a global variable.
+
+It may be that many tasks are in the state where the last event seen for them was `sys_enter`. Thus, after the last event is processed, a final "wrap up" step is required to complete the statistics for those tasks. Fortunately, there is a `trace_end` function which is called by `perf` after the final event has been processed.
+
+Last, we need to save the `id` of the system call in every `sys_enter`.
+```
+curr_timestamp = 0
+
+def raw_syscalls__sys_enter(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, args):
+
+ # convert the multiple timestamp values into a single value
+ curr_timestamp = nsecs(common_secs, common_nsecs)
+[…]
+ task.syscall = id
+[…]
+
+def trace_end():
+ for tid in tasks.keys():
+ task = tasks[tid]
+ # if this task ended while executing a system call
+ if task.mode == 'sys':
+ # compute the time from the entry to the system call to the end of the trace period
+ delta = curr_timestamp - task.timestamp
+ # accumulate the elapsed time for this system call
+ task.syscalls[task.syscall].pending += delta
+ # accumulate the system time for this task/CPU
+ task.cpus[task.cpu].sys += delta
+```
+
+### Migrations
+
+A task migration is when a task running on one CPU is moved to another CPU. This can happen by either:
+
+ 1. Explicit request (e.g., a call to `sched_setaffinity`), or
+ 2. Implicitly by the kernel (e.g., load balancing or vacating a CPU being taken offline)
+
+
+
+When detected:
+
+ * The migration count for the task should be incremented
+ * The statistics for the previous CPU should be updated
+ * A new CPU data structure may need to be updated and initialized if the CPU is new for the task
+ * The task's current CPU is set to the new CPU
+
+
+
+For accurate statistics, task migrations must be detected as soon as possible. The first case, explicit request, happens within a system call and can be detected in the `sys_exit` event for that system call. The second case has its own event, `sched:sched_migrate_task`, so it will need a new event-handling function.
+```
+def raw_syscalls__sys_exit(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, ret):
+
+ # convert the multiple timestamp values into a single value
+ timestamp = nsecs(common_secs, common_nsecs)
+
+ If start_timestamp = 0:
+ start_timestamp = timestamp
+
+ # find this task's data structure
+ try:
+ task = tasks[common_pid]
+
+ # compute elapsed time for this system call
+ delta = task.timestamp - timestamp
+
+ # accumulate time for this task/system call
+ task.syscalls[id].elapsed += delta
+ # increment the tally for this task/system call
+ task.syscalls[id].count += 1
+ # adjust statistics
+ if delta < task.syscalls[id].min:
+ task.syscalls[id].min = delta
+ if delta > task.syscalls[id].max:
+ task.syscalls[id].max = delta
+
+ except:
+ # new task!
+ task = Task()
+ # save the command string
+ task.comm = common_comm
+ # save the new task in the global list (dictionary) of tasks
+ tasks[common_pid] = task
+
+ task.cpu = common_cpu
+
+ # compute elapsed time for this system call
+ delta = start_timestamp - timestamp
+
+ # accumulate time for this task/system call
+ task.syscalls[id].pending += delta
+
+ If common_cpu != task.cpu:
+ task.migrations += 1
+ # divide the time spent in this syscall in half...
+ delta /= 2
+ # and give have to the previous CPU, below, and half to the new CPU, later
+ task.cpus[task.cpu].system += delta
+
+ # accumulate time for this task's state on this CPU
+ task.cpus[common_cpu].system += delta
+
+ # change task's state
+ task.mode = 'user'
+
+ # save the timestamp for the last event (this one) for this task
+ task.timestamp = timestamp
+
+def sched__sched_migrate_task(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, comm, pid, prio, orig_cpu,
+ dest_cpu, perf_sample_dict):
+
+ If start_timestamp = 0:
+ start_timestamp = timestamp
+
+ # find this task's data structure
+ try:
+ task = tasks[common_pid]
+ except:
+ # new task!
+ task = Task()
+ # save the command string
+ task.comm = common_comm
+ # save the new task in the global list (dictionary) of tasks
+ tasks[common_pid] = task
+
+ task.cpu = common_cpu
+
+ If common_cpu not in task.cpus:
+ task.cpus[common_cpu] = CPU()
+
+ task.migrations += 1
+```
+
+### Task creation
+
+To accurately collect statistics for a task, it is essential to know when the task is created. Tasks can be created with `fork()`, which creates a new process, or `pthread_create()`, which creates a new task within the same process. Fortunately, both are manifested by a `clone` system call and made evident by a `sched:sched_process_fork` event. The lifetime of the task starts at the `sched_process_fork` event. The edge case that arises is that the first likely events for the new task are:
+
+ 1. `sched_switch` when the new task starts running. The new task should be considered idle at creation until this event occurs
+ 2. `sys_exit` for the `clone` system call. The initial state of the new task needs to be based on the state of the task that creates it, including being within the `clone` system call.
+
+
+
+One edge case that must be handled is if the creating task (parent) is not yet known, it must be created and initialized, and the presumption is that it has been actively running since the start of the trace.
+```
+def sched__sched_process_fork(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, parent_comm, parent_pid, child_comm, child_pid):
+ global start_timestamp, curr_timestamp
+ curr_timestamp = self.timestamp
+ if (start_timestamp == 0):
+ start_timestamp = curr_timestamp
+ # find this task's data structure
+ try:
+ task = tasks[common_pid]
+ except:
+ # new task!
+ task = Task()
+ # save the command string
+ task.comm = common_comm
+ # save the new task in the global list (dictionary) of tasks
+ tasks[common_pid] = task
+ try:
+ parent = tasks[self.parent_tid]
+ except:
+ # need to create parent task here!
+ parent = Task(start_timestamp, self.command, 'sys', self.pid)
+ parent.sched_stat = True # ?
+ parent.cpu = self.cpu
+ parent.cpus[parent.cpu] = CPU()
+ tasks[self.parent_tid] = parent
+
+ task.resume_mode = parent.mode
+ task.syscall = parent.syscall
+ task.syscalls[task.syscall] = Call()
+ task.syscalls[task.syscall].timestamp = self.timestamp
+```
+
+### Task exit
+
+Similarly, for complete and accurate task statistics, it is essential to know when a task has terminated. There's an event for that: `sched:sched_process_exit`. This one is pretty easy to handle, in that the effort is just to close out the statistics and set the mode appropriately, so any end-of-trace processing will not think the task is still active:
+```
+def sched__sched_process_exit_old(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, comm, pid, prio):
+ global start_timestamp, curr_timestamp
+ curr_timestamp = self.timestamp
+ if (start_timestamp == 0):
+ start_timestamp = curr_timestamp
+
+ # find this task's data structure
+ try:
+ task = tasks[common_pid]
+ except:
+ # new task!
+ task = Task()
+ # save the command string
+ task.comm = common_comm
+ task.timestamp = curr_timestamp
+ # save the new task in the global list (dictionary) of tasks
+ tasks[common_pid] = task
+
+ delta = timestamp – task.timestamp
+ task.sys += delta
+ task.mode = 'exit'
+```
+
+### Output
+
+What follows is an example of the report displayed by `curt`, slightly reformatted to fit on a narrower page width and with the idle-time classification data (which makes the output very wide) removed, and for brevity. Seen are two processes, 1497 and 2857. Process 1497 has two tasks, 1497 and 1523. Each task has a per-CPU summary and system-wide ("ALL" CPUs) summary. Each task's data is followed by the system call data for that task (if any), hypervisor call data (if any), and interrupt data (if any). After each process's respective tasks is a per-process summary. Process 2857 has a task 2857-0 that is the previous task image before an exec() system call replaced the process image. After all processes is a system-wide summary.
+```
+1497:
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [ 1497] X 2 0.076354 0.019563 0.000000 0.000000 0.000000 15.818719 | 0.6%
+ [ 1497] X ALL 0.076354 0.019563 0.000000 0.000000 0.000000 15.818719 | 0.6% 0
+
+ -- ( ID)name count elapsed pending average minimum maximum
+ ( 0)read 2 0.004699 0.000000 0.002350 0.002130 0.002569
+ (232)epoll_wait 1 9.968375 5.865208 9.968375 9.968375 9.968375
+
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [ 1523] InputThread 1 0.052598 0.037073 0.000000 0.000000 0.000000 15.824965 | 0.6%
+ [ 1523] InputThread ALL 0.052598 0.037073 0.000000 0.000000 0.000000 15.824965 | 0.6% 0
+
+ -- ( ID)name count elapsed pending average minimum maximum
+ ( 0)read 14 0.011773 0.000000 0.000841 0.000509 0.002185
+ ( 1)write 2 0.010763 0.000000 0.005381 0.004974 0.005789
+ (232)epoll_wait 1 9.966649 5.872853 9.966649 9.966649 9.966649
+
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [ ALL] ALL 0.128952 0.056636 0.000000 0.000000 0.000000 31.643684 | 0.6% 0
+
+2857:
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [ 2857] execs.sh 1 0.257617 0.249685 0.000000 0.000000 0.000000 0.266200 | 65.6%
+ [ 2857] execs.sh 2 0.000000 0.023951 0.000000 0.000000 0.000000 0.005728 | 80.7%
+ [ 2857] execs.sh 5 0.313509 0.062271 0.000000 0.000000 0.000000 0.344279 | 52.2%
+ [ 2857] execs.sh 6 0.136623 0.128883 0.000000 0.000000 0.000000 0.533263 | 33.2%
+ [ 2857] execs.sh 7 0.527347 0.194014 0.000000 0.000000 0.000000 0.990625 | 42.1%
+ [ 2857] execs.sh ALL 1.235096 0.658804 0.000000 0.000000 0.000000 2.140095 | 46.9% 4
+
+ -- ( ID)name count elapsed pending average minimum maximum
+ ( 9)mmap 15 0.059388 0.000000 0.003959 0.001704 0.017919
+ ( 14)rt_sigprocmask 12 0.006391 0.000000 0.000533 0.000431 0.000711
+ ( 2)open 9 2.253509 0.000000 0.250390 0.008589 0.511953
+ ( 3)close 9 0.017771 0.000000 0.001975 0.000681 0.005245
+ ( 5)fstat 9 0.007911 0.000000 0.000879 0.000683 0.001182
+ ( 10)mprotect 8 0.052198 0.000000 0.006525 0.003913 0.018073
+ ( 13)rt_sigaction 8 0.004281 0.000000 0.000535 0.000458 0.000751
+ ( 0)read 7 0.197772 0.000000 0.028253 0.000790 0.191028
+ ( 12)brk 5 0.003766 0.000000 0.000753 0.000425 0.001618
+ ( 8)lseek 3 0.001766 0.000000 0.000589 0.000469 0.000818
+
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [2857-0] perf 6 0.053925 0.191898 0.000000 0.000000 0.000000 0.827263 | 22.9%
+ [2857-0] perf 7 0.000000 0.656423 0.000000 0.000000 0.000000 0.484107 | 57.6%
+ [2857-0] perf ALL 0.053925 0.848321 0.000000 0.000000 0.000000 1.311370 | 40.8% 1
+
+ -- ( ID)name count elapsed pending average minimum maximum
+ ( 0)read 0 0.000000 0.167845 -- -- --
+ ( 59)execve 0 0.000000 0.000000 -- -- --
+
+ALL:
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [ ALL] ALL 10.790803 29.633170 0.160165 0.000000 0.137747 54.449823 | 7.4% 50
+
+ -- ( ID)name count elapsed pending average minimum maximum
+ ( 1)write 2896 1.623985 0.000000 0.004014 0.002364 0.041399
+ (102)getuid 2081 3.523861 0.000000 0.001693 0.000488 0.025157
+ (142)sched_setparam 691 7.222906 32.012841 0.024925 0.002024 0.662975
+ ( 13)rt_sigaction 383 0.235087 0.000000 0.000614 0.000434 0.014402
+ ( 8)lseek 281 0.169157 0.000000 0.000602 0.000452 0.013404
+ ( 0)read 133 2.782795 0.167845 0.020923 0.000509 1.864439
+ ( 7)poll 96 8.583354 131.889895 0.193577 0.000626 4.596280
+ ( 4)stat 93 7.036355 1.058719 0.183187 0.000981 3.661659
+ ( 47)recvmsg 85 0.146644 0.000000 0.001725 0.000646 0.019067
+ ( 3)close 79 0.171046 0.000000 0.002165 0.000428 0.020659
+ ( 9)mmap 78 0.311233 0.000000 0.003990 0.001613 0.017919
+ (186)gettid 74 0.067315 0.000000 0.000910 0.000403 0.014075
+ ( 2)open 71 3.081589 0.213059 0.184248 0.001921 0.937946
+ (202)futex 62 5.145112 164.286154 0.405566 0.000597 11.587437
+
+ -- ( ID)name count elapsed pending average minimum maximum
+ ( 12)i8042 10 0.160165 0.000000 0.016016 0.010920 0.032805
+
+Total Trace Time: 15.914636 ms
+```
+
+### Hurdles and issues
+
+Following are some of the issues encountered in the development of `curt`.
+
+#### Out-of-order events
+
+One of the more challenging issues is the discovery that events in a `perf.data` file can be out of time order. For a program trying to monitor state transitions carefully, this is a serious issue. For example, a trace could include the following sequence of events, displayed as they appear in the trace file:
+```
+time 0000: sys_enter syscall1
+time 0007: sys_enter syscall2
+time 0006: sys_exit syscall1
+time 0009: sys_exit syscall2
+```
+
+Just blindly processing these events in the order they are presented to their respective event-handling functions (in the wrong time order) will result in incorrect statistics (or worse).
+
+The most user-friendly ways to handle out-of-order events include:
+
+ * Prevent traces from having out-of-order events in the first place by changing the way `perf record` works
+ * Providing a means to reorder events in a trace file, perhaps by enhancing `perf inject`
+ * Modifying how `perf script` works to present the events to the event-handling functions in time order
+
+
+
+But user-friendly is not the same as straightforward, nor easy. Also, none of the above are in the user's control.
+
+I chose to implement a queue for incoming events that would be sufficiently deep to allow for proper reordering of all events. This required a significant redesign of the code, including implementation of classes for each event, and moving the event processing for each event type into a method in that event's class.
+
+In the redesigned code, the actual event handlers' only job is to save the relevant data from the event into an instance of the event class, queue it, then process the top (oldest in time) event from the queue:
+```
+def raw_syscalls__sys_enter(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, args):
+ event = Event_sys_enter(nsecs(common_secs,common_nsecs), common_cpu, common_pid, common_comm, id)
+ process_event(event)
+```
+
+The simple reorderable queuing mechanism is in a common function:
+```
+events = []
+n_events = 0
+def process_event(event):
+ global events,n_events,curr_timestamp
+ i = n_events
+ while i > 0 and events[i-1].timestamp > event.timestamp:
+ i = i-1
+ events.insert(i,event)
+ if n_events < params.window:
+ n_events = n_events+1
+ else:
+ event = events[0]
+ # need to delete from events list now,
+ # because event.process() could reenter here
+ del events[0]
+ if event.timestamp < curr_timestamp:
+ sys.stderr.write("Error: OUT OF ORDER events detected.\n Try increasing the size of the look-ahead window with --window=\n")
+ event.process()
+```
+
+Note that the size of the queue is configurable, primarily for performance and to limit memory consumption. The function will report when that queue size is insufficient to eliminate out-of-order events. It is worth considering whether to consider this case a catastrophic failure and elect to terminate the program.
+
+Implementing a class for each event type led to some consideration for refactoring, such that common code could coalesce into a base class:
+```
+class Event (object):
+
+ def __init__(self):
+ self.timestamp = 0
+ self.cpu = 0
+ self.tid = 0
+ self.command = 'unknown'
+ self.mode = 'unknown'
+ self.pid = 0
+
+ def process(self):
+ global start_timestamp
+
+ try:
+ task = tasks[self.tid]
+ if task.pid == 'unknown':
+ tasks[self.tid].pid = self.pid
+ except:
+ task = Task(start_timestamp, self.command, self.mode, self.pid)
+ tasks[self.tid] = task
+
+ if self.cpu not in task.cpus:
+ task.cpus[self.cpu] = CPU()
+ if task.cpu == 'unknown':
+ task.cpu = self.cpu
+
+ if self.cpu != task.cpu:
+ task.cpu = self.cpu
+ task.migrations += 1
+
+ return task
+```
+
+Then a class for each event type would be similarly constructed:
+```
+class Event_sys_enter ( Event ):
+
+ def __init__(self, timestamp, cpu, tid, comm, id, pid):
+ self.timestamp = timestamp
+ self.cpu = cpu
+ self.tid = tid
+ self.command = comm
+ self.id = id
+ self.pid = pid
+ self.mode = 'busy-unknown'
+
+ def process(self):
+ global start_timestamp, curr_timestamp
+ curr_timestamp = self.timestamp
+ if (start_timestamp == 0):
+ start_timestamp = curr_timestamp
+
+ task = super(Event_sys_enter, self).process()
+
+ if task.mode == 'busy-unknown':
+ task.mode = 'user'
+ for cpu in task.cpus:
+ task.cpus[cpu].user = task.cpus[cpu].busy_unknown
+ task.cpus[cpu].busy_unknown = 0
+
+ task.syscall = self.id
+ if self.id not in task.syscalls:
+ task.syscalls[self.id] = Call()
+
+ task.syscalls[self.id].timestamp = curr_timestamp
+ task.change_mode(curr_timestamp, 'sys')
+```
+
+Further refactoring is evident above, as well, moving the common code that updates relevant statistics based on a task's state change and the state change itself into a `change_mode` method of the `Task` class.
+
+### Start-of-trace timestamp
+
+As mentioned above, for scripts that depend on elapsed time, there should be an easier way to get the first timestamp in the trace other than forcing every event-handling function to conditionally save its timestamp as the start-of-trace timestamp.
+
+### Awkward invocation
+
+The syntax for invoking a `perf` Python script, including script parameters, is slightly awkward:
+```
+$ perf script –s ./curt.py -- --window=80
+```
+
+Also, it's awkward that `perf` Python scripts are not themselves executable.
+
+The `curt.py` script was made directly executable and will invoke `perf`, which will in turn invoke the script. Implementation is a bit confusing but it's easy to use:
+```
+$ ./curt.py --window=80
+```
+
+This script must detect when it has been directly invoked. The Python environment established by `perf` is a virtual module from which the `perf` Python scripts import:
+```
+try:
+ from perf_trace_context import *
+```
+
+If this import fails, the script was directly invoked. In this case, the script will `exec perf`, specifying itself as the script to run, and passing along any command line parameters:
+```
+except:
+ if len(params.file_or_command) == 0:
+ params.file_or_command = [ "perf.data" ]
+ sys.argv = ['perf', 'script', '-i' ] + params.file_or_command + [ '-s', sys.argv[0] ]
+ sys.argv.append('--')
+ sys.argv += ['--window', str(params.window)]
+ if params.debug:
+ sys.argv.append('--debug')
+ sys.argv += ['--api', str(params.api)]
+ if params.debug:
+ print sys.argv
+ os.execvp("perf", sys.argv)
+ sys.exit(1)
+```
+
+In this way, the script can not only be run directly, it can still be run by using the `perf script` command.
+
+#### Simultaneous event registration required
+
+An artifact of the way `perf` enables events can lead to unexpected trace data. For example, specifying:
+```
+$ perf record –a –e raw_syscalls:sys_enter –e raw_syscalls:sys_exit ./command
+```
+
+Will result in a trace file that begins with the following series of events for a single task (the `perf` command itself):
+```
+sys_enter
+sys_enter
+sys_enter
+…
+
+```
+
+This happens because `perf` will register the `sys_enter` event for every CPU on the system (because of the `-a` argument), then it will register the `sys_exit` event for every CPU. In the latter case, since the `sys_enter` event has already been enabled for each CPU, that event shows up in the trace; but since the `sys_exit` has not been enabled on each CPU until after the call returns, the `sys_exit` call does not show up in the trace. The reverse issue happens at the end of the trace file, with a series of `sys_exit` events in the trace because the `sys_enter` event has already been disabled.
+
+The solution to this issue is to group the events, which is not well documented:
+```
+$ perf record –e '{raw_syscalls:sys_enter,raw_syscalls:sys_exit}' ./command
+```
+
+With this syntax, the `sys_enter` and `sys_exit` events are enabled simultaneously.
+
+#### Awkward recording step
+
+There are a lot of different events required for computation of the full set of statistics for tasks. This leads to a very long, complicated command for recording:
+```
+$ perf record -e '{raw_syscalls:*,sched:sched_switch,sched:sched_migrate_task,sched:sched_process_exec,sched:sched_process_fork,sched:sched_process_exit,sched:sched_stat_runtime,sched:sched_stat_wait,sched:sched_stat_sleep,sched:sched_stat_blocked,sched:sched_stat_iowait,powerpc:hcall_entry,powerpc:hcall_exit}' -a *command --args*
+
+```
+
+The solution to this issue is to enable the script to perform the record step itself, by itself invoking `perf`. A further enhancement is to proceed after the recording is complete and report the statistics from that recording:
+```
+if params.record:
+ # [ed. Omitting here the list of events for brevity]
+ eventlist = '{' + eventlist + '}' # group the events
+ command = ['perf', 'record', '--quiet', '--all-cpus',
+ '--event', eventlist ] + params.file_or_command
+ if params.debug:
+ print command
+ subprocess.call(command)
+```
+
+The command syntax required to record and report becomes:
+```
+$ ./curt.py --record ./command
+```
+
+### Process IDs and perf API change
+
+Process IDs are treated a bit cavalierly by `perf` scripting. Note well above that one of the common parameters for the generated event-handling functions is named `common_pid`. This is not the process ID, but the task ID. In fact, on many current Linux-based distributions, there is no way to determine a task's process ID from within a `perf` Python script. This presents a serious problem for a script that wants to compute statistics for a process.
+
+Fortunately, in Linux kernel v4.14, an additional parameter was provided to each of the event-handling functions—`perf_sample_dict`—a dictionary from which the process ID could be extracted: (`perf_sample_dict['sample']['pid']`).
+
+Unfortunately, current Linux distributions may not have that version of the Linux kernel. If the script is written to expect that extra parameter, the script will fail and report an error:
+```
+TypeError: irq__irq_handler_exit_new() takes exactly 11 arguments (10 given)
+```
+
+Ideally, a means to automatically discover if the additional parameter is passed would be available to permit a script to easily run with both the old and new APIs and to take advantage of the new API if it is available. Unfortunately, such a means is not readily apparent.
+
+Since there is clearly value in using the new API to determine process-wide statistics, `curt` provides a command line option to use the new API. `curt` then takes advantage of Python's lazy function binding to adjust, at run-time, which API to use:
+```
+if params.api == 1:
+ dummy_dict = {}
+ dummy_dict['sample'] = {}
+ dummy_dict['sample']['pid'] = 'unknown'
+ raw_syscalls__sys_enter = raw_syscalls__sys_enter_old
+ […]
+else:
+ raw_syscalls__sys_enter = raw_syscalls__sys_enter_new
+ […]
+```
+
+This requires two functions for each event:
+```
+def raw_syscalls__sys_enter_new(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, args, perf_sample_dict):
+
+ event = Event_sys_enter(nsecs(common_secs,common_nsecs), common_cpu, common_pid, common_comm, id, perf_sample_dict['sample']['pid'])
+ process_event(event)
+
+def raw_syscalls__sys_enter_old(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, args):
+ global dummy_dict
+ raw_syscalls__sys_enter_new(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, id, args, dummy_dict)
+```
+
+Note that the event-handling function for the older API will make use of the function for the newer API, passing a statically defined dictionary containing just enough data such that accessing it as `perf_sample_dict['sample']['pid']` will work (resulting in `'unknown'`).
+
+#### Events reported on other CPUs
+
+Not all events that refer to a task are reported from a CPU on which the task is running. This could result in an artificially high migration count and other incorrect statistics. For these types of events (`sched_stat`), the event CPU is ignored.
+
+#### Explicit migrations (no sched_migrate event)
+
+While there is conveniently an event for when the kernel decides to migrate a task from one CPU to another, there is no event for when the task requests a migration on its own. These are effected by system calls (`sched_setaffinity`), so the `sys_exit` event handler must compare the event CPU to the task's CPU, and if different, presume a migration has occurred. (This is described above, but repeated here in the "issues" section for completeness.)
+
+#### Mapping system call IDs to names is architecture-specific
+
+System calls are identified in events only as unique numeric identifiers. These identifiers are not readily interpreted by humans in the report. These numeric identifiers are not readily mapped to their mnemonics because they are architecture-specific, and new system calls can be added in newer kernels. Fortunately, `perf` provides a means to map system call numeric identifiers to system call names. A simple example follows:
+```
+from Util import syscall_name
+def raw_syscalls__sys_enter(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, id, args, perf_sample_dict):
+ print "%s id=%d" % (syscall_name(id), id)
+```
+
+Unfortunately, using syscall_name introduces a dependency on the `audit` python bindings. This dependency is being removed in upstream versions of perf.
+
+#### Mapping hypervisor call IDs to names is non-existent
+
+Similar to system calls, hypervisor calls are also identified only with numeric identifiers. For IBM's POWER hypervisor, they are statically defined. Unfortunately, `perf` does not provide a means to map hypervisor call identifiers to mnemonics. `curt` includes a (hardcoded) function to do just that:
+```
+hcall_to_name = {
+ '0x4':'H_REMOVE',
+ '0x8':'H_ENTER',
+ '0xc':'H_READ',
+ '0x10':'H_CLEAR_MOD',
+[…]
+}
+
+def hcall_name(opcode):
+ try:
+ return hcall_to_name[hex(opcode)]
+ except:
+ return str(opcode)
+```
+
+### Command strings as bytearrays
+
+`perf` stores command names and string arguments in Python bytearrays. Unfortunately, printing bytearrays in Python prints every character in the bytearray—even if the string is null-terminated. For example:
+```
+$ perf record –a –e 'sched:sched_switch' sleep 3
+$ perf script –g Python
+generated Python script: perf-script.py
+$ perf script -s ./perf-script.py
+in trace_begin
+sched__sched_switch 3 664597.912692243 21223 perf prev_comm=perf^@-terminal-^@, prev_pid=21223, prev_prio=120, prev_state=, next_comm=migration/3^@^@^@^@^@, next_pid=23, next_prio=0
+[…]
+```
+
+One solution is to truncate the length of these bytearrays based on null termination, as needed before printing:
+```
+def null(ba):
+ null = ba.find('\x00')
+ if null >= 0:
+ ba = ba[0:null]
+ return ba
+
+def sched__sched_switch(event_name, context, common_cpu,
+ common_secs, common_nsecs, common_pid, common_comm,
+ common_callchain, prev_comm, prev_pid, prev_prio, prev_state,
+ next_comm, next_pid, next_prio, perf_sample_dict):
+
+ print "prev_comm=%s, prev_pid=%d, prev_prio=%d, " \
+ "prev_state=%s, next_comm=%s, next_pid=%d, " \
+ "next_prio=%d" % \
+ (null(prev_comm), prev_pid, prev_prio,
+ flag_str("sched__sched_switch", "prev_state", prev_state),
+ null(next_comm), next_pid, next_prio)
+```
+
+Which nicely cleans up the output:
+```
+sched__sched_switch 3 664597.912692243 21223 perf prev_comm=perf, prev_pid=21223, prev_prio=120, prev_state=, next_comm=migration/3, next_pid=23, next_prio=0
+```
+
+### Dynamic mappings, like IRQ number to name
+
+Dissimilar to system calls and hypervisor calls, interrupt numbers (IRQs) are dynamically assigned by the kernel on demand, so there can't be a static table mapping an IRQ number to a name. Fortunately, `perf` passes the name to the event's `irq_handler_entry` routine. This allows a script to create a dictionary that maps the IRQ number to a name:
+```
+irq_to_name = {}
+def irq__irq_handler_entry_new(event_name, context, common_cpu, common_secs, common_nsecs, common_pid, common_comm, common_callchain, irq, name, perf_sample_dict):
+ irq_to_name[irq] = name
+ event = Event_irq_handler_entry(nsecs(common_secs,common_nsecs), common_cpu, common_pid, common_comm, irq, name, getpid(perf_sample_dict))
+ process_event(event)
+```
+
+Somewhat oddly, `perf` does not pass the name to the `irq_handler_exit` routine. So, it is possible that a trace may only see an `irq_handler_exit` for an IRQ and must be able to tolerate that. Here, instead of mapping the IRQ to a name, the IRQ number is returned as a string instead:
+```
+def irq_name(irq):
+ if irq in irq_to_name:
+ return irq_to_name[irq]
+ return str(irq)
+```
+#### Task 0
+Task 0 shows up everywhere. It's not a real task. It's a substitute for the "idle" state. It's the task ID given to the `sched_switch` event handler when the CPU is going to (or coming from) the "idle" state. It's often the task that is "interrupted" by interrupts. Tracking the statistics for task 0 as if it were a real task would not make sense. Currently, `curt` ignores task 0. However, this loses some information, like some time spent in interrupt processing. `curt` should, but currently doesn't, track interesting (non-idle) time for task 0.
+
+#### Spurious sched_migrate_task events (same CPU)
+
+Rarely, a `sched_migrate_task` event occurs in which the source and target CPUs are the same. In other words, the task is not migrated. To avoid artificially inflated migration counts, this case must be explicitly ignored:
+```
+class Event_sched_migrate_task (Event):
+ def process(self):
+[…]
+ if self.cpu == self.dest_cpu:
+ return
+```
+
+#### exec
+
+The semantics of the `exec` system call are that the image of the current process is replaced by a completely new process image without changing the process ID. This is awkward for tracking the statistics of a process (really, a task) based on the process (task) ID. The change is significant enough that the statistics for each task should be accumulated separately, so the current task's statistics need to be closed out and a new set of statistics should be initialized. The challenge is that both the old and new tasks have the same process (task) ID. `curt` addresses this by tagging the task's task ID with a numeric suffix:
+```
+class Event_sched_process_exec (Event):
+ def process(self):
+ global start_timestamp, curr_timestamp
+ curr_timestamp = self.timestamp
+ if (start_timestamp == 0):
+ start_timestamp = curr_timestamp
+
+ task = super(Event_sched_process_exec, self).process()
+
+ new_task = Task(self.timestamp, self.command, task.mode, self.pid)
+ new_task.sched_stat = True
+ new_task.syscall = task.syscall
+ new_task.syscalls[task.syscall] = Call()
+ new_task.syscalls[task.syscall].timestamp = self.timestamp
+
+ task.change_mode(curr_timestamp, 'exit')
+
+ suffix=0
+ while True:
+ old_tid = str(self.tid)+"-"+str(suffix)
+ if old_tid in tasks:
+ suffix += 1
+ else:
+ break
+
+ tasks[old_tid] = tasks[self.tid]
+
+ del tasks[self.tid]
+
+ tasks[self.tid] = new_task
+```
+
+This will clearly separate the statistics for the different process images. In the example below, the `perf` command (task "9614-0") `exec`'d `exec.sh` (task "9614-1"), which in turn `exec`'d itself (task "9614"):
+```
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [ 9614] execs.sh 4 1.328238 0.485604 0.000000 0.000000 0.000000 2.273230 | 44.4%
+ [ 9614] execs.sh 7 0.000000 0.201266 0.000000 0.000000 0.000000 0.003466 | 98.3%
+ [ 9614] execs.sh ALL 1.328238 0.686870 0.000000 0.000000 0.000000 2.276696 | 47.0% 1
+
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [9614-0] perf 3 0.000000 0.408588 0.000000 0.000000 0.000000 2.298722 | 15.1%
+ [9614-0] perf 4 0.059079 0.028269 0.000000 0.000000 0.000000 0.611355 | 12.5%
+ [9614-0] perf 5 0.000000 0.067626 0.000000 0.000000 0.000000 0.004702 | 93.5%
+ [9614-0] perf ALL 0.059079 0.504483 0.000000 0.000000 0.000000 2.914779 | 16.2% 2
+
+-- [ task] command cpu user sys irq hv busy idle | util% moves
+ [9614-1] execs.sh 3 1.207972 0.987433 0.000000 0.000000 0.000000 2.435908 | 47.4%
+ [9614-1] execs.sh 4 0.000000 0.341152 0.000000 0.000000 0.000000 0.004147 | 98.8%
+ [9614-1] execs.sh ALL 1.207972 1.328585 0.000000 0.000000 0.000000 2.440055 | 51.0% 1
+```
+
+#### Distribution support
+
+Surprisingly, there is currently no support for `perf`'s Python bindings in Ubuntu. [Follow the saga][4] for more detail.
+
+#### Limit on number of traced events
+
+As `curt` gets more sophisticated, it is likely that more and more events may be required to be included in the trace file. `perf` currently requires one file descriptor per event per CPU. This becomes a problem when the maximum number of open file descriptors is not a large multiple of the number of CPUs on the system. On systems with large numbers of CPUs, this quickly becomes a problem. For example, the default maximum number of open file descriptors is often 1,024. An IBM POWER8 system with four sockets may have 12 cores per socket and eight threads (CPUs) per core. Such a system has 4 * 12 * 8 = 392 CPUs. In that case, `perf` could trace only about two events! A workaround is to (significantly) increase the maximum number of open file descriptors (`ulimit –n` if the system administrator has configured the hard limits high enough; or the administrator can set the limits higher in `/etc/security/limits.conf` for `nofile`).
+
+### Summary
+
+I hope this article shows the power of `perf`—and specifically the utility and flexibility of the Python scripting enabled with `perf`—to perform sophisticated processing of kernel trace data. Also, it shows some of the issues and edge cases that can be encountered when the boundaries of such technologies are tested.
+
+Please feel free to download and make use of the `curt` tool described here, report problems, suggest improvements, or contribute code of your own on the [`curt` GitHub page][5].
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/fun-perf-and-python
+
+作者:[Paul Clarke][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/thinkopenly
+[1]:https://2018.texaslinuxfest.org/
+[2]:https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.cmds1/curt.htm
+[3]:https://opensource.com/article/17/9/intro-ebpf
+[4]:https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1707875
+[5]:https://github.com/open-power-sdk/curt
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
new file mode 100644
index 0000000000..d305b716d6
--- /dev/null
+++ b/sources/tech/20180730 50 Best Ubuntu Apps You Should Be Using Right Now.md
@@ -0,0 +1,499 @@
+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/20180730 A single-user, lightweight OS for your next home project - Opensource.com.md b/sources/tech/20180730 A single-user, lightweight OS for your next home project - Opensource.com.md
new file mode 100644
index 0000000000..a4dbfb9e12
--- /dev/null
+++ b/sources/tech/20180730 A single-user, lightweight OS for your next home project - Opensource.com.md
@@ -0,0 +1,65 @@
+A single-user, lightweight OS for your next home project | Opensource.com
+======
+
+
+What on earth is RISC OS? Well, it's not a new kind of Linux. And it's not someone's take on Windows. In fact, released in 1987, it's older than either of these. But you wouldn't necessarily realize it by looking at it.
+
+The point-and-click graphic user interface features a pinboard and an icon bar across the bottom for your active applications. So, it looks eerily like Windows 95, eight years before it happened.
+
+This OS was originally written for the [Acorn Archimedes][1] . The Acorn RISC Machines CPU in this computer was completely new hardware that needed completely new software to run on it. This was the original operating system for the ARM chip, long before anyone had thought of Android or [Armbian][2]
+
+And while the Acorn desktop eventually faded to obscurity, the ARM chip went on to conquer the world. And here, RISC OS has always had a niche—often in embedded devices, where you'd never actually know it was there. RISC OS was, for a long time, a completely proprietary operating system. But in recent years, the owners have started releasing the source code to a project called [RISC OS Open][3].
+
+### 1\. You can install it on your Raspberry Pi
+
+The Raspberry Pi's official operating system, [Raspbian][4], is actually pretty great (but if you aren't interested in tinkering with novel and different things in tech, you probably wouldn't be fiddling with a Raspberry Pi in the first place). Because RISC OS is written specifically for ARM, it can run on all kinds of small-board computers, including every model of Raspberry Pi.
+
+### 2\. It's super lightweight
+
+The RISC OS installation on my Raspberry Pi takes up a few hundred megabytes—and that's after I've loaded dozens of utilities and games. Most of these are well under a megabyte.
+
+If you're really on a diet, the RISC OS Pico will fit on a 16MB SD card. This is perfect if you're hacking something to go in an embedded system or IoT project. Of course, 16MB is actually a fair bit more than the 512KB ROM chip squeezed into the old Archimedes. But I guess with 30 years of progress in memory technology, it's okay to stretch your legs just a little a bit.
+
+### 3\. It's excellent for retro gaming
+
+When the Archimedes was in its prime, the ARM CPU was several times faster than the Motorola 68000 in the Apple Macintosh and Commodore Amiga, and it totally smoked that new 386, too. This made it an attractive platform for game developers who wanted to strut their stuff with the most powerful desktop computer on the planet.
+
+Many of the rights holders to these games have been generous enough to give permission for hobbyists to download their old work for free. And while RISC OS and the hardware has moved on, with a very small amount of fiddling you can get them to run.
+
+If you're interested in exploring this, [here's a guide][5] to getting these games working on your Raspberry Pi.
+
+### 4\. It's got BBC BASIC
+
+Press F12 to go to the command line, type `*BASIC`, and you get a full BBC BASIC interpreter, just like the old days.
+
+For those who weren't around for it in the 80s, let me explain: BBC BASIC was the first ever programming language for so many of us back in the day, for the excellent reason that it was specifically designed to teach children how to code. There were mountains of books and magazine articles that taught us to code our own simple but highly playable games.
+
+Decades later, coding your own game in BBC BASIC is still a great project for a technically minded kid who wants something to do during school holidays. But few kids have a BBC micro at home anymore. So what should they run it on?
+
+Well, there are interpreters you can run on just about every home computer, but that's not helpful when someone else needs to use it. So why not a Raspberry Pi with RISC OS installed?
+
+### 5\. It's a simple, single-user operating system
+
+RISC OS is not like Linux, with its user and superuser access. It has one user who has full access to the whole machine. So it's probably not the best daily driver to deploy across an enterprise, or even to give to granddad to do his banking. But if you're looking for something to hack and tinker with, it's absolutely fantastic. There isn't all that much between you and the bare metal, so you can just tuck right in.
+
+### Further reading
+
+If you want to learn more about this operating system, check out [RISC OS Open][3], or just flash an image to a card and start using it.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/gentle-intro-risc-os
+
+作者:[James Mawson][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/dxmjames
+[1]:https://en.wikipedia.org/wiki/Acorn_Archimedes
+[2]:https://www.armbian.com/
+[3]:https://www.riscosopen.org/content/
+[4]:https://www.raspbian.org/
+[5]:https://www.riscosopen.org/wiki/documentation/show/Introduction%20to%20RISC%20OS
diff --git a/sources/tech/20180731 What-s in a container image- Meeting the legal challenges.md b/sources/tech/20180731 What-s in a container image- Meeting the legal challenges.md
new file mode 100644
index 0000000000..dafb058a42
--- /dev/null
+++ b/sources/tech/20180731 What-s in a container image- Meeting the legal challenges.md
@@ -0,0 +1,64 @@
+What's in a container image: Meeting the legal challenges
+======
+
+
+[Container][1] technology has, for many years, been transforming how workloads in data centers are managed and speeding the cycle of application development and deployment.
+
+In addition, container images are increasingly used as a distribution format, with container registries a mechanism for software distribution. Isn't this just like packages distributed using package management tools? Not quite. While container image distribution is similar to RPMs, DEBs, and other package management systems (for example, storing and distributing archives of files), the implications of container image distribution are more complicated. It is not the fault of container technology itself; rather, it's because container distribution is used differently than package management systems.
+
+Talking about the challenges of license compliance for container images, [Dirk Hohndel][2], chief open source officer at VMware, pointed out that the content of a container image is more complex than most people expect, and many readily available images have been built in surprisingly cavalier ways. (See the [LWN.net article][3] by Jake Edge about a talk Dirk gave in April.)
+
+Why is it hard to understand the licensing of container images? Shouldn't there just be a label for the image ("the license is X")? In the [Open Container Image Format Specification][4] , one of the pre-defined annotation keys is "org.opencontainers.image.licenses," which is described as "License(s) under which contained software is distributed as an SPDX License Expression." But that doesn't contemplate the complexity of a container image–while very simple images are built from tens of components, images are often built from hundreds of components. An [SPDX License Expression][5] is most frequently used to convey the licensing for a single source file. Such expressions can handle more than one license, such as "GPL-2.0 OR BSD-3-Clause" (see, for example, [Appendix IV][6] of version 2.1 of the SPDX specification). But the licensing for a typical container image is, typically, much more complicated.
+
+In talking about container-related technology, the term "[container][7]" can lead to confusion. A container does not refer to the containment of files for storing or transferring. Rather, it refers to using features built into the kernel (such as cgroups and namespaces) to present a sort of "contained" experience to code running on the kernel. In other words, the containment to which "container" refers is an execution experience, not a distribution experience. The set of files to be laid out in a file system as the basis for an executing container is typically distributed in what is known as a "container image," sometimes confusingly referred to simply as a container, thereby awkwardly overloading the term "container."
+
+In understanding software distribution via container images, I believe it is useful to consider two separate factors:
+
+ * **Diversity of content:** The basic unit of software distribution (a container image) includes a larger quantity and diversity of content than in the basic unit of distribution in typical software distribution mechanisms.
+ * **Use model:** The nature of widely used tooling fosters the use of a registry, which is often publicly available, in the typical workflow.
+
+
+
+### Diversity of content
+
+When talking about a particular container image, the focus of attention is often on a particular software component (for example, a database or the code that implements one specific service). However, the container image includes a much larger collection of software. In fact, even the developer who created the image may have only a superficial understanding of and/or interest in most of the components in the image. With other distribution mechanisms, those other pieces of software would be identified as dependencies, and users of the software might be directed elsewhere for expertise on those components. In a container, the individual who acquires the container image isn't aware of those additional components that play supporting roles to the featured component.
+
+#### The unit of distribution: user-driven vs. factory-driven
+
+For container images, the distribution unit is user-driven, not factory-driven. Container images are a great tool for reducing the burden on software consumers. With a container image, the image's consumer can focus on the application of interest; the image's builder can take care of the dependencies and configuration. This simplification can be a huge benefit.
+
+When the unit of software is driven by the "factory," the user bears a greater responsibility for building a platform on which to run the software of interest, assembling the correct versions of the dependencies, and getting all the configuration details right. The unit of distribution in a package management system is a modular unit, rather than a complete solution. This unit facilitates building and maintaining a flow of components that are flexible enough to be assembled into myriad solutions. Note that because of this unit, a package maintainer will typically be far more familiar with the content of the packages than someone who builds containers. A person building a container may have a detailed understanding of the container's featured components, but limited familiarity with the image's supporting components.
+
+Packages, package management system tools, package maintenance processes, and package maintainers are incredibly underappreciated. They have been central to delivery of a large variety of software over the last two decades. While container images are playing a growing role, I don't expect the importance of package management systems to fade anytime soon. In fact, the bulk of the content in container images benefits from being built from such packages.
+
+In understanding container images, it is important to appreciate how distribution via such images has different properties than distribution of packages. Much of the content in images is built from packages, but the image's consumer may not know what packages are included or other package-level information. In the future, a variety of techniques may be used to build containers, e.g., directly from source without involvement of a package maintainer.
+
+### Use models
+
+What about reports that so many container images are poorly built? In part, the volume of casually built images is because of container tools that facilitate a workflow to make images publicly available. When experimenting with container tools and moving to a workflow that extends beyond a laptop, the tools expect you to have a repository where multiple machines can pull container images (a container registry). You could spin up your own. Some widely used tools make it easy to use an existing registry that is available at no cost, provided the images are publicly available. This makes many casually built images visible, even those that were never intended to be maintained or updated.
+
+By comparison, how often do you see developers publishing RPMs of their early explorations? RPMs resulting from experimentation by random developers are not ending up in the major package repositories.
+
+Or consider someone experimenting with the latest machine learning frameworks. In the past, a researcher might have shared only analysis results. Now, they can share a full analytical software configuration by publishing a container image. This could be a great benefit to other researchers. However, those browsing a container registry could be confused by the ready-to-run nature of such images. It is important to distinguish between an image built for one individual's exploration and an image that was assembled and tested with broad use in mind.
+
+Be aware that container images include supporting software, not just the featured software; a container image distributes a collection of software. If you are building upon or otherwise using images built by others, be aware of how that image was built and consider your level of confidence in the image's source.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/7/whats-container-image-meeting-legal-challenges
+
+作者:[Scott Peterson][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/skpeterson
+[1]:https://opensource.com/resources/what-are-linux-containers
+[2]:https://www.linkedin.com/in/dirkhohndel
+[3]:https://lwn.net/Articles/752982/
+[4]:https://github.com/opencontainers/image-spec/blob/master/spec.md
+[5]:https://spdx.org/
+[6]:https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60
+[7]:https://opensource.com/bus/16/8/introduction-linux-containers-and-image-signing
diff --git a/sources/tech/20180801 5 of the Best Linux Games to Play in 2018.md b/sources/tech/20180801 5 of the Best Linux Games to Play in 2018.md
new file mode 100644
index 0000000000..a0580434ec
--- /dev/null
+++ b/sources/tech/20180801 5 of the Best Linux Games to Play in 2018.md
@@ -0,0 +1,83 @@
+5 of the Best Linux Games to Play in 2018
+======
+
+
+
+Linux may not be establishing itself as the gamer’s platform of choice any time soon – the lack of success with Valve’s Steam Machines seems a poignant reminder of that – but that doesn’t mean that the platform isn’t steadily growing with its fair share of great games.
+
+From indie hits to glorious RPGs, 2018 has already been a solid year for Linux games. Here we’ve listed our five favourites so far.
+
+Looking for great Linux games but don’t want to splash the cash? Look to our list of the best [free Linux games][1] for guidance!
+
+### 1. Pillars of Eternity II: Deadfire
+
+![best-linux-games-2018-pillars-of-eternity-2-deadfire][2]
+
+One of the titles that best represents the cRPG revival of recent years makes your typical Bethesda RPG look like a facile action-adventure. The latest entry in the majestic Pillars of Eternity series has a more buccaneering slant as you sail with a crew around islands filled with adventures and peril.
+
+Adding naval combat to the mix, Deadfire continues with the rich storytelling and excellent writing of its predecessor while building on those beautiful graphics and hand-painted backgrounds of the original game.
+
+This is a deep and unquestionably hardcore RPG that may cause some to bounce off it, but those who take to it will be absorbed in its world for months.
+
+### 2. Slay the Spire
+
+![best-linux-games-2018-slay-the-spire][3]
+
+Still in early access, but already one of the best games of the year, Slay the Spire is a deck-building card game that’s embellished by a vibrant visual style and rogue-like mechanics that’ll leave you coming back for more after each infuriating (but probably deserved) death.
+
+With endless card combinations and a different layout each time you play, Slay the Spire feels like the realisation of all the best systems that have been rocking the indie scene in recent years – card games and a permadeath adventure rolled into one.
+
+And we repeat that it’s still in early access, so it’s only going to get better!
+
+### 3. Battletech
+
+![best-linux-games-2018-battletech][4]
+
+As close as we get on this list to a “blockbuster” game, Battletech is an intergalactic wargame (based on a tabletop game) where you load up a team of Mechs and guide them through a campaign of rich, turn-based battles.
+
+The action takes place across a range of terrain – from frigid wastelands to golden sun-soaked climes – as you load your squad of four with hulking hot weaponry, taking on rival squads. If this sounds a little “MechWarrior” to you, then you’re thinking along the right track, albeit this one’s more focused on the tactics than outright action.
+
+Alongside a campaign that sees you navigate your way through a cosmic conflict, the multiplayer mode is also likely to consume untold hours of your life.
+
+### 4. Dead Cells
+
+![best-linux-games-2018-dead-cells][5]
+
+This one deserves highlighting as the combat-platformer of the year. With its rogue-lite structure, Dead Cells throws you into a dark (yet gorgeously coloured) world where you slash and dodge your way through procedurally-generated levels. It’s a bit like a 2D Dark Souls, if Dark Souls were saturated in vibrant neon colours.
+
+Dead Cells can be merciless, but its precise and responsive controls ensure that you only ever have yourself to blame for failure, and its upgrades system that carries over between runs ensures that you always have some sense of progress.
+
+Dead Cells is a zenith of pixel-game graphics, animations and mechanics, a timely reminder of just how much can be achieved without the excesses of 3D graphics.
+
+### 5. Iconoclasts
+
+![best-linux-games-2018-iconoclasts][6]
+
+A little less known than some of the above, this is still a lovely game that could be seen as a less foreboding, more cutesy alternative to Dead Cells. It casts you as Robin, a girl who’s cast out as a fugitive after finding herself at the wrong end of the twisted politics of an alien world.
+
+It’s a good plot, even though your role in it is mainly blasting your way through the non-linear levels. Robin acquires all kinds of imaginative upgrades, the most crucial of which is her wrench, which you use to do everything from deflecting projectiles to solving the clever little environmental puzzles.
+
+Iconoclasts is a joyful, vibrant platformer, borrowing from greats like Megaman for its combat and Metroid for its exploration. You can do a lot worse than take inspiration from those two classics.
+
+### Conclusion
+
+That’s it for our picks of the best Linux games to have come out in 2018. Have you dug up any gaming gems that we’ve missed? Let us know in the comments!
+
+--------------------------------------------------------------------------------
+
+via: https://www.maketecheasier.com/best-linux-games/
+
+作者:[Robert Zak][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://www.maketecheasier.com/author/robzak/
+[1]:https://www.maketecheasier.com/open-source-linux-games/
+[2]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-pillars-of-eternity-2-deadfire.jpg (best-linux-games-2018-pillars-of-eternity-2-deadfire)
+[3]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-slay-the-spire.jpg (best-linux-games-2018-slay-the-spire)
+[4]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-battletech.jpg (best-linux-games-2018-battletech)
+[5]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-dead-cells.jpg (best-linux-games-2018-dead-cells)
+[6]:https://www.maketecheasier.com/assets/uploads/2018/07/best-linux-games-2018-iconoclasts.jpg (best-linux-games-2018-iconoclasts)
diff --git a/sources/tech/20180801 Getting started with Standard Notes for encrypted note-taking.md b/sources/tech/20180801 Getting started with Standard Notes for encrypted note-taking.md
new file mode 100644
index 0000000000..a2845eef65
--- /dev/null
+++ b/sources/tech/20180801 Getting started with Standard Notes for encrypted note-taking.md
@@ -0,0 +1,299 @@
+Getting started with Standard Notes for encrypted note-taking
+======
+
+
+
+[Standard Notes][1] is a simple, encrypted notes app that aims to make dealing with your notes the easiest thing you'll do all day. When you sign up for a free sync account, your notes are automatically encrypted and seamlessly synced with all your devices.
+
+There are two key factors that differentiate Standard Notes from other, commercial software solutions:
+
+ 1. The server and client are both completely open source.
+ 2. The company is built on sustainable business practices and focuses on product development.
+
+
+
+When you combine open source with ethical business practices, you get a software product that has the potential to serve you for decades. You start to feel ownership in the product rather than feeling like just another transaction for an IPO-bound company.
+
+In this article, I’ll describe how to deploy your own Standard Notes open source syncing server on a Linux machine. You’ll then be able to use your server with our published applications for Linux, Windows, Android, Mac, iOS, and the web.
+
+If you don’t want to host your own server and are ready to start using Standard Notes right away, you can use our public syncing server. Simply head on over to [Standard Notes][1] to get started.
+
+### Hosting your own Standard Notes server
+
+Get the [Standard File Rails app][2] running on your Linux box and expose it via [NGINX][3] or any other web server.
+
+### Getting started
+
+These instructions are based on setting up our syncing server on a fresh [CentOS][4]-like installation. You can use a hosting service like [AWS][5] or [DigitalOcean][6] to launch your server, or even run it locally on your own machine.
+
+ 1. Update your system:
+
+```
+ sudo yum update
+
+```
+
+ 2. Install [RVM][7] (Ruby Version Manager):
+
+```
+ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
+ \curl -sSL https://get.rvm.io | bash -s stable
+
+```
+
+ 3. Begin using RVM in current session:
+```
+ source /home/ec2-user/.rvm/scripts/rvm
+
+```
+
+ 4. Install [Ruby][8]:
+
+```
+ rvm install ruby
+
+```
+
+This should install the latest version of Ruby (2.3 at the time of this writing.)
+
+Note that at least Ruby 2.2.2 is required for Rails 5.
+
+ 5. Use Ruby:
+```
+ rvm use ruby
+
+```
+
+ 6. Install [Bundler][9]:
+
+```
+ gem install bundler --no-ri --no-rdoc
+
+```
+
+ 7. Install [mysql-devel][10]:
+```
+ sudo yum install mysql-devel
+
+```
+
+ 8. Install [MySQL][11] (optional; you can also use a hosted db through [Amazon RDS][12], which is recommended):
+```
+ sudo yum install mysql56-server
+
+ sudo service mysqld start
+
+ sudo mysql_secure_installation
+
+ sudo chkconfig mysqld on
+
+```
+
+Create a database:
+
+```
+ mysql -u root -p
+
+ > create database standard_file;
+
+ > quit;
+
+```
+
+ 9. Install [Passenger][13]:
+```
+ sudo yum install rubygems
+
+ gem install rubygems-update --no-rdoc --no-ri
+
+ update_rubygems
+
+ gem install passenger --no-rdoc --no-ri
+
+```
+
+ 10. Remove system NGINX installation if installed (you’ll use Passenger’s instead):
+```
+ sudo yum remove nginx
+ sudo rm -rf /etc/nginx
+```
+
+ 11. Configure Passenger:
+```
+ sudo chmod o+x "/home/ec2-user"
+
+ sudo yum install libcurl-devel
+
+ rvmsudo passenger-install-nginx-module
+
+ rvmsudo passenger-config validate-install
+
+```
+
+ 12. Install Git:
+```
+ sudo yum install git
+
+```
+
+ 13. Set up HTTPS/SSL for your server (free using [Let'sEncrypt][14]; required if using the secure client on [https://app.standardnotes.org][15]):
+```
+ sudo chown ec2-user /opt
+
+ cd /opt
+
+ git clone https://github.com/letsencrypt/letsencrypt
+
+ cd letsencrypt
+
+```
+
+Run the setup wizard:
+```
+ ./letsencrypt-auto certonly --standalone --debug
+
+```
+
+Note the location of the certificates, typically `/etc/letsencrypt/live/domain.com/fullchain.pem`
+
+ 14. Configure NGINX:
+```
+ sudo vim /opt/nginx/conf/nginx.conf
+
+```
+
+Add this to the bottom of the file, inside the last curly brace:
+```
+ server {
+
+ listen 443 ssl default_server;
+
+ ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
+
+ ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
+
+ server_name domain.com;
+
+ passenger_enabled on;
+
+ passenger_app_env production;
+
+ root /home/ec2-user/ruby-server/public;
+
+ }
+
+```
+
+ 15. Make sure you are in your home directory and clone the Standard File [ruby-server][2] project:
+```
+ cd ~
+
+ git clone https://github.com/standardfile/ruby-server.git
+
+ cd ruby-server
+
+```
+
+ 16. Set up project:
+```
+ bundle install
+
+ bower install
+
+ rails assets:precompile
+
+```
+
+ 17. Create a .env file for your environment variables. The Rails app will automatically load these when it starts.
+
+```
+ vim .env
+
+```
+
+Insert:
+```
+ RAILS_ENV=production
+
+ SECRET_KEY_BASE=use "bundle exec rake secret"
+
+
+
+ DB_HOST=localhost
+
+ DB_PORT=3306
+
+ DB_DATABASE=standard_file
+
+ DB_USERNAME=root
+
+ DB_PASSWORD=
+
+```
+
+ 18. Setup database:
+```
+ rails db:migrate
+
+```
+
+ 19. Start NGINX:
+```
+ sudo /opt/nginx/sbin/nginx
+
+```
+
+Tip: you will need to restart NGINX whenever you make changes to your environment variables or the NGINX configuration:
+```
+ sudo /opt/nginx/sbin/nginx -s reload
+
+```
+
+ 20. You’re done!
+
+
+
+
+### Using your new server
+
+Now that you have your server running, you can plug it into any of the Standard Notes applications and sign into it.
+
+**On the Standard Notes web or desktop app:**
+
+Click Account, then Register. Choose "Advanced Options" and you’ll see a field for Sync Server. Enter your server’s URL here.
+
+**On the Standard Notes Android or iOS app:**
+
+Open the Settings window, click "Advanced Options" when signing in or registering, and enter your server URL in the Sync Server field.
+
+For help or questions with your Standard Notes server, join our [Slack group][16] in the #dev channel, or visit our [help page][17] for frequently asked questions and other topics.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/getting-started-standard-notes
+
+作者:[Mo Bitar][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/mobitar
+[1]:https://standardnotes.org/
+[2]:https://github.com/standardfile/ruby-server
+[3]:https://www.nginx.com/
+[4]:https://www.centos.org/
+[5]:https://aws.amazon.com/
+[6]:https://www.digitalocean.com/
+[7]:https://rvm.io/
+[8]:https://www.ruby-lang.org/en/
+[9]:https://bundler.io/
+[10]:https://rpmfind.net/linux/rpm2html/search.php?query=mysql-devel
+[11]:https://www.mysql.com/
+[12]:https://aws.amazon.com/rds/
+[13]:https://www.phusionpassenger.com/
+[14]:https://letsencrypt.org/
+[15]:https://app.standardnotes.org/
+[16]:https://standardnotes.org/slack
+[17]:https://standardnotes.org/help
diff --git a/sources/tech/20180801 Hiri is a Linux Email Client Exclusively Created for Microsoft Exchange.md b/sources/tech/20180801 Hiri is a Linux Email Client Exclusively Created for Microsoft Exchange.md
new file mode 100644
index 0000000000..dbe5d042f9
--- /dev/null
+++ b/sources/tech/20180801 Hiri is a Linux Email Client Exclusively Created for Microsoft Exchange.md
@@ -0,0 +1,114 @@
+Hiri is a Linux Email Client Exclusively Created for Microsoft Exchange
+======
+Previously, I have written about the email services [Protonmail][1] and [Tutanota][2] on It’s FOSS. And though I liked both of those email providers very much, some of us couldn’t possibly use these email services exclusively. If you are like me and you have an email address provided for you by your work, then you understand what I am talking about.
+
+Some of us use [Thunderbird][3] for these types of use cases, while others of us use something like [Geary][4] or even [Mailspring][5]. But for those of us who have to deal with [Microsoft Exchange Servers][6], none of these offer seamless solutions on Linux for our work needs.
+
+This is where [Hiri][7] comes in. We have already featured Hiri on our list of [best email clients for Linux][8], but we thought it was about time for an in-depth review.
+
+FYI, Hiri is neither free nor open source software.
+
+### Reviewing Hiri email client on Linux
+
+![Hiri email client review][9]
+
+According to their website, Hiri not only supports Microsoft Exchange and Office 365 accounts, it was exclusively “built for the Microsoft email ecosystem.”
+
+Based in Dublin, Ireland, Hiri has raised $2 million in funding. They have been in the business for almost five years but started supporting Linux only last year. The support for Linux has brought Hiri a considerable amount of success.
+
+I have been using Hiri for a week as of yesterday, and I have to say, I have been very pleased with my experience…for the most part.
+
+#### Hiri features
+
+Some of the main features of Hiri are:
+
+ * Cross-platform application available for Linux, macOS and Windows
+ * **Supports only Office 365, Outlook and Microsoft Exchange for now**
+ * Clean and intuitive UI
+ * Action filters
+ * Reminders
+ * [Skills][10]: Plugins to make you more productive with your emails
+ * Office 365 and Exchange and other Calendar Sync
+ * Compatible with [Active Directory][11]
+ * Offline email access
+ * Secure (it doesn’t send data to any third party server, it’s just an email client)
+ * Compatible with Microsoft’s archiving tool
+
+
+
+#### Taking a look at Hiri Features
+
+![][12]
+
+Hiri can either be compiled manually or [installed easily as Snap][13] and comes jam-packed with useful features. But, if you knew me at all, you would know that usually, a robust feature list is not a huge selling point for me. As a self-proclaimed minimalist, I tend to believe the simpler option is often the better option, and the less “fluff” there is surrounding a product, the easier it is to get to the part that really matters. Admittedly, this is not always the case. For example, KDE’s [Plasma][14] desktop is known for its excessive amount of tweaks and features and I am still a huge Plasma fan. But in Hiri’s case, it has what feels like the perfect feature set and in no way feels convoluted or confusing.
+
+That is partially due to the way that Hiri works. If I had to put it into my own words, I would say that Hiri feels almost modular. It does this by utilizing what Hiri calls the Skill Center. Here you can add or remove functionality in Hiri at the flip of a switch. This includes the ability to add tasks, delegate action items to other people, set reminders, and even enables the user to create better subject lines. None of which are required, but each of which adds something to Hiri that no other email client has done as well.
+
+Using these features can help you organize your email like never before. The Dashboard feature allows you to monitor your time spent working on emails, the Task List enables you to stay on track, the Action/FYI feature allows you to tag your emails as needed to help you cipher through a messy inbox, and the Zero Inbox feature helps the user keep their inbox count at a minimum once they have sorted through the nonsense. And as someone who is an avid Inbox Zeroer (if that is even a thing), this to me was incredibly useful.
+
+Hiri also syncs with your associated calendars as you would expect, and it even allows a global search for all of the other accounts associated with your office. Need to email Frank Smith in Human Resources but can’t remember his email address? No big deal! Hiri will auto-fill the email address once you start typing in his name just like in a native Outlook client.
+
+Multiple account support is also available in Hiri. The support for IMAP will be added in a few months.
+
+In short, Hiri’s feature-set allows for what feels like a truly native Microsoft offering on Linux. It is clean, simple enough, and allows someone with my productivity workflow to thrive. I really dig what Hiri has to offer, and it’s as simple as that.
+
+#### Experiencing the Hiri UI
+
+As far as design goes, Hiri gets a solid A from me. I never felt like I was using something outdated looking like [Evolution][15] (I know people like Evolution a lot, but to say it is clean and modern is a lie), it never felt overly complicated like [KMail][16], and it felt less cramped than Thunderbird. Though I love Thunderbird dearly, the inbox list is just a little too small to feel like I can really cipher through my emails in a decent amount of time. Hiri seemingly fixes this but adds another issue that may be even worse.
+
+![][17]
+
+Geary is an email client that I think does layouts just right. It is spacious, but not in a wasteful way, it is clean, simple, and allows me to get from point A to point B quickly. Hiri, on the other hand, falls just shy of layout heaven. Though the inbox list looks fantastic, when you click to read an email it takes up the whole screen. Whereas Geary or Thunderbird can be set up to have the user’s list of emails on the left and opened emails in the same window on the right, which is my preferred way to read email, Hiri does not allow this functionality. The layout either looks and functions like it belongs on a mobile device, or the email preview is below the email list instead of to the right. This isn’t a make or break issue for me, but I will be honest and say I really don’t like it.
+
+In my opinion, Hiri could work even better with a couple of tweaks. But that opinion is just that, an opinion. Hiri is modern, clean, and intuitive enough, I am just obnoxiously picky. Other than that, the color palette is beautiful, the soft edges are pretty stunning, and Hiri’s overall design language is a breath of fresh air in the, at times, outdated feel that is oh so common in the Linux application world.
+
+Also, this isn’t Hiri’s fault but since I installed the Hiri snap it still has the same cursor theme issue that many other snaps suffer from, which drives me UP A WALL when I move in and out of the application, so there’s that.
+
+#### How much does Hiri cost?
+
+![Hiri is compatible with Microsoft Active Directory][18]
+
+Hiri is neither free nor open source software. [Hiri costs][19] either up to $39 a year or $119 for a lifetime license. However, it does provide a free seven day trial period.
+
+Considering the features it provides, Hiri is a good product even if you don’t have to deal with Microsoft Exchange Servers. Don’t take my word for it. Give Hiri a try for free for the seven day trial and see for yourself if it is worth paying or not.
+
+And if you decide to purchase it, I have further good news for you. Hiri team has agreed to provide an exclusive 60% discount to It’s FOSS readers. All you have to do is to use coupon code ITSFOSS60 at checkout.
+
+[Get 60% Off with ITSFOSS60 Coupon Code][20]
+
+#### Conclusion
+
+In the end, Hiri is an amazingly beautiful piece of software that checks so many boxes for me. That being said, the three marks that it misses for me are collectively too big to overlook: the layout, the cost, and the freedom (or lack thereof). If you are someone who is really in need of a native client, the layout does not bother you, you can justify spending some money, and you don’t want or need it to be FOSS, then you may have just found your new email client!
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/hiri-email-review/
+
+作者:[Phillip Prado][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/phillip/
+[1]:https://itsfoss.com/protonmail/
+[2]:https://itsfoss.com/tutanota-review/
+[3]:https://www.thunderbird.net/en-US/
+[4]:https://wiki.gnome.org/Apps/Geary
+[5]:http://getmailspring.com/
+[6]:https://en.wikipedia.org/wiki/Microsoft_Exchange_Server
+[7]:https://www.hiri.com/
+[8]:https://itsfoss.com/best-email-clients-linux/
+[9]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/08/hiri-email-client-review.jpeg
+[10]:https://www.hiri.com/skills/
+[11]:https://en.wikipedia.org/wiki/Active_Directory
+[12]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/Hiri2-e1533106054811.png
+[13]:https://snapcraft.io/hiri
+[14]:https://www.kde.org/plasma-desktop
+[15]:https://wiki.gnome.org/Apps/Evolution
+[16]:https://www.kde.org/applications/internet/kmail/
+[17]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/Hiri3-e1533106099642.png
+[18]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/Hiri1-e1533106238745.png
+[19]:https://www.hiri.com/pricing/
+[20]:https://www.hiri.com/download/
diff --git a/sources/tech/20180801 Migrating Perl 5 code to Perl 6.md b/sources/tech/20180801 Migrating Perl 5 code to Perl 6.md
new file mode 100644
index 0000000000..0399fd7a62
--- /dev/null
+++ b/sources/tech/20180801 Migrating Perl 5 code to Perl 6.md
@@ -0,0 +1,77 @@
+Migrating Perl 5 code to Perl 6
+======
+
+
+
+Whether you are a programmer who is taking the first steps to convert your Perl 5 code to Perl 6 and encountering some issues or you're just interested in learning about what might happen if you try to port Perl 5 programs to Perl 6, this article should answer your questions.
+
+The [Perl 6 documentation][1] already contains most (if not all) the [documentation you need][2] to deal with the issues you will confront in migrating Perl 5 code to Perl 6. But, as documentation goes, the focus is on the factual differences. I will try to go a little more in-depth about specific issues and provide a little more hands-on information based on my experience porting quite a lot of Perl 5 code to Perl 6.
+
+### How is Perl 6 anyway?
+
+Very well, thank you! Since its first official release in December 2015, Rakudo Perl 6 has seen an order of magnitude of improvement and quite a few bug fixes (more than 14,000 commits in total). Seven books about Perl 6 have been published so far. [Learning Perl 6][3] by Brian D. Foy will soon be published by O'Reilly, having been re-worked from the seminal [Learning Perl][4] (aka "The Llama Book") that many people have come to know and love.
+
+The user distribution [Rakudo Star][5] is on a three-month release cycle, and more than 1,100 modules are available in the [Perl 6 ecosystem][6]. The Rakudo Compiler Release is on a monthly release cycle and typically contains contributions by more than 30 people. Perl 6 modules are uploaded to the Perl programming Authors Upload Server ([PAUSE][7]) and distributed all over the world using the Comprehensive Perl Archive Network ([CPAN][8]).
+
+The online [Perl 6 Introduction][9] document has been translated into 12 languages, teaching over 3 billion people about Perl 6 in their native language. The most recent incarnation of [Perl 6 Weekly][10] has been reporting on all things Perl 6 every week since February 2014.
+
+[Cro][11], a microservices framework, uses all of Perl 6's features from the ground up, providing HTTP 1.1 persistent connections, HTTP 2.0 with request multiplexing, and HTTPS with optional certificate authority out of the box. And a [Perl 6 IDE][12] is now in (paid) beta (think of it as a Kickstarter with immediate deliverables).
+
+### Using Perl 5 features in Perl 6
+
+Perl 5 code can be seamlessly integrated with Perl 6 using the [`Inline::Perl5`][13] module, making all of [CPAN][14] available to any Perl 6 program. This could be considered cheating, as it will embed a Perl 5 interpreter and therefore continues to have a dependency on the `perl` (5) runtime. But it does make it easy to get your Perl 6 code running (if you need access to modules that have not yet been ported) simply by adding `:from` to your `use` statement, like `use DBI:from;`.
+
+In January 2018, I proposed a [CPAN Butterfly Plan][15] to convert Perl 5 functionality to Perl 6 as closely as possible to the original API. I stated this as a goal because Perl 5 (as a programming language) is so much more than syntax alone. Ask anyone what Perl's unique selling point is, and they will most likely tell you it is CPAN. Therefore, I think it's time to move from this view of the Perl universe:
+
+
+
+to a more modern view:
+
+
+
+In other words: put CPAN, as the most important element of Perl, in the center.
+
+### Converting semantics
+
+To run Perl 5 code natively in Perl 6, you also need a lot of Perl 5 semantics. Having (optional) support for Perl 5 semantics available in Perl 6 lowers the conceptual threshold that Perl 5 programmers perceive when trying to program in Perl 6. It's easier to feel at home!
+
+Since the publication of the CPAN Butterfly Plan, more than 100 built-in Perl 5 functions are now supported in Perl 6 with the same API. Many functions already exist in Perl 6 but have slightly different semantics, e.g., `shift` in Perl 5 magically shifts from `@_` (or `@ARGV`) if no parameter is specified; in Perl 6 the parameter is obligatory.
+
+More than 50 Perl 5 CPAN distributions have also been ported to Perl 6 while adhering to the original Perl 5 API. These include core modules such as [Scalar::Util][16] and [List::Util][17], but also non-core modules such as [Text::CSV][18] and [Memoize][19]. Distributions that are upstream on the [River of CPAN][20] are targeted to have as much effect on the ecosystem as possible.
+
+### Summary
+
+Rakudo Perl 6 has matured in such a way that using Perl 6 is now a viable approach to creating new, interactive projects. Being able to use reliable and proven Perl 5 language components aids in lowering the threshold for developers to use Perl 6, and it builds towards a situation where the sum of Perl 5 and Perl 6 becomes greater than its parts.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/migrating-perl-5-perl-6
+
+作者:[Elizabeth Mattijsen][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/lizmat
+[1]:https://docs.perl6.org/
+[2]:https://docs.perl6.org/language/5to6-overview
+[3]:https://www.learningperl6.com
+[4]:http://shop.oreilly.com/product/0636920049517.do
+[5]:https://rakudo.org/files
+[6]:https://modules.perl6.org
+[7]:https://pause.perl.org/pause/query?ACTION=pause_04about
+[8]:https://www.cpan.org
+[9]:https://perl6intro.com
+[10]:https://p6weekly.wordpress.com
+[11]:https://cro.services
+[12]:https://commaide.com
+[13]:http://modules.perl6.org/dist/Inline::Perl5:cpan:NINE
+[14]:https://metacpan.org
+[15]:https://www.perl.com/article/an-open-letter-to-the-perl-community/
+[16]:https://modules.perl6.org/dist/Scalar::Util
+[17]:https://modules.perl6.org/dist/List::Util
+[18]:https://modules.perl6.org/dist/Text::CSV
+[19]:https://modules.perl6.org/dist/Memoize
+[20]:http://neilb.org/2015/04/20/river-of-cpan.html
diff --git a/sources/tech/20180802 Top 5 CAD Software Available for Linux in 2018.md b/sources/tech/20180802 Top 5 CAD Software Available for Linux in 2018.md
new file mode 100644
index 0000000000..ec02690b6e
--- /dev/null
+++ b/sources/tech/20180802 Top 5 CAD Software Available for Linux in 2018.md
@@ -0,0 +1,143 @@
+Top 5 CAD Software Available for Linux in 2018
+======
+[Computer Aided Design (CAD)][1] is an essential part of many streams of engineering. CAD is professionally used is architecture, auto parts design, space shuttle research, aeronautics, bridge construction, interior design, and even clothing and jewelry.
+
+A number of professional grade CAD software like SolidWorks and Autodesk AutoCAD are not natively supported on the Linux platform. So today we will be having a look at the top CAD software available for Linux. Let’s dive right in.
+
+### Best CAD Software available for Linux
+
+![CAD Software for Linux][2]
+
+Before you see the list of CAD software for Linux, you should keep one thing in mind that not all the applications listed here are open source. We included some non-FOSS CAD software to help average Linux user.
+
+Installation instructions of Ubuntu-based Linux distributions have been provided. You may check the respective websites to learn the installation procedure for other distributions.
+
+The list is not any specific order. CAD application at number one should not be considered better than the one at number three and so on.
+
+#### 1\. FreeCAD
+
+For 3D Modelling, FreeCAD is an excellent option which is both free (beer and speech) and open source. FreeCAD is built with keeping mechanical engineering and product design as target purpose. FreeCAD is multiplatform and is available on Windows, Mac OS X+ along with Linux.
+
+![freecad][3]
+
+Although FreeCAD has been the choice of many Linux users, it should be noted that FreeCAD is still on version 0.17 and therefore, is not suitable for major deployment. But the development has picked up pace recently.
+
+[FreeCAD][4]
+
+FreeCAD does not focus on direct 2D drawings and animation of organic shapes but it’s great for design related to mechanical engineering. FreeCAD version 0.15 is available in the Ubuntu repositories. You can install it by running the below command.
+```
+sudo apt install freecad
+
+```
+
+To get newer daily builds (0.17 at the moment), open a terminal (ctrl+alt+t) and run the commands below one by one.
+```
+sudo add-apt-repository ppa:freecad-maintainers/freecad-daily
+
+sudo apt update
+
+sudo apt install freecad-daily
+
+```
+
+#### 2\. LibreCAD
+
+LibreCAD is a free, opensource, 2D CAD solution. Generally, CAD tends to be a resource-intensive task, and if you have a rather modest hardware, then I’d suggest you go for LibreCAD as it is really lightweight in terms of resource usage. LibreCAD is a great candidate for geometric constructions.
+
+![librecad][5]
+As a 2D tool, LibreCAD is good but it cannot work on 3D models and renderings. It might be unstable at times but it has a dependable autosave which won’t let your work go wasted.
+
+[LibreCAD][6]
+
+You can install LibreCAD by running the following command
+```
+sudo apt install librecad
+
+```
+
+#### 3\. OpenSCAD
+
+OpenSCAD is a free 3D CAD software. OpenSCAD is very lightweight and flexible. OpenSCAD is not interactive. You need to ‘program’ the model and OpenSCAD interprets that code to render a visual model. It is a compiler in a sense. You cannot draw the model. You describe the model.
+
+![openscad][7]
+
+OpenSCAD is the most complicated tool on this list but once you get to know it, it provides an enjoyable work experience.
+
+[OpenSCAD][8]
+
+You can use the following commands to install OpenSCAD.
+```
+sudo apt-get install openscad
+
+```
+
+#### 4\. BRL-CAD
+
+BRL-CAD is one of the oldest CAD tools out there. It also has been loved by Linux/UNIX users as it aligns itself with *nix philosophies of modularity and freedom.
+
+![BRL-CAD rendering by Sean][9]
+
+BRL-CAD was started in 1979, and it is still developed actively. Now, BRL-CAD is not AutoCAD but it is still a great choice for transport studies such as thermal and ballistic penetration. BRL-CAD underlies CSG instead of boundary representation. You might need to keep that in mind while opting for BRL-CAD. You can download BRL-CAD from its official website.
+
+[BRL-CAD][10]
+
+#### 5\. DraftSight (not open source)
+
+If You’re used to working on AutoCAD, then DraftSight would be the perfect alternative for you.
+
+DraftSight is a great CAD tool available on Linux. It has a rather similar workflow to AutoCAD, which makes migrating easier. It even provides a similar look and feel. DrafSight is also compatible with the .dwg file format of AutoCAD. But DrafSight is a 2D CAD software. It does not support 3D CAD as of yet.
+
+![draftsight][11]
+
+Although DrafSight is a commercial software with a starting price of $149. A free version is also made available on the[DraftSight website][12]. You can download the .deb package and install it on Ubuntu based distributions. need to register your free copy using your email ID to start using DraftSight.
+
+[DraftSight][12]
+
+#### Honorary mentions
+
+ * With a huge growth in cloud computing technologies, cloud CAD solutions like [OnShape][13] have been getting popular day by day.
+ * [SolveSpace][14] is another open-source project worth mentioning. It supports 3D modeling.
+ * Siemens NX is an industrial grade CAD solution available on Windows, Mac OS and Linux, but it is ridiculously expensive, so omitted in this list.
+ * Then you have [LeoCAD][15], which is a CAD software where you use LEGO blocks to build stuff. What you do with this information is up to you.
+
+
+
+#### CAD on Linux, in my opinion
+
+Although gaming on Linux has picked up, I always tell my hardcore gaming friends to stick to Windows. Similarly, if You are an engineering student with CAD in your curriculum, I’d recommend that you use the software that your college prescribes (AutoCAD, SolidEdge, Catia), which generally tend to run on Windows only.
+
+And for the advanced professionals, these tools are simply not up to the mark when we’re talking about industry standards.
+
+For those of you thinking about running AutoCAD in WINE, although some older versions of AutoCAD can be installed on WINE, they simply do not perform, with glitches and crashes ruining the experience.
+
+That being said, I highly respect the work that has been put by the developers of the above-listed software. They have enriched the FOSS world. And it’s great to see software like FreeCAD developing with an accelerated pace in the recent years.
+
+Well, that’s it for today. Do share your thoughts with us using the comments section below and don’t forget to share this article. Cheers.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/cad-software-linux/
+
+作者:[Aquil Roshan][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/aquil/
+[1]:https://en.wikipedia.org/wiki/Computer-aided_design
+[2]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/08/cad-software-linux.jpeg
+[3]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/freecad.jpg
+[4]:https://www.freecadweb.org/
+[5]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/librecad.jpg
+[6]:https://librecad.org/
+[7]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/openscad.jpg
+[8]:http://www.openscad.org/
+[9]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/brlcad.jpg
+[10]:https://brlcad.org/
+[11]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/draftsight.jpg
+[12]:https://www.draftsight2018.com/
+[13]:https://www.onshape.com/
+[14]:http://solvespace.com/index.pl
+[15]:https://www.leocad.org/
diff --git a/sources/tech/20180802 Walkthrough On How To Use GNOME Boxes.md b/sources/tech/20180802 Walkthrough On How To Use GNOME Boxes.md
new file mode 100644
index 0000000000..f4c9790df9
--- /dev/null
+++ b/sources/tech/20180802 Walkthrough On How To Use GNOME Boxes.md
@@ -0,0 +1,117 @@
+Walkthrough On How To Use GNOME Boxes
+======
+
+
+
+Boxes or GNOME Boxes is a virtualization software for GNOME Desktop Environment. It is similar to Oracle VirtualBox but features a simple user interface. Boxes also pose some challenge for newbies and VirtualBox users, for instance, on VirtualBox, it is easy to install guest addition image through menu bar but the same is not true for Boxes. Rather, users are encouraged to install additional guest tools from the terminal program within the guest session.
+
+This article will provide a walkthrough on how to use GNOME Boxes by installing the software and actually setting a guest session on the machine. It will also take you through the steps for installing the guest tools and provide some additional tips for Boxes configuration.
+
+### Purpose of virtualization
+
+If you are wondering what is the purpose of virtualization and why most computer experts and developers use them a lot. There is usually a common reason for this: **TESTING**.
+
+Developers who use Linux and writes software for Windows has to test his program on an actual Windows environment before deploying it to the end users. Virtualization makes it possible for him to install and set up a Windows guest session on his Linux computer.
+
+Virtualization is also used by ordinary users who wish to get hands-on with their favorite Linux distro that is still in beta release, without installing it on their physical computer. So in the event the virtual machine crashes, the host is not affected and the important files & documents stored on the physical disk remain intact.
+
+Virtualization allows you to test a software built for another platform/architecture which may include ARM, MIPS, SPARC, etc on your computer equipped with another architecture such as Intel or AMD.
+
+### Installing GNOME Boxes
+
+Launch Ubuntu Software and key in " gnome boxes ". Click the application name to load its installer page and then select the Install button. [][1]
+
+### Extra setup for Ubuntu 18.04
+
+There's a bug in GNOME Boxes on Ubuntu 18.04; it fails to start the Virtual Machine (VM). To remedy that, perform the below two steps on a terminal program:
+
+1. Add the line "group=kvm" to the qemu config file sudo gedit /etc/modprobe.d/qemu-system-x86.conf
+
+2. Add your user account to kvm group sudo usermod -a -G kvm
+
+ [][2]
+
+ After that, logout and re-login again for the changes to take effect.
+
+#### Downloading an image file
+
+You can download an image file/Operating System (OS) from the Internet or within the GNOME Boxes setup itself. However, for this article we'll proceed with the realistic method ie., downloading an image file from the Internet. We'll be configuring Lubuntu on Boxes so head over to this website to download the Linux distro.
+
+[Download][3]
+
+#### To burn or not to burn
+
+If you have no intention to distribute Lubuntu to your friends or install it on a physical machine then it's best not to burn the image file to a blank disc or portable USB drive. Instead just leave it as it is, we'll use it for creating a VM afterward.
+
+#### Starting GNOME Boxes
+
+Below is the interface of GNOME Boxes on Ubuntu - [][4]
+
+The interface is simple and intuitive for newbies to get familiar right away without much effort. Boxes don't feature a menu bar or toolbar, unlike Oracle VirtualBox. On the top left is the New button to create a VM and on the right houses buttons for VM options; delete list or grid view, and configuration (they'll become available when a VM is created).
+
+### Installing an Operating System
+
+Click the New button and choose "Select a file". Select the downloaded Lubuntu image file on the Downloads library and then click Create button.
+
+ [][5]
+
+In case this is your first time installing an OS on a VM, do not panic when the installer pops up a window asking you to erase the disk partition. It's safe, your physical computer hard drive won't be erased, only that the storage space would be allocated for your VM. So on a 1TB hard drive, if you allocate 30 GB for your VM, performing erase partition operation on Boxes would only erase that virtual 30 GB storage drive and not the physical storage.
+
+ _Usually, computer students find virtualization a useful tool for practicing advanced partitioning using UNIX based OS. You can too since there is no risk that would tamper the main OS files._
+
+After installing Lubuntu, you'll be prompted to reboot the computer (VM) to finish the installation process and actually boot from the hard drive. Confirm the operation.
+
+
+
+Sometimes, certain Linux distros hang in the reboot process after installation. The trick is to force shutdown the VM from the options button found on the top right side of the tile bar and then power it on again.
+
+#### Set up Guest tools
+
+By now you might have noticed Lubuntu's screen resolution is small with extra black spaces on the left and right side, and folder sharing is not enabled too. This brings up the need to install guest tools on Lubuntu.
+
+
+
+Launch terminal program from the guest session (not your host terminal program) and install the guest tools using the below command:
+
+sudo apt install spice-vdagent spice-webdavd
+
+After that, reboot Lubuntu and the next boot will set the VM to its appropriate screen resolution; no more extra black spaces on the left and right side. You can resize Boxes window and the guest screen resolution will automatically resize itself.
+
+ [][6]
+
+To share a folder between the host and guest, open Boxes options while the guest is still running and choose Properties. On the Devices & Shares category, click the + button and set up the name. By default, Public folder from the host will be shared with the guest OS. You can configure the directory of your choice. After that is done, launch Lubuntu's file manager program (it's called PCManFM) and click Go menu on the menu bar. Select Network and choose Spice Client Folder. The first time you try to open it a dialog box will pop up asking you which program should handle the network, select PCManFM under Accessories category and the network will be mounted on the desktop. Launch it and there you'll see your shared folder name.
+
+Now you can share files and folders between host and guest computer. Subsequent launch of the network will directly open the shared folder so you don't have to open the folder manually the next time.
+
+ [][7]
+
+#### Where's the OS installed?
+
+Lubuntu is installed as a VM using **GNOME Boxes** but where does it store the disk image?
+
+This question is of particular interest for those who wish to move the huge image file to another partition where there is sufficient storage. The trick is using symlinks which is efficient as it saves more space for Linux root partition and or home partition, depending on how the user set it up during installation. Boxes stores the disk image files to ~/.local/share/gnome-boxes/images folder
+
+### Conclusion
+
+We've successfully set up Lubuntu as a guest OS on our Ubuntu. You can try other variants of Ubuntu such as Kubuntu, Ubuntu MATE, Xubuntu, etc or some random Linux distros which in my opinion would be quite challenging due to varying package management. But there's no harm in wanting to :) You can also try installing other platforms like Microsoft Windows, OpenBSD, etc on your computer as a VM. And by the way, don't forget to leave your opinions in the comment section below.
+
+
+--------------------------------------------------------------------------------
+
+via: http://www.linuxandubuntu.com/home/walkthrough-on-how-to-use-gnome-boxes
+
+作者:[linuxandubuntu][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]:http://www.linuxandubuntu.com
+[1]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/install-gnome-boxes_orig.jpg
+[2]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/gnome-boxes-extras-for-ubuntu-18-04_orig.jpg
+[3]:https://lubuntu.net/
+[4]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/create-gnome-boxes_orig.jpg
+[5]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/install-os-on-ubuntu-guest-box_orig.jpg
+[6]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/lubuntu-on-gnome-boxes_orig.jpg
+[7]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/gnome-boxes-guest-addition_orig.jpg
diff --git a/sources/tech/20180803 5 Essential Tools for Linux Development.md b/sources/tech/20180803 5 Essential Tools for Linux Development.md
new file mode 100644
index 0000000000..006372ca82
--- /dev/null
+++ b/sources/tech/20180803 5 Essential Tools for Linux Development.md
@@ -0,0 +1,148 @@
+5 Essential Tools for Linux Development
+======
+
+
+
+Linux has become a mainstay for many sectors of work, play, and personal life. We depend upon it. With Linux, technology is expanding and evolving faster than anyone could have imagined. That means Linux development is also happening at an exponential rate. Because of this, more and more developers will be hopping on board the open source and Linux dev train in the immediate, near, and far-off future. For that, people will need tools. Fortunately, there are a ton of dev tools available for Linux; so many, in fact, that it can be a bit intimidating to figure out precisely what you need (especially if you’re coming from another platform).
+
+To make that easier, I thought I’d help narrow down the selection a bit for you. But instead of saying you should use Tool X and Tool Y, I’m going to narrow it down to five categories and then offer up an example for each. Just remember, for most categories, there are several available options. And, with that said, let’s get started.
+
+### Containers
+
+Let’s face it, in this day and age you need to be working with containers. Not only are they incredibly easy to deploy, they make for great development environments. If you regularly develop for a specific platform, why not do so by creating a container image that includes all of the tools you need to make the process quick and easy. With that image available, you can then develop and roll out numerous instances of whatever software or service you need.
+
+Using containers for development couldn’t be easier than it is with [Docker][1]. The advantages of using containers (and Docker) are:
+
+ * Consistent development environment.
+
+ * You can trust it will “just work” upon deployment.
+
+ * Makes it easy to build across platforms.
+
+ * Docker images available for all types of development environments and languages.
+
+ * Deploying single containers or container clusters is simple.
+
+
+
+
+Thanks to [Docker Hub][2], you’ll find images for nearly any platform, development environment, server, service… just about anything you need. Using images from Docker Hub means you can skip over the creation of the development environment and go straight to work on developing your app, server, API, or service.
+
+Docker is easily installable of most every Linux platform. For example: To install Docker on Ubuntu, you only have to open a terminal window and issue the command:
+```
+sudo apt-get install docker.io
+
+```
+
+With Docker installed, you’re ready to start pulling down specific images, developing, and deploying (Figure 1).
+
+![Docker images][4]
+
+Figure 1: Docker images ready to deploy.
+
+[Used with permission][5]
+
+### Version control system
+
+If you’re working on a large project or with a team on a project, you’re going to need a version control system. Why? Because you need to keep track of your code, where your code is, and have an easy means of making commits and merging code from others. Without such a tool, your projects would be nearly impossible to manage. For Linux users, you cannot beat the ease of use and widespread deployment of [Git][6] and [GitHub][7]. If you’re new to their worlds, Git is the version control system that you install on your local machine and GitHub is the remote repository you use to upload (and then manage) your projects. Git can be installed on most Linux distributions. For example, on a Debian-based system, the install is as simple as:
+```
+sudo apt-get install git
+
+```
+
+Once installed, you are ready to start your journey with version control (Figure 2).
+
+![Git installed][9]
+
+Figure 2: Git is installed and available for many important tasks.
+
+[Used with permission][5]
+
+Github requires you to create an account. You can use it for free for non-commercial projects, or you can pay for commercial project housing (for more information check out the price matrix [here][10]).
+
+### Text editor
+
+Let’s face it, developing on Linux would be a bit of a challenge without a text editor. Of course what a text editor is varies, depending upon who you ask. One person might say vim, emacs, or nano, whereas another might go full-on GUI with their editor. But since we’re talking development, we need a tool that can meet the needs of the modern day developer. And before I mention a couple of text editors, I will say this: Yes, I know that vim is a serious workhorse for serious developers and, if you know it well vim will meet and exceed all of your needs. However, getting up to speed enough that it won’t be in your way, can be a bit of a hurdle for some developers (especially those new to Linux). Considering my goal is to always help win over new users (and not just preach to an already devout choir), I’m taking the GUI route here.
+
+As far as text editors are concerned, you cannot go wrong with the likes of [Bluefish][11]. Bluefish can be found in most standard repositories and features project support, multi-threaded support for remote files, search and replace, open files recursively, snippets sidebar, integrates with make, lint, weblint, xmllint, unlimited undo/redo, in-line spell checker, auto-recovery, full screen editing, syntax highlighting (Figure 3), support for numerous languages, and much more.
+
+![Bluefish][13]
+
+Figure 3: Bluefish running on Ubuntu Linux 18.04.
+
+[Used with permission][5]
+
+### IDE
+
+Integrated Development Environment (IDE) is a piece of software that includes a comprehensive set of tools that enable a one-stop-shop environment for developing. IDEs not only enable you to code your software, but document and build them as well. There are a number of IDEs for Linux, but one in particular is not only included in the standard repositories it is also very user-friendly and powerful. That tool in question is [Geany][14]. Geany features syntax highlighting, code folding, symbol name auto-completion, construct completion/snippets, auto-closing of XML and HTML tags, call tips, many supported filetypes, symbol lists, code navigation, build system to compile and execute your code, simple project management, and a built-in plugin system.
+
+Geany can be easily installed on your system. For example, on a Debian-based distribution, issue the command:
+```
+sudo apt-get install geany
+
+```
+
+Once installed, you’re ready to start using this very powerful tool that includes a user-friendly interface (Figure 4) that has next to no learning curve.
+
+![Geany][16]
+
+Figure 4: Geany is ready to serve as your IDE.
+
+[Used with permission][5]
+
+### diff tool
+
+There will be times when you have to compare two files to find where they differ. This could be two different copies of what was the same file (only one compiles and the other doesn’t). When that happens, you don’t want to have to do that manually. Instead, you want to employ the power of tool like [Meld][17]. Meld is a visual diff and merge tool targeted at developers. With Meld you can make short shrift out of discovering the differences between two files. Although you can use a command line diff tool, when efficiency is the name of the game, you can’t beat Meld.
+
+Meld allows you to open a comparison between to files and it will highlight the differences between each. Meld also allows you to merge comparisons either from the right or the left (as the files are opened side by side - Figure 5).
+
+![Comparing two files][19]
+
+Figure 5: Comparing two files with a simple difference.
+
+[Used with permission][5]
+
+Meld can be installed from most standard repositories. On a Debian-based system, the installation command is:
+```
+sudo apt-get install meld
+
+```
+
+### Working with efficiency
+
+These five tools not only enable you to get your work done, they help to make it quite a bit more efficient. Although there are a ton of developer tools available for Linux, you’re going to want to make sure you have one for each of the above categories (maybe even starting with the suggestions I’ve made).
+
+Learn more about Linux through the free ["Introduction to Linux" ][20]course from The Linux Foundation and edX.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/learn/intro-to-linux/2018/8/5-essential-tools-linux-development
+
+作者:[Jack Wallen][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://www.linux.com/users/jlwallen
+[1]:https://www.docker.com/
+[2]:https://hub.docker.com/
+[3]:/files/images/5devtools1jpg
+[4]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/5devtools_1.jpg?itok=V1Bsbkg9 (Docker images)
+[5]:/licenses/category/used-permission
+[6]:https://git-scm.com/
+[7]:https://github.com/
+[8]:/files/images/5devtools2jpg
+[9]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/5devtools_2.jpg?itok=YJjhe4O6 (Git installed)
+[10]:https://github.com/pricing
+[11]:http://bluefish.openoffice.nl/index.html
+[12]:/files/images/5devtools3jpg
+[13]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/5devtools_3.jpg?itok=66A7Svme (Bluefish)
+[14]:https://www.geany.org/
+[15]:/files/images/5devtools4jpg
+[16]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/5devtools_4.jpg?itok=jRcA-0ue (Geany)
+[17]:http://meldmerge.org/
+[18]:/files/images/5devtools5jpg
+[19]:https://www.linux.com/sites/lcom/files/styles/rendered_file/public/5devtools_5.jpg?itok=eLkfM9oZ (Comparing two files)
+[20]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180803 How to use Fedora Server to create a router - gateway.md b/sources/tech/20180803 How to use Fedora Server to create a router - gateway.md
new file mode 100644
index 0000000000..0394826c10
--- /dev/null
+++ b/sources/tech/20180803 How to use Fedora Server to create a router - gateway.md
@@ -0,0 +1,285 @@
+How to use Fedora Server to create a router / gateway
+======
+
+
+
+Building a router (or gateway) using Fedora Server is an interesting project for users wanting to learn more about Linux system administration and networking. In this article, learn how to configure a Fedora Server minimal install to act as an internet router / gateway.
+
+This guide is based on [Fedora 28][1] and assumes you have already installed Fedora Server (minimal install). Additionally, you require a suitable network card / modem for the incoming internet connection. In this example, the [DrayTek VigorNIC 132][2] NIC was used to create the router.
+
+### Why build your own router
+
+There are many benefits for building your own router over buying a standalone box (or using the one supplied by your internet provider):
+
+ * Easily update and run latest software versions
+ * May be less prone to be part of larger hacking campaign as its not a common consumer device
+ * Run your own VMs or containers on same host/router
+ * Build OpenShift on top of router (future story in this series)
+ * Include your own VPN, Tor, or other tunnel paths along with correct routing
+
+
+
+The downside is related to time and knowledge.
+
+ * You have to manage your own security
+ * You need to have the knowledge to troubleshoot if an issue happens or find it through the web (no support calls)
+ * Costs more in most cases than hardware provided by an internet provider
+
+
+
+Basic network topology
+
+The diagram below describes the basic topology used in this setup. The machine running Fedora Server has a PCI Express modem for VDSL. Alternatively, if you use a [Raspberry Pi][3] with external modem the configuration is mostly similar.
+
+![topology][4]
+
+### Initial Setup
+
+First of all, install the packages needed to make the router. Bash auto-complete is included to make things easier when later configuring. Additionally, install packages to allow you to host your own VMs on the same router/hosts via KVM-QEMU.
+```
+dnf install -y bash-completion NetworkManager-ppp qemu-kvm qemu-img virt-manager libvirt libvirt-python libvirt-client virt-install virt-viewer
+
+```
+
+Next, use **nmcli** to set the MTU on the WAN(PPPoE) interfaces to align with DSL/ATM MTU and create **pppoe** interface. This [link][5] has a great explanation on how this works. The username and password will be provided by your internet provider.
+```
+nmcli connection add type pppoe ifname enp2s0 username 00xxx5511yyy0001@t-online.de password XXXXXX 802-3-ethernet.mtu 1452
+
+```
+
+Now, set up the firewall with the default zone as external and remove incoming SSH access.
+```
+firewall-cmd --set-default-zone=external
+firewall-cmd --permanent --zone=external --remove-service=ssh
+
+```
+
+Add LAN interface(br0) along with preferred LAN IP address and then add your physical LAN interface to the bridge.
+```
+nmcli connection add ifname br0 type bridge con-name br0 bridge.stp no ipv4.addresses 10.0.0.1/24 ipv4.method manual
+nmcli connection add type bridge-slave ifname enp1s0 master br0
+
+```
+
+Remember to use a subnet that does not overlap with your works VPN subnet. For example my work provides a 10.32.0.0/16 subnet when I VPN into the office so I need to avoid using this in my home network. If you overlap addressing then the route provided by your VPN will likely have lower priority and you will not route through the VPN tunnel.
+
+Now create a file called bridge.xml, containing a bridge definition that **virsh** will consume to create a bridge in **QEMU**.
+```
+cat > bridge.xml <
+ host-bridge
+
+
+
+EOF
+
+```
+
+Start and enable your libvirt-guests service so you can add the bridge in your virtual environment for the VMs to use.
+```
+systemctl start libvirt-guests.service
+systemctl enable libvirt-guests.service
+
+```
+
+Add your “host-bridge” to QEMU via virsh command and the XML file you created earlier.
+```
+virsh net-define bridge.xml
+
+```
+
+virsh net-start host-bridge virsh net-autostart host-bridge
+
+Add br0 to internal zone and allow DNS and DHCP as we will be setting up our own services on this router.
+```
+firewall-cmd --permanent --zone=internal --add-interface=br0
+firewall-cmd --permanent --zone=internal --add-service=dhcp
+firewall-cmd --permanent --zone=internal --add-service=dns
+
+```
+
+Since many DHCP clients including Windows and Linux don’t take into account the MTU attribute in DHCP, we will need to allow TCP based protocols to set MSS based on PMTU size.
+```
+firewall-cmd --permanent --direct --add-passthrough ipv4 -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
+
+```
+
+Now we reload the firewall to take permanent changes into account.
+```
+nmcli connection reload
+
+```
+
+### Install and Configure DHCP
+
+DHCP configuration depends on your home network setup. Use your own desired domain name and and the subnet was defined during the creation of **br0**. Be sure to note the MAC address in the config file below can either be capture from the command below once you have DHCP services up and running or you can pull it off the label externally on the device you want to set to static addressing.
+```
+cat /var/lib/dhcpd/dhcpd.leases
+
+dnf -y install dhcp
+vi /etc/dhcp/dhcpd.conf
+
+option domain-name "lajoie.org";
+option domain-name-servers 10.0.0.1;
+default-lease-time 600;
+max-lease-time 7200;
+authoritative;
+subnet 10.0.0.0 netmask 255.255.255.0 {
+ range dynamic-bootp 10.0.0.100 10.0.0.254;
+ option broadcast-address 10.0.0.255;
+ option routers 10.0.0.1; option interface-mtu 1452;
+}
+host ubifi {
+ option host-name "ubifi.lajoie.org";
+ hardware ethernet f0:9f:c2:1f:c1:12;
+ fixed-address 10.0.0.2;
+}
+
+```
+
+Now enable and start your DHCP server
+```
+systemctl start dhcpd
+systemctl enable dhcpd
+
+```
+
+### DNS Install and Configure
+
+Next, install **bind** and and **bind-utils** for tools like **nslookup** and **dig**.
+```
+dnf -y install bind bind-utils
+
+```
+
+Configure your bind server with listening address (LAN interface in this case) and the forward/reverse zones.
+```
+$ vi /etc/named.conf
+
+options {
+ listen-on port 53 { 10.0.0.1; };
+ listen-on-v6 port 53 { none; };
+ directory "/var/named";
+ dump-file "/var/named/data/cache_dump.db";
+ statistics-file "/var/named/data/named_stats.txt";
+ memstatistics-file "/var/named/data/named_mem_stats.txt";
+ secroots-file "/var/named/data/named.secroots";
+ recursing-file "/var/named/data/named.recursing";
+ allow-query { 10.0.0.0/24; };
+ recursion yes;
+ forwarders {8.8.8.8; 8.8.4.4; };
+ dnssec-enable yes;
+ dnssec-validation yes;
+ managed-keys-directory "/var/named/dynamic";
+ pid-file "/run/named/named.pid";
+ session-keyfile "/run/named/session.key";
+ include "/etc/crypto-policies/back-ends/bind.config";
+};
+controls { };
+logging {
+ channel default_debug {
+ file "data/named.run";
+ severity dynamic;
+ };
+};
+view "internal" {
+ match-clients { localhost; 10.0.0.0/24; };
+ zone "lajoie.org" IN {
+ type master;
+ file "lajoie.org.db";
+ allow-update { none; };
+ };
+ zone "0.0.10.in-addr.arpa" IN {
+ type master;
+ file "0.0.10.db";
+ allow-update { none; };
+ };
+};
+
+```
+
+Here is a zone file for example and make sure to update the serial number after each edit of the bind service will assume no changes took place.
+```
+$ vi /var/named/lajoie.org.db
+
+$TTL 86400
+@ IN SOA gw.lajoie.org. root.lajoie.org. (
+ 2018040801 ;Serial
+ 3600 ;Refresh
+ 1800 ;Retry
+ 604800 ;Expire
+ 86400 ;Minimum TTL )
+IN NS gw.lajoie.org.
+IN A 10.0.0.1
+gw IN A 10.0.0.1
+ubifi IN A 10.0.0.2
+
+```
+
+Here is a reverse zone file for example and make sure to update the serial number after each edit of the bind service will assume no changes took place.
+```
+$ vi /var/named/0.0.10.db
+
+$TTL 86400
+@ IN SOA gw.lajoie.org. root.lajoie.org. (
+ 2018040801 ;Serial
+ 3600 ;Refresh
+ 1800 ;Retry
+ 604800 ;Expire
+ 86400 ;Minimum TTL )
+IN NS gw.lajoie.org.
+IN PTR lajoie.org.
+IN A 255.255.255.0
+1 IN PTR gw.lajoie.org.
+2 IN PTR ubifi.lajoie.org.
+
+```
+
+Now enable and start your DNS server
+```
+systemctl start named
+systemctl enable named
+
+```
+
+# Secure SSH
+
+Last simple step is to make SSH service listen only on your LAN segment. Run this command to see whats listening at this moment. Remember we did not allow SSH on the external firewall zone but this step is still best practice in my opinion.
+```
+ss -lnp4
+
+```
+
+Now edit the SSH service to only listen on your LAN segment.
+```
+vi /etc/ssh/sshd_config
+
+AddressFamily inet
+ListenAddress 10.0.0.1
+
+```
+
+Restart your SSH service for changes to take effect.
+```
+systemctl restart sshd.service
+
+```
+
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/use-fedora-server-create-router-gateway/
+
+作者:[Eric Lajoie][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://fedoramagazine.org/author/elajoie/
+[1]:https://getfedora.org/en/server/
+[2]:https://www.draytek.com/en/products/products-a-z/router.all/vigornic-132-series/
+[3]:https://fedoraproject.org/wiki/Architectures/ARM/Raspberry_Pi
+[4]:https://ericlajoie.com/photo/FedoraRouter.png
+[5]:https://www.sonicwall.com/en-us/support/knowledge-base/170505851231244
diff --git a/sources/tech/20180803 SDKMAN - A CLI Tool To Easily Manage Multiple Software Development Kits.md b/sources/tech/20180803 SDKMAN - A CLI Tool To Easily Manage Multiple Software Development Kits.md
new file mode 100644
index 0000000000..1fcd5f729b
--- /dev/null
+++ b/sources/tech/20180803 SDKMAN - A CLI Tool To Easily Manage Multiple Software Development Kits.md
@@ -0,0 +1,308 @@
+SDKMAN – A CLI Tool To Easily Manage Multiple Software Development Kits
+======
+
+
+
+Are you a developer who often install and test applications on different SDKs? I’ve got a good news for you! Say hello to **SDKMAN** , a CLI tool that helps you to easily manage multiple software development kits. It provides a convenient way to install, switch, list and remove candidates. Using SDKMAN, you can now manage parallel versions of multiple SDKs easily on any Unix-like operating system. It allows the developers to install Software Development Kits for the JVM such as Java, Groovy, Scala, Kotlin and Ceylon. Ant, Gradle, Grails, Maven, SBT, Spark, Spring Boot, Vert.x and many others are also supported. SDKMAN is free, light weight, open source and written in **Bash**.
+
+### Installing SDKMAN
+
+Installing SDKMAN is trivial. First, make sure you have installed **zip** and **unzip** applications. It is available in the default repositories of most Linux distributions. For instance, to install unzip on Debian-based systems, simply run:
+```
+$ sudo apt-get install zip unzip
+
+```
+
+Then, install SDKMAN using command:
+```
+$ curl -s "https://get.sdkman.io" | bash
+
+```
+
+It’s that simple. Once the installation is completed, run the following command:
+```
+$ source "$HOME/.sdkman/bin/sdkman-init.sh"
+
+```
+
+If you want to install it in a custom location of your choice other than **$HOME/.sdkman** , for example **/usr/local/** , do:
+```
+$ export SDKMAN_DIR="/usr/local/sdkman" && curl -s "https://get.sdkman.io" | bash
+
+```
+
+Make sure your user has full access rights to this folder.
+
+Finally, check if the installation is succeeded using command:
+```
+$ sdk version
+==== BROADCAST =================================================================
+* 01/08/18: Kotlin 1.2.60 released on SDKMAN! #kotlin
+* 31/07/18: Sbt 1.2.0 released on SDKMAN! #sbt
+* 31/07/18: Infrastructor 0.2.1 released on SDKMAN! #infrastructor
+================================================================================
+
+SDKMAN 5.7.2+323
+
+```
+
+Congratulations! SDKMAN has been installed. Let us go ahead and see how to install and manage SDKs.
+
+### Manage Multiple Software Development Kits
+
+To view the list of available candidates(SDKs), run:
+```
+$ sdk list
+
+```
+
+Sample output would be:
+```
+================================================================================
+Available Candidates
+================================================================================
+q-quit /-search down
+j-down ?-search up
+k-up h-help
+
+--------------------------------------------------------------------------------
+Ant (1.10.1) https://ant.apache.org/
+
+Apache Ant is a Java library and command-line tool whose mission is to drive
+processes described in build files as targets and extension points dependent
+upon each other. The main known usage of Ant is the build of Java applications.
+Ant supplies a number of built-in tasks allowing to compile, assemble, test and
+run Java applications. Ant can also be used effectively to build non Java
+applications, for instance C or C++ applications. More generally, Ant can be
+used to pilot any type of process which can be described in terms of targets and
+tasks.
+
+: $ sdk install ant
+
+```
+
+As you can see, SDKMAN list one candidate at a time along with the description of the candidate and it’s official website and the installation command. Press ENTER key to list the next candidates.
+
+To install a SDK, for example Java JDK, run:
+```
+$ sdk install java
+
+```
+
+Sample output:
+```
+Downloading: java 8.0.172-zulu
+
+In progress...
+
+######################################################################################## 100.0%
+
+Repackaging Java 8.0.172-zulu...
+
+Done repackaging...
+
+Installing: java 8.0.172-zulu
+Done installing!
+
+Setting java 8.0.172-zulu as default.
+
+```
+
+If you have multiple SDKs, it will prompt if you want the currently installed version to be set as **default**. Answering **Yes** will set the currently installed version as default.
+
+To install particular version of a SDK, do:
+```
+$ sdk install ant 1.10.1
+
+```
+
+If you already have local installation of a specific candidate, you can set it as local version like below.
+```
+$ sdk install groovy 3.0.0-SNAPSHOT /path/to/groovy-3.0.0-SNAPSHOT
+
+```
+
+To list a particular candidates versions:
+```
+$ sdk list ant
+
+```
+
+Sample output:
+```
+================================================================================
+Available Ant Versions
+================================================================================
+> * 1.10.1
+1.10.0
+1.9.9
+1.9.8
+1.9.7
+
+================================================================================
++ - local version
+* - installed
+> - currently in use
+================================================================================
+
+```
+
+Like I already said, If you have installed multiple versions, SDKMAN will prompt you if you want the currently installed version to be set as **default**. You can answer Yes to set it as default. Also, you can do that later by using the following command:
+```
+$ sdk default ant 1.9.9
+
+```
+
+The above command will set Apache Ant version 1.9.9 as default.
+
+You can choose which version of an installed candidate to use by using the following command:
+```
+$ sdk use ant 1.9.9
+
+```
+
+To check what is currently in use for a Candidate, for example Java, run:
+```
+$ sdk current java
+
+Using java version 8.0.172-zulu
+
+```
+
+To check what is currently in use for all Candidates, for example Java, run:
+```
+$ sdk current
+
+Using:
+
+ant: 1.10.1
+java: 8.0.172-zulu
+
+```
+
+To upgrade an outdated candidate, do:
+```
+$ sdk upgrade scala
+
+```
+
+You can also check what is outdated for all Candidates as well.
+```
+$ sdk upgrade
+
+```
+
+SDKMAN has offline mode feature that allows the SDKMAN to function when working offline. You can enable or disable the offline mode at any time by using the following commands:
+```
+$ sdk offline enable
+
+$ sdk offline disable
+
+```
+
+To remove an installed SDK, run:
+```
+$ sdk uninstall ant 1.9.9
+
+```
+
+For more details, check the help section.
+```
+$ sdk help
+
+Usage: sdk [candidate] [version]
+sdk offline
+
+commands:
+install or i [version]
+uninstall or rm
+list or ls [candidate]
+use or u [version]
+default or d [version]
+current or c [candidate]
+upgrade or ug [candidate]
+version or v
+broadcast or b
+help or h
+offline [enable|disable]
+selfupdate [force]
+update
+flush
+
+candidate : the SDK to install: groovy, scala, grails, gradle, kotlin, etc.
+ use list command for comprehensive list of candidates
+ eg: $ sdk list
+
+version : where optional, defaults to latest stable if not provided
+ eg: $ sdk install groovy
+
+```
+
+### Update SDKMAN
+
+The following command installs a new version of SDKMAN if it is available.
+```
+$ sdk selfupdate
+
+```
+
+SDKMAN will also periodically check for any updates and let you know with instruction on how to update.
+```
+WARNING: SDKMAN is out-of-date and requires an update.
+
+$ sdk update
+Adding new candidates(s): scala
+
+```
+
+### Remove cache
+
+It is recommended to clean the cache that contains the downloaded SDK binaries for time to time. To do so, simply run:
+```
+$ sdk flush archives
+
+```
+
+It is also good to clean temporary folder to save up some space:
+```
+$ sdk flush temp
+
+```
+
+### Uninstall SDKMAN
+
+If you don’t need SDKMAN or don’t like it, remove as shown below.
+```
+$ tar zcvf ~/sdkman-backup_$(date +%F-%kh%M).tar.gz -C ~/ .sdkman
+$ rm -rf ~/.sdkman
+
+```
+
+Finally, open your **.bashrc** , **.bash_profile** and/or **.profile** files and find and remove the following lines.
+```
+#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
+export SDKMAN_DIR="/home/sk/.sdkman"
+[[ -s "/home/sk/.sdkman/bin/sdkman-init.sh" ]] && source "/home/sk/.sdkman/bin/sdkman-init.sh"
+
+```
+
+If you use ZSH, remove the above line from the **.zshrc** file.
+
+And, that’s all for today. I hope you find SDKMAN useful. More good stuffs to come. Stay tuned!
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/sdkman-a-cli-tool-to-easily-manage-multiple-software-development-kits/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
diff --git a/sources/tech/20180806 GPaste Is A Great Clipboard Manager For Gnome Shell.md b/sources/tech/20180806 GPaste Is A Great Clipboard Manager For Gnome Shell.md
new file mode 100644
index 0000000000..c3b2d2b77e
--- /dev/null
+++ b/sources/tech/20180806 GPaste Is A Great Clipboard Manager For Gnome Shell.md
@@ -0,0 +1,96 @@
+GPaste Is A Great Clipboard Manager For Gnome Shell
+======
+**[GPaste][1] is a clipboard management system that consists of a library, daemon, and interfaces for the command line and Gnome (using a native Gnome Shell extension).**
+
+A clipboard manager allows keeping track of what you're copying and pasting, providing access to previously copied items. GPaste, with its native Gnome Shell extension, makes the perfect addition for those looking for a Gnome clipboard manager.
+
+[![GPaste Gnome Shell extension Ubuntu 18.04][2]][3]
+GPaste Gnome Shell extension
+**Using GPaste in Gnome, you get a configurable, searchable clipboard history, available with a click on the top panel. GPaste remembers not only the text you copy, but also file paths and images** (the latter needs to be enabled from its settings as it's disabled by default).
+
+What's more, GPaste can detect growing lines, meaning it can detect when a new text copy is an extension of another and replaces it if it's true, useful for keeping your clipboard clean.
+
+From the extension menu you can pause GPaste from tracking the clipboard, and remove items from the clipboard history or the whole history. You'll also find a button that launches the GPaste user interface window.
+
+**If you prefer to use the keyboard, you can use a key shortcut to open the GPaste history from the top bar** (`Ctrl + Alt + H`), **or open the full GPaste GUI** (`Ctrl + Alt + G`).
+
+The tool also incorporates keyboard shortcuts to (can be changed):
+
+ * delete the active item from history: `Ctrl + Alt + V`
+
+ * **mark the active item as being a password (which obfuscates the clipboard entry in GPaste):** `Ctrl + Alt + S`
+
+ * sync the clipboard to the primary selection: `Ctrl + Alt + O`
+
+ * sync the primary selection to the clipboard: `Ctrl + Alt + P`
+
+ * upload the active item to a pastebin service: `Ctrl + Alt + U`
+
+[![][4]][5]
+GPaste GUI
+
+The GPaste interface window provides access to the clipboard history (with options to clear, edit or upload items), which can be searched, an option to pause GPaste from tracking the clipboard, restart the GPaste daemon, backup current clipboard history, as well as to its settings.
+
+[![][6]][7]
+GPaste GUI
+
+From the GPaste UI you can change settings like:
+
+ * Enable or disable the Gnome Shell extension
+ * Sync the daemon state with the extension's one
+ * Primary selection affects history
+ * Synchronize clipboard with primary selection
+ * Image support
+ * Trim items
+ * Detect growing lines
+ * Save history
+ * History settings like max history size, memory usage, max text item length, and more
+ * Keyboard shortcuts
+
+
+
+### Download GPaste
+
+[Download GPaste](https://github.com/Keruspe/GPaste)
+
+The Gpaste project page does not link to any GPaste binaries, and only source installation instructions. Users running Linux distributions other than Debian or Ubuntu (for which you'll find GPaste installation instructions below) can search their distro repositories for GPaste.
+
+Do not confuse GPaste with the GPaste Integration extension posted on the Gnome Shell extension website. That is a Gnome Shell extension that uses GPaste daemon, which is no longer maintained. The native Gnome Shell extension built into GPaste is still maintained.
+
+#### Install GPaste in Ubuntu (18.04, 16.04) or Debian (Jessie and newer)
+
+**For Debian, GPaste is available for Jessie and newer, while for Ubuntu, GPaste is in the repositories for 16.04 and newer (so it's available in the Ubuntu 18.04 Bionic Beaver).**
+
+**You can install GPaste (the daemon and the Gnome Shell extension) in Debian or Ubuntu using this command:**
+```
+sudo apt install gnome-shell-extensions-gpaste gpaste
+
+```
+
+After the installation completes, restart Gnome Shell by pressing `Alt + F2` and typing `r` , then pressing the `Enter` key. The GPaste Gnome Shell extension should now be enabled and its icon should show up on the top Gnome Shell panel. If it's not, use Gnome Tweaks (Gnome Tweak Tool) to enable the extension.
+
+**The GPaste 3.28.0 package from[Debian][8] and [Ubuntu][9] has a bug that makes it crash if the image support option is enabled, so do not enable this feature for now.** This was marked as
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxuprising.com/2018/08/gpaste-is-great-clipboard-manager-for.html
+
+作者:[Logix][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://plus.google.com/118280394805678839070
+[1]:https://github.com/Keruspe/GPaste
+[2]:https://2.bp.blogspot.com/-2ndArDBcrwY/W2gyhMc1kEI/AAAAAAAABS0/ZAe_onuGCacMblF733QGBX3XqyZd--WuACLcBGAs/s400/gpaste-gnome-shell-extension-ubuntu1804.png (Gpaste Gnome Shell)
+[3]:https://2.bp.blogspot.com/-2ndArDBcrwY/W2gyhMc1kEI/AAAAAAAABS0/ZAe_onuGCacMblF733QGBX3XqyZd--WuACLcBGAs/s1600/gpaste-gnome-shell-extension-ubuntu1804.png
+[4]:https://2.bp.blogspot.com/-7FBRsZJvYek/W2gyvzmeRxI/AAAAAAAABS4/LhokMFSn8_kZndrNB-BTP4W3e9IUuz9BgCLcBGAs/s640/gpaste-gui_1.png
+[5]:https://2.bp.blogspot.com/-7FBRsZJvYek/W2gyvzmeRxI/AAAAAAAABS4/LhokMFSn8_kZndrNB-BTP4W3e9IUuz9BgCLcBGAs/s1600/gpaste-gui_1.png
+[6]:https://4.bp.blogspot.com/-047ShYc6RrQ/W2gyz5FCf_I/AAAAAAAABTA/-o6jaWzwNpsSjG0QRwRJ5Xurq_A6dQ0sQCLcBGAs/s640/gpaste-gui_2.png
+[7]:https://4.bp.blogspot.com/-047ShYc6RrQ/W2gyz5FCf_I/AAAAAAAABTA/-o6jaWzwNpsSjG0QRwRJ5Xurq_A6dQ0sQCLcBGAs/s1600/gpaste-gui_2.png
+[8]:https://packages.debian.org/buster/gpaste
+[9]:https://launchpad.net/ubuntu/+source/gpaste
+[10]:https://www.imagination-land.org/posts/2018-04-13-gpaste-3.28.2-released.html
diff --git a/sources/tech/20180806 How ProPublica Illinois uses GNU Make to load 1.4GB of data every day.md b/sources/tech/20180806 How ProPublica Illinois uses GNU Make to load 1.4GB of data every day.md
new file mode 100644
index 0000000000..f5cd367985
--- /dev/null
+++ b/sources/tech/20180806 How ProPublica Illinois uses GNU Make to load 1.4GB of data every day.md
@@ -0,0 +1,126 @@
+How ProPublica Illinois uses GNU Make to load 1.4GB of data every day
+======
+
+
+
+I avoided using GNU Make in my data journalism work for a long time, partly because the documentation was so obtuse that I couldn’t see how Make, one of many extract-transform-load (ETL) processes, could help my day-to-day data reporting. But this year, to build [The Money Game][1], I needed to load 1.4GB of Illinois political contribution and spending data every day, and the ETL process was taking hours, so I gave Make another chance.
+
+Now the same process takes less than 30 minutes.
+
+Here’s how it all works, but if you want to skip directly to the code, [we’ve open-sourced it here][2].
+
+Fundamentally, Make lets you say:
+
+ * File X depends on a transformation applied to file Y
+ * If file X doesn’t exist, apply that transformation to file Y and make file X
+
+
+
+This “start with file Y to get file X” pattern is a daily reality of data journalism, and using Make to load political contribution and spending data was a great use case. The data is fairly large, accessed via a slow FTP server, has a quirky format, has just enough integrity issues to keep things interesting, and needs to be compatible with a legacy codebase. To tackle it, I needed to start from the beginning.
+
+### Overview
+
+The financial disclosure data we’re using is from the Illinois State Board of Elections, but the [Illinois Sunshine project][3] had released open source code (no longer available) to handle the ETL process and fundraising calculations. Using their code, the ETL process took about two hours to run on robust hardware and over five hours on our servers, where it would sometimes fail for reasons I never quite understood. I needed it to work better and work faster.
+
+The process looks like this:
+
+ * **Download** data files via FTP from Illinois State Board Of Elections.
+ * **Clean** the data using Python to resolve integrity issues and create clean versions of the data files.
+ * **Load** the clean data into PostgreSQL using its highly efficient but finicky “\copy” command.
+ * **Transform** the data in the database to clean up column names and provide more immediately useful forms of the data using “raw” and “public” PostgreSQL schemas and materialized views (essentially persistently cached versions of standard SQL views).
+
+
+
+The cleaning step must happen before any data is loaded into the database, so we can take advantage of PostgreSQL’s efficient import tools. If a single row has a string in a column where it’s expecting an integer, the whole operation fails.
+
+GNU Make is well-suited to this task. Make’s model is built around describing the output files your ETL process should produce and the operations required to go from a set of original source files to a set of output files.
+
+As with any ETL process, the goal is to preserve your original data, keep operations atomic and provide a simple and repeatable process that can be run over and over.
+
+Let’s examine a few of the steps:
+
+### Download and pre-import cleaning
+
+Take a look at this snippet, which could be a standalone Makefile:
+```
+data/download/%.txt : aria2c -x5 -q -d data/download --ftp-user="$(ILCAMPAIGNCASH_FTP_USER)" --ftp-passwd="$(ILCAMPAIGNCASH_FTP_PASSWD)" ftp://ftp.elections.il.gov/CampDisclDataFiles/$*.txt data/processed/%.csv : data/download/%.txt python processors/clean_isboe_tsv.py $< $* > $@
+
+```
+
+This snippet first downloads a file via FTP and then uses Python to process it. For example, if “Expenditures.txt” is one of my source data files, I can run `make data/processed/Expenditures.csv` to download and process the expenditure data.
+
+There are two things to note here.
+
+The first is that we use [Aria2][4] to handle FTP duties. Earlier versions of the script used other FTP clients that were either slow as molasses or painful to use. After some trial and error, I found Aria2 did the job better than lftp (which is fast but fussy) or good old ftp (which is both slow and fussy). I also found some incantations that took download times from roughly an hour to less than 20 minutes.
+
+Second, the cleaning step is crucial for this dataset. It uses a simple class-based Python validation scheme you can [see here][5]. The important thing to note is that while Python is pretty slow generally, Python 3 is fast enough for this. And as long as you are [only processing row-by-row][6] without any objects accumulating in memory or doing any extra disk writes, performance is fine, even on low-resource machines like the servers in ProPublica’s cluster, and there aren’t any unexpected quirks.
+
+### Loading
+
+Make is built around file inputs and outputs. But what happens if our data is both in files and database tables? Here are a few valuable tricks I learned for integrating database tables into Makefiles:
+
+**One SQL file per table / transform** : Make loves both files and simple mappings, so I created individual files with the schema definitions for each table or any other atomic table-level operation. The table names match the SQL filenames, the SQL filenames match the source data filenames. You can see them [here][7].
+
+**Use exit code magic to make tables look like files to Make** : Hannah Cushman and Forrest Gregg from DataMade [introduced me to this trick on Twitter][8]. Make can be fooled into treating tables like files if you prefix table level commands with commands that emit appropriate exit codes. If a table exists, emit a successful code. If it doesn’t, emit an error.
+
+Beyond that, loading consists solely of the highly efficient PostgreSQL `\copy` command. While the `COPY` command is even more efficient, it doesn’t play nicely with Amazon RDS. Even if ProPublica moved to a different database provider, I’d continue to use `\copy` for portability unless eking out a little more performance was mission-critical.
+
+There’s one last curveball: The loading step imports data to a PostgreSQL schema called `raw` so that we can cleanly transform the data further. Postgres schemas provide a useful way of segmenting data within a single database — instead of a single namespace with tables like `raw_contributions` and `clean_contributions`, you can keep things simple and clear with an almost folder-like structure of `raw.contributions` and `public.contributions`.
+
+### Post-import transformations
+
+The Illinois Sunshine code also renames columns and slightly reshapes the data for usability and performance reasons. Column aliasing is useful for end users and the intermediate tables are required for compatibility with the legacy code.
+
+In this case, the loader imports into a schema called `raw` that is as close to the source data as humanly possible.
+
+The data is then transformed by creating materialized views of the raw tables that rename columns and handle some light post-processing. This is enough for our purposes, but more elaborate transformations could be applied without sacrificing clarity or obscuring the source data. Here’s a snippet of one of these view definitions:
+```
+CREATE MATERIALIZED VIEW d2_reports AS SELECT id as id, committeeid as committee_id, fileddocid as filed_doc_id, begfundsavail as beginning_funds_avail, indivcontribi as individual_itemized_contrib, indivcontribni as individual_non_itemized_contrib, xferini as transfer_in_itemized, xferinni as transfer_in_non_itemized, # …. FROM raw.d2totals WITH DATA;
+```
+
+These transformations are very simple, but simply using more readable column names is a big improvement for end-users.
+
+As with table schema definitions, there is a file for each table that describes the transformed view. We use materialized views, which, again, are essentially persistently cached versions of standard SQL views, because storage is cheap and they are faster than traditional SQL views.
+
+### A note about security
+
+You’ll notice we use environment variables that are expanded inline when the commands are run. That’s useful for debugging and helps with portability. But it’s not a good idea if you think log files or terminal output could be compromised or people who shouldn’t know these secrets have access to logs or shared systems. For more security, you could use a system like the PostgreSQL `pgconf` file and remove the environment variable references.
+
+### Makefiles for the win
+
+My only prior experience with Make was in a computational math course 15 years ago, where it was a frustrating and poorly explained footnote. The combination of obtuse documentation, my bad experience in school and an already reliable framework kept me away. Plus, my shell scripts and Python Fabric/Invoke code were doing a fine job building reliable data processing pipelines based on the same principles for the smaller, quick turnaround projects I was doing.
+
+But after trying Make for this project, I was more than impressed with the results. It’s concise and expressive. It enforces atomic operations, but rewards them with dead simple ways to handle partial builds, which is a big deal during development when you really don’t want to be repeating expensive operations to test individual components. Combined with PostgreSQL’s speedy import tools, schemas, and materialized views, I was able to load the data in a fraction of the time. And just as important, the performance of the new process is less sensitive to varying system resources.
+
+If you’re itching to get started with Make, here are a few additional resources:
+
++ [Making Data, The Datamade Way][9], by Hannah Cushman. My original inspiration.
++ [“Why Use Make”][10] by Mike Bostock.
++ [“Practical Makefiles, by example”][11] by John Tsiombikas is a nice resource if you want to dig deeper, but Make’s documentation is intimidating.
+
+
+In the end, the best build/processing system is any system that never alters source data, clearly shows transformations, uses version control and can be easily run over and over. Grunt, Gulp, Rake, Make, Invoke … you have options. As long as you like what you use and use it religiously, your work will benefit.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/how-propublica-illinois-uses-gnu-make
+
+作者:[David Eads][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/eads
+[1]:https://www.propublica.org/article/illinois-governors-race-campaign-widget-update
+[2]:https://github.com/propublica/ilcampaigncash/
+[3]:https://illinoissunshine.org/
+[4]:https://aria2.github.io/
+[5]:https://github.com/propublica/ilcampaigncash/blob/master/processors/lib/models.py
+[6]:https://github.com/propublica/ilcampaigncash/blob/master/processors/clean_isboe_tsv.py#L13
+[7]:https://github.com/propublica/ilcampaigncash/tree/master/sql/tables
+[8]:https://twitter.com/eads/status/968970130427404293
+[9]: https://github.com/datamade/data-making-guidelines
+[10]: https://bost.ocks.org/mike/make/
+[11]: http://nuclear.mutantstargoat.com/articles/make/
diff --git a/sources/tech/20180806 Recreate Famous Data Decryption Effect Seen On Sneakers Movie.md b/sources/tech/20180806 Recreate Famous Data Decryption Effect Seen On Sneakers Movie.md
new file mode 100644
index 0000000000..9deb3242db
--- /dev/null
+++ b/sources/tech/20180806 Recreate Famous Data Decryption Effect Seen On Sneakers Movie.md
@@ -0,0 +1,110 @@
+Recreate Famous Data Decryption Effect Seen On Sneakers Movie
+======
+
+
+
+A while ago, we published a guide that described how to [**turn your Ubuntu Linux console into a veritable Hollywood technical melodrama hacker interface**][1] using **Hollywood** utility which is written by **Dustin Kirkland** from Canonical. Today, I have stumbled upon a similar CLI utility named “ **N** o **M** ore **S** ecrets”, shortly **nms**. Like Hollywood utility, the nms utility is also **USELESS** (Sorry!). You can use it just for fun. The nms will recreate the famous data decryption effect seen on Sneakers, released in 1992.
+
+[**Sneakers**][2] is a comedy and crime-thriller genre movie, starred by **Robert Redford** among other famous actors named **Dan Aykroyd** , **David Strathairn** and **Ben Kingsley**. This movie is one of the popular hacker movie released in 1990s. If you haven’t watched it already, there is [**a scene**][3] in Sneakers movie where a group of experts who specialize in testing security systems will recover a top secret black box that has the ability to decrypt all existing encryption systems around the world. The nms utility simply simulates how exactly the data decryption effect scene looks like on Sneakers movie in your Terminal.
+
+### Installing Nms
+
+The nms project has no dependencies, but it relies on ANSI/VT100 terminal escape sequences to recreate the effect. Most modern terminal programs support these sequences by default. Just in case, if your Terminal doesn’t support these sequences, install **ncurses**. Ncurses is available in the default repositories of most Linux distributions. We are going to compile and install nms from source. So, just make sure you have installed the development tools in your Linux box. If you haven’t installed them already, refer the following links.
+
+After installing, git, make, and gcc development tools, run the following commands one by one to compile and install nms utility.
+```
+$ git clone https://github.com/bartobri/no-more-secrets.git
+$ cd ./no-more-secrets
+$ make nms
+$ make sneakers
+$ sudo make install
+
+```
+
+Finally, check if the installation was successful using command:
+```
+$ nms -v
+nms version 0.3.3
+
+```
+
+Alternatively, you can install nms using [**Linuxbrew**][4] package manager as shown below.
+```
+$ brew install no-more-secrets
+
+```
+
+Now it is time to run nms.
+
+### Recreate Famous Data Decryption Effect Seen On Sneakers Movie Using Nms
+
+The nms utility works on piped data. Pipe any Linux command’s output to nms tool like below and enjoy the effect right from your Terminal. Have a look at the following command:
+```
+$ ls -l | nms
+
+```
+
+By default, after the initial encrypted characters are displayed, the **nms** utility will wait for the user to press a key to start the decryption sequence. This is how the it is depicted in the Sneakers movie. Just press any key to start the decryption sequence to reveal the original plaintext characters.
+
+If you don’t want to press any key, you can auto-initiate the decryption sequence using **-a** flag.
+```
+$ ls -l | nms -a
+
+```
+
+You can also set a foreground color, for example green, use **-f ** option as shown below.
+```
+$ ls -l | nms -f green
+
+```
+
+Remember If you don’t specify **-a** flag, you must press any key to initiate the decryption sequence.
+
+To clear the screen before starting encryption and decryption processes, use **-c** flag.
+```
+$ ls -l | nms -c
+
+```
+
+To mask single blank space characters, use -s flag. Please note that other space characters such as tabs and newlines will not be masked.
+```
+$ ls -l | nms -s
+
+```
+
+You can also view the actual decryption effect scene in the Sneakers movie using the following command:
+```
+$ sneakers
+
+```
+
+Choose any option given to exit this utility.
+
+Don’t like it? Sorry about that. Go to the nms project folder and simply run the following command to remove it.
+```
+$ sudo make uninstall
+
+```
+
+And, that’s all for now. More good stuffs to come. Stay tuned!
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/no-more-secrets-recreate-famous-data-decryption-effect-seen-on-sneakers-movie/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
+[1]:https://www.ostechnix.com/turn-ubuntu-terminal-hollywood-technical-melodrama-hacker-interface/
+[2]:https://www.imdb.com/title/tt0105435/
+[3]:https://www.youtube.com/watch?v=F5bAa6gFvLs&t=35
+[4]:https://www.ostechnix.com/linuxbrew-common-package-manager-linux-mac-os-x/
diff --git a/sources/tech/20180806 Systemd Timers- Three Use Cases.md b/sources/tech/20180806 Systemd Timers- Three Use Cases.md
new file mode 100644
index 0000000000..7d1d4cac97
--- /dev/null
+++ b/sources/tech/20180806 Systemd Timers- Three Use Cases.md
@@ -0,0 +1,220 @@
+Systemd Timers: Three Use Cases
+======
+
+
+
+In this systemd tutorial series, we have[ already talked about systemd timer units to some degree][1], but, before moving on to the sockets, let's look at three examples that illustrate how you can best leverage these units.
+
+### Simple _cron_ -like behavior
+
+This is something I have to do: collect [popcon data from Debian][2] every week, preferably at the same time so I can see how the downloads for certain applications evolve. This is the typical thing you can have a _cron_ job do, but a systemd timer can do it too:
+```
+# cron-like popcon.timer
+
+[Unit]
+Description= Says when to download and process popcons
+
+[Timer]
+OnCalendar= Thu *-*-* 05:32:07
+Unit= popcon.service
+
+[Install]
+WantedBy= basic.target
+
+```
+
+The actual _popcon.service_ runs a regular _wget_ job, so nothing special. What is new in here is the `OnCalendar=` directive. This is what lets you set a service to run on a certain date at a certain time. In this case, `Thu` means " _run on Thursdays_ " and the `*-*-*` means " _the exact date, month and year don't matter_ ", which translates to " _run on Thursday, regardless of the date, month or year_ ".
+
+Then you have the time you want to run the service. I chose at about 5:30 am CEST, which is when the server is not very busy.
+
+If the server is down and misses the weekly deadline, you can also work an _anacron_ -like functionality into the same timer:
+```
+# popcon.timer with anacron-like functionality
+
+[Unit]
+Description=Says when to download and process popcons
+
+[Timer]
+Unit=popcon.service
+OnCalendar=Thu *-*-* 05:32:07
+Persistent=true
+
+[Install]
+WantedBy=basic.target
+
+```
+
+When you set the `Persistent=` directive to true, it tells systemd to run the service immediately after booting if the server was down when it was supposed to run. This means that if the machine was down, say for maintenance, in the early hours of Thursday, as soon as it is booted again, _popcon.service_ will be run immediately and then it will go back to the routine of running the service every Thursday at 5:32 am.
+
+So far, so straightforward.
+
+### Delayed execution
+
+But let's kick thing up a notch and "improve" the [systemd-based surveillance system][3]. Remember that the system started taking pictures the moment you plugged in a camera. Suppose you don't want pictures of your face while you install the camera. You will want to delay the start up of the picture-taking service by a minute or two so you can plug in the camera and move out of frame.
+
+To do this; first change the Udev rule so it points to a timer:
+```
+ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="03f0",
+ATTRS{idProduct}=="e207", TAG+="systemd", ENV{SYSTEMD_WANTS}="picchanged.timer",
+SYMLINK+="mywebcam", MODE="0666"
+
+```
+
+The timer looks like this:
+```
+# picchanged.timer
+
+[Unit]
+Description= Runs picchanged 1 minute after the camera is plugged in
+
+[Timer]
+OnActiveSec= 1 m
+Unit= picchanged.path
+
+[Install]
+WantedBy= basic.target
+
+```
+
+The Udev rule gets triggered when you plug the camera in and it calls the timer. The timer waits for one minute after it starts (`OnActiveSec= 1 m`) and then runs _picchanged.path_ , which [monitors to see if the master image changes][4]. The _picchanged.path_ is also in charge of pulling in the _webcam.service_ , the service that actually takes the picture.
+
+### Start and stop Minetest server at a certain time every day
+
+In the final example, let's say you have decided to delegate parenting to systemd. I mean, systemd seems to be already taking over most of your life anyway. Why not embrace the inevitable?
+
+So you have your Minetest service set up for your kids. You also want to give some semblance of caring about their education and upbringing and have them do homework and chores. What you want to do is make sure Minetest is only available for a limited time (say from 5 pm to 7 pm) every evening.
+
+This is different from " _starting a service at certain time_ " in that, writing a timer to start the service at 5 pm is easy...:
+```
+# minetest.timer
+
+[Unit]
+Description= Runs the minetest.service at 5pm everyday
+
+[Timer]
+OnCalendar= *-*-* 17:00:00
+Unit= minetest.service
+
+[Install]
+WantedBy= basic.target
+
+```
+
+... But writing a counterpart timer that shuts down a service at a certain time needs a bigger dose of lateral thinking.
+
+Let's start with the obvious -- the timer:
+```
+# stopminetest.timer
+
+[Unit]
+Description= Stops the minetest.service at 7 pm everyday
+
+[Timer]
+OnCalendar= *-*-* 19:05:00
+Unit= stopminetest.service
+
+[Install]
+WantedBy= basic.target
+
+```
+
+The tricky part is how to tell _stopminetest.service_ to actually, you know, stop the Minetest. There is no way to pass the PID of the Minetest server from _minetest.service_. and there are no obvious commands in systemd's unit vocabulary to stop or disable a running service.
+
+The trick is to use systemd's `Conflicts=` directive. The `Conflicts=` directive is similar to systemd's `Wants=` directive, in that it does _exactly the opposite_. If you have `Wants=a.service` in a unit called _b.service_ , when it starts, _b.service_ will run _a.service_ if it is not running already. Likewise, if you have a line that reads `Conflicts= a.service` in your _b.service_ unit, as soon as _b.service_ starts, systemd will stop _a.service_.
+
+This was created for when two services could clash when trying to take control of the same resource simultaneously, say when two services needed to access your printer at the same time. By putting a `Conflicts=` in your preferred service, you could make sure it would override the least important one.
+
+You are going to use `Conflicts=` a bit differently, however. You will use `Conflicts=` to close down cleanly the _minetest.service_ :
+```
+# stopminetest.service
+
+[Unit]
+Description= Closes down the Minetest service
+Conflicts= minetest.service
+
+[Service]
+Type= oneshot
+ExecStart= /bin/echo "Closing down minetest.service"
+
+```
+
+The _stopminetest.service_ doesn't do much at all. Indeed, it could do nothing at all, but just because it contins that `Conflicts=` line in there, when it is started, systemd will close down _minetest.service_.
+
+There is one last wrinkle in your perfect Minetest set up: What happens if you are late home from work, it is past the time when the server should be up but playtime is not over? The `Persistent=` directive (see above) that runs a service if it has missed its start time is no good here, because if you switch the server on, say at 11 am, it would start Minetest and that is not what you want. What you really want is a way to make sure that systemd will only start Minetest between the hours of 5 and 7 in the evening:
+```
+# minetest.timer
+
+[Unit]
+Description= Runs the minetest.service every minute between the hours of 5pm and 7pm
+
+[Timer]
+OnCalendar= *-*-* 17..19:*:00
+Unit= minetest.service
+
+[Install]
+WantedBy= basic.target
+
+```
+
+The line `OnCalendar= *-*-* 17..19:*:00` is interesting for two reasons: (1) `17..19` is not a point in time, but a period of time, in this case the period of time between the times of 17 and 19; and (2) the `*` in the minute field indicates that the service must be run every minute. Hence, you would read this as " _run the minetest.service every minute between 5 and 7 pm_ ".
+
+There is still one catch, though: once the _minetest.service_ is up and running, you want _minetest.timer_ to stop trying to run it again and again. You can do that by including a `Conflicts=` directive into _minetest.service_ :
+```
+# minetest.service
+
+[Unit]
+Description= Runs Minetest server
+Conflicts= minetest.timer
+
+[Service]
+Type= simple
+User=
+
+ExecStart= /usr/bin/minetest --server
+ExecStop= /bin/kill -2 $MAINPID
+
+[Install]
+WantedBy= multi-user.targe
+
+```
+
+The `Conflicts=` directive shown above makes sure _minetest.timer_ is stopped as soon as the _minetest.service_ is successfully started.
+
+Now enable and start _minetest.timer_ :
+```
+systemctl enable minetest.timer
+systemctl start minetest.timer
+
+```
+
+And, if you boot the server at, say, 6 o'clock, _minetest.timer_ will start up and, as the time falls between 5 and 7, _minetest.timer_ will try and start _minetest.service_ every minute. But, as soon as _minetest.service_ is running, systemd will stop _minetest.timer_ because it "conflicts" with _minetest.service_ , thus avoiding the timer from trying to start the service over and over when it is already running.
+
+It is a bit counterintuitive that you use the service to kill the timer that started it up in the first place, but it works.
+
+### Conclusion
+
+You probably think that there are better ways of doing all of the above. I have heard the term "overengineered" in regard to these articles, especially when using systemd timers instead of cron.
+
+But, the purpose of this series of articles is not to provide the best solution to any particular problem. The aim is to show solutions that use systemd units as much as possible, even to a ridiculous length. The aim is to showcase plenty of examples of how the different types of units and the directives they contain can be leveraged. It is up to you, the reader, to find the real practical applications for all of this.
+
+Be that as it may, there is still one more thing to go: next time, we'll be looking at _sockets_ and _targets_ , and then we'll be done with systemd units.
+
+Learn more about Linux through the free ["Introduction to Linux" ][5]course from The Linux Foundation and edX.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/intro-to-linux/2018/8/systemd-timers-two-use-cases-0
+
+作者:[Paul Brown][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://www.linux.com/users/bro66
+[1]:https://www.linux.com/blog/learn/intro-to-linux/2018/7/setting-timer-systemd-linux
+[2]:https://popcon.debian.org/
+[3]:https://www.linux.com/blog/intro-to-linux/2018/6/systemd-services-reacting-change
+[4]:https://www.linux.com/blog/learn/intro-to-linux/2018/6/systemd-services-monitoring-files-and-directories
+[5]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180806 Use Gstreamer and Python to rip CDs.md b/sources/tech/20180806 Use Gstreamer and Python to rip CDs.md
new file mode 100644
index 0000000000..7b78184ad9
--- /dev/null
+++ b/sources/tech/20180806 Use Gstreamer and Python to rip CDs.md
@@ -0,0 +1,312 @@
+Use Gstreamer and Python to rip CDs
+======
+
+
+
+In a previous article, you learned how to use the MusicBrainz service to provide tag information for your audio files, using a simple Python script. This article shows you how to also script an all-in-one solution to copy your CDs down to a music library folder in your choice of formats.
+
+Unfortunately, the powers that be make it impossible for Fedora to carry the necessary bits to encode MP3 in official repos. So that part is left as an exercise for the reader. But if you use a cloud service such as Google Play to host your music, this script makes audio files you can upload easily.
+
+The script will record your CD down to one of the following file formats:
+
+ * Uncompressed WAV, which you can further encode or play with.
+ * Compressed but lossless FLAC. Lossless files preserve all the fidelity of the original audio.
+ * Compressed, lossy Ogg Vorbis. Like MP3 and Apple’s AAC, Ogg Vorbis uses special algorithms and psychoacoustic properties to sound close to the original audio. However, Ogg Vorbis usually produces superior results to those other compressed formats at the same file sizes. You can[read more about it here][1] if you like technical details.
+
+
+
+### The components
+
+The first element of the script is a [GStreamer][2] pipeline. GStreamer is a full featured multimedia framework included in Fedora. It comes [installed by default in Workstation][3], too. GStreamer is used behind the scene by many multimedia apps in Fedora. It lets apps manipulate all kinds of video and audio files.
+
+The second major component in this script is choosing, and using, a multimedia tagging library. In this case [the mutagen library][4] makes it easy to tag many kinds of multimedia files. The script in this article uses mutagen to tag Ogg Vorbis or FLAC files.
+
+Finally, the script uses [Python’s argparse, part of the standard library][5], for some easy to use options and help text. The argparse library is useful for most Python scripts where you expect the user to provide parameters. This article won’t cover this part of the script in great detail.
+
+### The script
+
+You may recall [the previous article][6] that used MusicBrainz to fetch tag information. This script includes that code, with some tweaks to make it integrate better with the new functions. (You may find it easier to read this script if you copy and paste it into your favorite editor.)
+```
+#!/usr/bin/python3
+
+import os, sys
+import subprocess
+from argparse import ArgumentParser
+import libdiscid
+import musicbrainzngs as mb
+import requests
+import json
+from getpass import getpass
+
+parser = ArgumentParser()
+parser.add_argument('-f', '--flac', action='store_true', dest='flac',
+ default=False, help='Rip to FLAC format')
+parser.add_argument('-w', '--wav', action='store_true', dest='wav',
+ default=False, help='Rip to WAV format')
+parser.add_argument('-o', '--ogg', action='store_true', dest='ogg',
+ default=False, help='Rip to Ogg Vorbis format')
+options = parser.parse_args()
+
+# Set up output varieties
+if options.wav + options.ogg + options.flac > 1:
+ raise parser.error("Only one of -f, -o, -w please")
+if options.wav:
+ fmt = 'wav'
+ encoding = 'wavenc'
+elif options.flac:
+ fmt = 'flac'
+ encoding = 'flacenc'
+ from mutagen.flac import FLAC as audiofile
+elif options.ogg:
+ fmt = 'oga'
+ quality = 'quality=0.3'
+ encoding = 'vorbisenc {} ! oggmux'.format(quality)
+ from mutagen.oggvorbis import OggVorbis as audiofile
+
+# Get MusicBrainz info
+this_disc = libdiscid.read(libdiscid.default_device())
+mb.set_useragent(app='get-contents', version='0.1')
+mb.auth(u=input('Musicbrainz username: '), p=getpass())
+
+release = mb.get_releases_by_discid(this_disc.id, includes=['artists',
+ 'recordings'])
+if release.get('disc'):
+ this_release=release['disc']['release-list'][0]
+
+ album = this_release['title']
+ artist = this_release['artist-credit'][0]['artist']['name']
+ year = this_release['date'].split('-')[0]
+
+ for medium in this_release['medium-list']:
+ for disc in medium['disc-list']:
+ if disc['id'] == this_disc.id:
+ tracks = medium['track-list']
+ break
+
+ # We assume here the disc was found. If you see this:
+ # NameError: name 'tracks' is not defined
+ # ...then the CD doesn't appear in MusicBrainz and can't be
+ # tagged. Use your MusicBrainz account to create a release for
+ # the CD and then try again.
+
+ # Get cover art to cover.jpg
+ if this_release['cover-art-archive']['artwork'] == 'true':
+ url = 'http://coverartarchive.org/release/' + this_release['id']
+ art = json.loads(requests.get(url, allow_redirects=True).content)
+ for image in art['images']:
+ if image['front'] == True:
+ cover = requests.get(image['image'], allow_redirects=True)
+ fname = '{0} - {1}.jpg'.format(artist, album)
+ print('Saved cover art as {}'.format(fname))
+ f = open(fname, 'wb')
+ f.write(cover.content)
+ f.close()
+ break
+
+for trackn in range(len(tracks)):
+ track = tracks[trackn]['recording']['title']
+
+ # Output file name based on MusicBrainz values
+ outfname = '{:02} - {}.{}'.format(trackn+1, track, fmt).replace('/', '-')
+
+ print('Ripping track {}...'.format(outfname))
+ cmd = 'gst-launch-1.0 cdiocddasrc track={} ! '.format(trackn+1) + \
+ 'audioconvert ! {} ! '.format(encoding) + \
+ 'filesink location="{}"'.format(outfname)
+ msgs = subprocess.getoutput(cmd)
+
+ if not options.wav:
+ audio = audiofile(outfname)
+ print('Tagging track {}...'.format(outfname))
+ audio['TITLE'] = track
+ audio['TRACKNUMBER'] = str(trackn+1)
+ audio['ARTIST'] = artist
+ audio['ALBUM'] = album
+ audio['DATE'] = year
+ audio.save()
+
+```
+
+#### Determining output format
+
+This part of the script lets the user decide how to format the output files:
+```
+parser = ArgumentParser()
+parser.add_argument('-f', '--flac', action='store_true', dest='flac',
+ default=False, help='Rip to FLAC format')
+parser.add_argument('-w', '--wav', action='store_true', dest='wav',
+ default=False, help='Rip to WAV format')
+parser.add_argument('-o', '--ogg', action='store_true', dest='ogg',
+ default=False, help='Rip to Ogg Vorbis format')
+options = parser.parse_args()
+
+# Set up output varieties
+if options.wav + options.ogg + options.flac > 1:
+ raise parser.error("Only one of -f, -o, -w please")
+if options.wav:
+ fmt = 'wav'
+ encoding = 'wavenc'
+elif options.flac:
+ fmt = 'flac'
+ encoding = 'flacenc'
+ from mutagen.flac import FLAC as audiofile
+elif options.ogg:
+ fmt = 'oga'
+ quality = 'quality=0.3'
+ encoding = 'vorbisenc {} ! oggmux'.format(quality)
+ from mutagen.oggvorbis import OggVorbis as audiofile
+
+```
+
+The parser, built from the argparse library, gives you a built in –help function:
+```
+$ ipod-cd --help
+usage: ipod-cd [-h] [-b BITRATE] [-w] [-o]
+
+optional arguments:
+ -h, --help show this help message and exit
+ -b BITRATE, --bitrate BITRATE
+ Set a target bitrate
+ -w, --wav Rip to WAV format
+ -o, --ogg Rip to Ogg Vorbis format
+
+```
+
+The script allows the user to use -f, -w, or -o on the command line to choose a format. Since these are stored as True (a Python boolean value), they can also be treated as the integer value 1. If more than one is selected, the parser generates an error.
+
+Otherwise, the script sets an appropriate encoding string to be used with GStreamer later in the script. Notice the Ogg Vorbis selection also includes a quality setting, which is then included in the encoding. Care to try your hand at an easy change? Try making a parser argument and additional formatting code so the user can select a quality value between -0.1 and 1.0.
+
+Notice also that for each of the file formats that allows tagging (WAV does not), the script imports a different tagging class. This way the script can have simpler, less confusing tagging code later in the script. In this script, both Ogg Vorbis and FLAC are using classes from the mutagen library.
+
+#### Getting CD info
+
+The next section of the script attempts to load MusicBrainz info for the disc. You’ll find that audio files ripped with this script have data not included in the Python code here. This is because GStreamer is also capable of detecting CD-Text that’s included on some discs during the mastering and manufacturing process. Often, though, this data is in all capitals (like “TRACK TITLE”). MusicBrainz info is more compatible with modern apps and other platforms.
+
+For more information on this section, [refer to the previous article here on the Magazine][6]. A few trivial changes appear here to make the script work better as a single process.
+
+One item to note is this warning:
+```
+# We assume here the disc was found. If you see this:
+# NameError: name 'tracks' is not defined
+# ...then the CD doesn't appear in MusicBrainz and can't be
+# tagged. Use your MusicBrainz account to create a release for
+# the CD and then try again.
+
+```
+
+The script as shown doesn’t include a way to handle cases where CD information isn’t found. This is on purpose. If it happens, take a moment to help the community by [entering CD information on MusicBrainz][7], using your login account.
+
+#### Ripping and labeling tracks
+
+The next section of the script actually does the work. It’s a simple loop that iterates through the track list found via MusicBrainz.
+
+First, the script sets the output filename for the individual track based on the format the user selected:
+```
+for trackn in range(len(tracks)):
+ track = tracks[trackn]['recording']['title']
+
+ # Output file name based on MusicBrainz values
+ outfname = '{:02} - {}.{}'.format(trackn+1, track, fmt)
+
+```
+
+Then, the script calls a CLI GStreamer utility to perform the ripping and encoding process. That process turns each CD track into an audio file in your current directory:
+```
+ print('Ripping track {}...'.format(outfname))
+ cmd = 'gst-launch-1.0 cdiocddasrc track={} ! '.format(trackn+1) + \
+ 'audioconvert ! {} ! '.format(encoding) + \
+ 'filesink location="{}"'.format(outfname)
+ msgs = subprocess.getoutput(cmd)
+
+```
+
+The complete GStreamer pipeline would look like this at a command line:
+```
+gst-launch-1.0 cdiocddasrc track=1 ! audioconvert ! vorbisenc quality=0.3 ! oggmux ! filesink location="01 - Track Name.oga"
+
+```
+
+GStreamer has Python libraries to let you use the framework in interesting ways directly without using subprocess. To keep this article less complex, the script calls the command line utility from Python to do the multimedia work.
+
+Finally, the script labels the output file if it’s not a WAV file. Both Ogg Vorbis and FLAC use similar methods in their mutagen classes. That means this code can remain very simple:
+```
+ if not options.wav:
+ audio = audiofile(outfname)
+ print('Tagging track {}...'.format(outfname))
+ audio['TITLE'] = track
+ audio['TRACKNUMBER'] = str(trackn+1)
+ audio['ARTIST'] = artist
+ audio['ALBUM'] = album
+ audio['DATE'] = year
+ audio.save()
+
+```
+
+If you decide to write code for another file format, you need to import the correct class earlier, and then perform the tagging correctly. You don’t have to use the mutagen class. For instance, you might choose to use eyed3 for tagging MP3 files. In that case, the tagging code might look like this:
+```
+...
+# In the parser handling for MP3 format
+from eyed3 import load as audiofile
+...
+# In the handling for MP3 tags
+audio.tag.version = (2, 3, 0)
+audio.tag.artist = artist
+audio.tag.title = track
+audio.tag.album = album
+audio.tag.track_num = (trackn+1, len(tracks))
+audio.tag.save()
+
+```
+
+(Note the encoding function is up to you to provide.)
+
+### Running the script
+
+Here’s an example output of the script:
+```
+$ ipod-cd -o
+Ripping track 01 - Shout, Pt. 1.oga...
+Tagging track 01 - Shout, Pt. 1.oga...
+Ripping track 02 - Stars of New York.oga...
+Tagging track 02 - Stars of New York.oga...
+Ripping track 03 - Breezy.oga...
+Tagging track 03 - Breezy.oga...
+Ripping track 04 - Aeroplane.oga...
+Tagging track 04 - Aeroplane.oga...
+Ripping track 05 - Minor Is the Lonely Key.oga...
+Tagging track 05 - Minor Is the Lonely Key.oga...
+Ripping track 06 - You Can Come Round If You Want To.oga...
+Tagging track 06 - You Can Come Round If You Want To.oga...
+Ripping track 07 - I'm Gonna Haunt This Place.oga...
+Tagging track 07 - I'm Gonna Haunt This Place.oga...
+Ripping track 08 - Crash That Piano.oga...
+Tagging track 08 - Crash That Piano.oga...
+Ripping track 09 - Save Yourself.oga...
+Tagging track 09 - Save Yourself.oga...
+Ripping track 10 - Get on Home.oga...
+Tagging track 10 - Get on Home.oga...
+
+```
+
+Enjoy burning your old CDs into easily portable audio files!
+
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/use-gstreamer-python-rip-cds/
+
+作者:[Paul W. Frields][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://fedoramagazine.org/author/pfrields/
+[1]:https://xiph.org/vorbis/
+[2]:https://gstreamer.freedesktop.org/
+[3]:https://getfedora.org/workstation
+[4]:https://mutagen.readthedocs.io/en/latest/
+[5]:https://docs.python.org/3/library/argparse.html
+[6]:https://fedoramagazine.org/use-musicbrainz-get-cd-information/
+[7]:https://musicbrainz.org/
diff --git a/sources/tech/20180807 5 reasons the i3 window manager makes Linux better.md b/sources/tech/20180807 5 reasons the i3 window manager makes Linux better.md
new file mode 100644
index 0000000000..8ad6a4ac7d
--- /dev/null
+++ b/sources/tech/20180807 5 reasons the i3 window manager makes Linux better.md
@@ -0,0 +1,111 @@
+5 reasons the i3 window manager makes Linux better
+======
+
+
+
+One of the nicest things about Linux (and open source software in general) is the freedom to choose among different alternatives to address our needs.
+
+I've been using Linux for a long time, but I was never entirely happy with the desktop environment options available. Until last year, [Xfce][1] was the closest to what I consider a good compromise between features and performance. Then I found [i3][2], an amazing piece of software that changed my life.
+
+I3 is a tiling window manager. The goal of a window manager is to control the appearance and placement of windows in a windowing system. Window managers are often used as part a full-featured desktop environment (such as GNOME or Xfce), but some can also be used as standalone applications.
+
+A tiling window manager automatically arranges the windows to occupy the whole screen in a non-overlapping way. Other popular tiling window managers include [wmii][3] and [xmonad][4].
+
+![i3 tiled window manager screenshot][6]
+
+Screenshot of i3 with three tiled windows
+
+Following are the top five reasons I use the i3 window manager and recommend it for a better Linux desktop experience.
+
+### 1\. Minimalism
+
+I3 is fast. It is neither bloated nor fancy. It is designed to be simple and efficient. As a developer, I value these features, as I can use the extra capacity to power my favorite development tools or test stuff locally using containers or virtual machines.
+
+In addition, i3 is a window manager and, unlike full-featured desktop environments, it does not dictate the applications you should use. Do you want to use Thunar from Xfce as your file manager? GNOME's gedit to edit text? I3 does not care. Pick the tools that make the most sense for your workflow, and i3 will manage them all in the same way.
+
+### 2\. Screen real estate
+
+As a tiling window manager, i3 will automatically "tile" or position the windows in a non-overlapping way, similar to laying tiles on a wall. Since you don't need to worry about window positioning, i3 generally makes better use of your screen real estate. It also allows you to get to what you need faster.
+
+There are many useful cases for this. For example, system administrators can open several terminals to monitor or work on different remote systems simultaneously; and developers can use their favorite IDE or editor and a few terminals to test their programs.
+
+In addition, i3 is flexible. If you need more space for a particular window, enable full-screen mode or switch to a different layout, such as stacked or tabbed.
+
+### 3\. Keyboard-driven workflow
+
+I3 makes extensive use of keyboard shortcuts to control different aspects of your environment. These include opening the terminal and other programs, resizing and positioning windows, changing layouts, and even exiting i3. When you start using i3, you need to memorize a few of those shortcuts to get around and, with time, you'll use more of them.
+
+The main benefit is that you don't often need to switch contexts from the keyboard to the mouse. With practice, it means you'll improve the speed and efficiency of your workflow.
+
+For example, to open a new terminal, press `+`. Since the windows are automatically positioned, you can start typing your commands right away. Combine that with a nice terminal-driven text editor (e.g., Vim) and a keyboard-focused browser for a fully keyboard-driven workflow.
+
+In i3, you can define shortcuts for everything. Here are some examples:
+
+ * Open terminal
+ * Open browser
+ * Change layouts
+ * Resize windows
+ * Control music player
+ * Switch workspaces
+
+
+
+Now that I am used to this workflow, I can't see myself going back to a regular desktop environment.
+
+### 4\. Flexibility
+
+I3 strives to be minimal and use few system resources, but that does not mean it can't be pretty. I3 is flexible and can be customized in several ways to improve the visual experience. Because i3 is a window manager, it doesn't provide tools to enable customizations; you need external tools for that. Some examples:
+
+ * Use `feh` to define a background picture for your desktop.
+ * Use a compositor manager such as `compton` to enable effects like window fading and transparency.
+ * Use `dmenu` or `rofi` to enable customizable menus that can be launched from a keyboard shortcut.
+ * Use `dunst` for desktop notifications.
+
+
+
+I3 is fully configurable, and you can control every aspect of it by updating the default configuration file. From changing all keyboard shortcuts, to redefining the name of the workspaces, to modifying the status bar, you can make i3 behave in any way that makes the most sense for your needs.
+
+![i3 with rofi menu and dunst desktop notifications][8]
+
+i3 with `rofi` menu and `dunst` desktop notifications
+
+Finally, for more advanced users, i3 provides a full interprocess communication ([IPC][9]) interface that allows you to use your favorite language to develop scripts or programs for even more customization options.
+
+### 5\. Workspaces
+
+In i3, a workspace is an easy way to group windows. You can group them in different ways according to your workflow. For example, you can put the browser on one workspace, the terminal on another, an email client on a third, etc. You can even change i3's configuration to always assign specific applications to their own workspaces.
+
+Switching workspaces is quick and easy. As usual in i3, do it with a keyboard shortcut. Press `+num` to switch to workspace `num`. If you get into the habit of always assigning applications/groups of windows to the same workspace, you can quickly switch between them, which makes workspaces a very useful feature.
+
+In addition, you can use workspaces to control multi-monitor setups, where each monitor gets an initial workspace. If you switch to that workspace, you switch to that monitor—without moving your hand off the keyboard.
+
+Finally, there is another, special type of workspace in i3: the scratchpad. It is an invisible workspace that shows up in the middle of the other workspaces by pressing a shortcut. This is a convenient way to access windows or programs that you frequently use, such as an email client or your music player.
+
+### Give it a try
+
+If you value simplicity and efficiency and are not afraid of working with the keyboard, i3 is the window manager for you. Some say it is for advanced users, but that is not necessarily the case. You need to learn a few basic shortcuts to get around at the beginning, but they'll soon feel natural and you'll start using them without thinking.
+
+This article just scratches the surface of what i3 can do. For more details, consult [i3's documentation][10].
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/i3-tiling-window-manager
+
+作者:[Ricardo Gerardi][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/rgerardi
+[1]:https://xfce.org/
+[2]:https://i3wm.org/
+[3]:https://code.google.com/archive/p/wmii/
+[4]:https://xmonad.org/
+[5]:/file/406476
+[6]:https://opensource.com/sites/default/files/uploads/i3_screenshot.png (i3 tiled window manager screenshot)
+[7]:/file/405161
+[8]:https://opensource.com/sites/default/files/uploads/rofi_dunst.png (i3 with rofi menu and dunst desktop notifications)
+[9]:https://i3wm.org/docs/ipc.html
+[10]:https://i3wm.org/docs/userguide.html
diff --git a/sources/tech/20180809 Getting started with Postfix, an open source mail transfer agent.md b/sources/tech/20180809 Getting started with Postfix, an open source mail transfer agent.md
new file mode 100644
index 0000000000..a98065489d
--- /dev/null
+++ b/sources/tech/20180809 Getting started with Postfix, an open source mail transfer agent.md
@@ -0,0 +1,334 @@
+Getting started with Postfix, an open source mail transfer agent
+======
+
+
+
+[Postfix][1] is a great program that routes and delivers email to accounts that are external to the system. It is currently used by approximately [33% of internet mail servers][2]. In this article, I'll explain how you can use Postfix to send mail using Gmail with two-factor authentication enabled.
+
+Before you get Postfix up and running, however, you need to have some items lined up. Following are instructions on how to get it working on a number of distros.
+
+### Prerequisites
+
+ * An installed OS (Ubuntu/Debian/Fedora/Centos/Arch/FreeBSD/OpenSUSE)
+ * A Google account with two-factor authentication
+ * A working internet connection
+
+
+
+### Step 1: Prepare Google
+
+Open a web browser and log into your Google account. Once you’re in, go to your settings by clicking your picture and selecting "Google Account.” Click “Sign-in & security” and scroll down to "App passwords.” Use your password to log in. Then you can create a new app password (I named mine "postfix Setup”).
+
+
+
+Note the crazy password (shown below), which I will use throughout this article.
+
+
+
+### Step 2: Install Postfix
+
+Before you can configure the mail client, you need to install it. You must also install either the `mailutils` or `mailx` utility, depending on the OS you're using. Here's how to install it for each OS:
+
+**Debian/Ubuntu** :
+```
+apt-get update && apt-get install postfix mailutils
+
+```
+
+**Fedora** :
+```
+dnf update && dnf install postfix mailx
+
+```
+
+**Centos** :
+```
+yum update && yum install postfix mailx cyrus-sasl cyrus-sasl-plain
+
+```
+
+**Arch** :
+```
+pacman -Sy postfix mailutils
+
+```
+
+**FreeBSD** :
+```
+portsnap fetch extract update
+
+cd /usr/ports/mail/postfix
+
+make config
+
+```
+
+In the configuration dialog, select "SASL support." All other options can remain the same.
+
+From there: `make install clean`
+
+Install `mailx` from the binary package: `pkg install mailx`
+
+**OpenSUSE** :
+```
+zypper update && zypper install postfix mailx cyrus-sasl
+
+```
+
+### Step 3: Set up Gmail authentication
+
+Once you've installed Postfix, you can set up Gmail authentication. Since you have created the app password, you need to put it in a configuration file and lock it down so no one else can see it. Fortunately, this is simple to do:
+
+**Ubuntu/Debian/Fedora/Centos/Arch/OpenSUSE** :
+```
+vim /etc/postfix/sasl_passwd
+
+```
+
+Add this line:
+```
+[smtp.gmail.com]:587 ben.heffron@gmail.com:thgcaypbpslnvgce
+
+```
+
+Save and close the file. Since your Gmail password is stored as plaintext, make the file accessible only by root to be extra safe.
+```
+chmod 600 /etc/postfix/sasl_passwd
+
+```
+
+**FreeBSD** :
+```
+vim /usr/local/etc/postfix/sasl_passwd
+
+```
+
+Add this line:
+```
+[smtp.gmail.com]:587 ben.heffron@gmail.com:thgcaypbpslnvgce
+
+```
+
+Save and close the file. Since your Gmail password is stored as plaintext, make the file accessible only by root to be extra safe.
+```
+chmod 600 /usr/local/etc/postfix/sasl_passwd
+
+```
+
+
+
+### Step 4: Get Postfix moving
+
+This step is the "meat and potatoes"—everything you've done so far has been preparation.
+
+Postfix gets its configuration from the `main.cf` file, so the settings in this file are critical. For Google, it is mandatory to enable the correct SSL settings.
+
+Here are the six options you need to enter or update on the `main.cf` to make it work with Gmail (from the [SASL readme][3]):
+
+ * The **smtp_sasl_auth_enable** setting enables client-side authentication. We will configure the client’s username and password information in the second part of the example.
+ * The **relayhost** setting forces the Postfix SMTP to send all remote messages to the specified mail server instead of trying to deliver them directly to their destination.
+ * With the **smtp_sasl_password_maps** parameter, we configure the Postfix SMTP client to send username and password information to the mail gateway server.
+ * Postfix SMTP client SASL security options are set using **smtp_sasl_security_options** , with a whole lot of options. In this case, it will be nothing; otherwise, Gmail won’t play nicely with Postfix.
+ * The **smtp_tls_CAfile** is a file containing CA certificates of root CAs trusted to sign either remote SMTP server certificates or intermediate CA certificates.
+ * From the [configure settings page:][4] **stmp_use_tls** uses TLS when a remote SMTP server announces STARTTLS support, the default is not using TLS.
+
+
+
+**Ubuntu/Debian/Arch**
+
+These three OSes keep their files (certificates and `main.cf`) in the same location, so this is all you need to put in there:
+```
+vim /etc/postfix/main.cf
+
+```
+
+If the following values aren’t there, add them:
+```
+relayhost = [smtp.gmail.com]:587
+
+smtp_use_tls = yes
+
+smtp_sasl_auth_enable = yes
+
+smtp_sasl_security_options =
+
+smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+
+smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
+
+```
+
+Save and close the file.
+
+**Fedora/CentOS**
+
+These two OSes are based on the same underpinnings, so they share the same updates.
+```
+vim /etc/postfix/main.cf
+
+```
+
+If the following values aren’t there, add them:
+```
+relayhost = [smtp.gmail.com]:587
+
+smtp_use_tls = yes
+
+smtp_sasl_auth_enable = yes
+
+smtp_sasl_security_options =
+
+smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+
+smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
+
+```
+
+Save and close the file.
+
+**OpenSUSE**
+```
+vim /etc/postfix/main.cf
+
+```
+
+If the following values aren’t there, add them:
+```
+relayhost = [smtp.gmail.com]:587
+
+smtp_use_tls = yes
+
+smtp_sasl_auth_enable = yes
+
+smtp_sasl_security_options =
+
+smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+
+smtp_tls_CAfile = /etc/ssl/ca-bundle.pem
+
+```
+
+Save and close the file.
+
+OpenSUSE also requires that you modify the Postfix master process configuration file `master.cf`. Open it for editing:
+```
+vim /etc/postfix/master.cf
+
+```
+
+Uncomment the line that reads:
+```
+#tlsmgr unix - - n 1000? 1 tlsmg
+
+```
+
+It should look like this:
+```
+tlsmgr unix - - n 1000? 1 tlsmg
+
+```
+
+Save and close the file.
+
+**FreeBSD**
+```
+vim /usr/local/etc/postfix/main.cf
+
+```
+
+If the following values aren’t there, add them:
+```
+relayhost = [smtp.gmail.com]:587
+
+smtp_use_tls = yes
+
+smtp_sasl_auth_enable = yes
+
+smtp_sasl_security_options =
+
+smtp_sasl_password_maps = hash:/usr/local/etc/postfix/sasl_passwd
+
+smtp_tls_CAfile = /etc/mail/certs/cacert.pem
+
+```
+
+Save and close the file.
+
+### Step 5: Set up the password file
+
+Remember that password file you created? Now you need to feed it into Postfix using `postmap`. This is part of the `mailutils` or `mailx` utilities.
+
+**Debian, Ubuntu, Fedora, CentOS, OpenSUSE, Arch Linux**
+```
+postmap /etc/postfix/sasl_passwd
+
+```
+
+**FreeBSD**
+```
+postmap /usr/local/etc/postfix/sasl_passwd
+
+```
+
+### Step 6: Get Postfix grooving
+
+To get all the settings and configurations working, you must restart Postfix.
+
+**Debian, Ubuntu, Fedora, CentOS, OpenSUSE, Arch Linux**
+
+These guys make it simple to restart:
+```
+systemctl restart postfix.service
+
+```
+
+**FreeBSD**
+
+To start Postfix at startup, edit `/etc/rc.conf`:
+```
+vim /etc/rc.conf
+
+```
+
+Add the line:
+```
+postfix_enable=YES
+
+```
+
+Save and close the file. Then start Postfix by running:
+```
+service postfix start
+
+```
+
+### Step 7: Test it
+
+Now for the big finale—time to test it to see if it works. The `mail` command is another tool installed with `mailutils` or `mailx`.
+```
+echo Just testing my sendmail gmail relay" | mail -s "Sendmail gmail Relay" ben.heffron@gmail.com
+
+```
+
+This is what I used to test my settings, and then it came up in my Gmail.
+
+
+
+Now you can use Gmail with two-factor authentication in your Postfix setup.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/postfix-open-source-mail-transfer-agent
+
+作者:[Ben Heffron][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/elheffe
+[1]:http://www.postfix.org/start.html
+[2]:http://www.securityspace.com/s_survey/data/man.201806/mxsurvey.html
+[3]:http://www.postfix.org/SASL_README.html
+[4]:http://www.postfix.org/postconf.5.html#smtp_tls_security_level
diff --git a/sources/tech/20180809 Perform robust unit tests with PyHamcrest.md b/sources/tech/20180809 Perform robust unit tests with PyHamcrest.md
new file mode 100644
index 0000000000..1c7d7e9226
--- /dev/null
+++ b/sources/tech/20180809 Perform robust unit tests with PyHamcrest.md
@@ -0,0 +1,176 @@
+Perform robust unit tests with PyHamcrest
+======
+
+
+
+At the base of the [testing pyramid][1] are unit tests. Unit tests test one unit of code at a time—usually one function or method.
+
+Often, a single unit test is designed to test one particular flow through a function, or a specific branch choice. This enables easy mapping of a unit test that fails and the bug that made it fail.
+
+Ideally, unit tests use few or no external resources, isolating them and making them faster.
+
+_Good_ tests increase developer productivity by catching bugs early and making testing faster. _Bad_ tests decrease developer productivity.
+
+Unit test suites help maintain high-quality products by signaling problems early in the development process. An effective unit test catches bugs before the code has left the developer machine, or at least in a continuous integration environment on a dedicated branch. This marks the difference between good and bad unit tests:tests increase developer productivity by catching bugs early and making testing faster.tests decrease developer productivity.
+
+Productivity usually decreases when testing _incidental features_. The test fails when the code changes, even if it is still correct. This happens because the output is different, but in a way that is not part of the function's contract.
+
+A good unit test, therefore, is one that helps enforce the contract to which the function is committed.
+
+If a unit test breaks, the contract is violated and should be either explicitly amended (by changing the documentation and tests), or fixed (by fixing the code and leaving the tests as is).
+
+While limiting tests to enforce only the public contract is a complicated skill to learn, there are tools that can help.
+
+One of these tools is [Hamcrest][2], a framework for writing assertions. Originally invented for Java-based unit tests, today the Hamcrest framework supports several languages, including [Python][3].
+
+Hamcrest is designed to make test assertions easier to write and more precise.
+```
+def add(a, b):
+
+ return a + b
+
+
+
+from hamcrest import assert_that, equal_to
+
+
+
+def test_add():
+
+ assert_that(add(2, 2), equal_to(4))
+
+```
+
+This is a simple assertion, for simple functionality. What if we wanted to assert something more complicated?
+```
+def test_set_removal():
+
+ my_set = {1, 2, 3, 4}
+
+ my_set.remove(3)
+
+ assert_that(my_set, contains_inanyorder([1, 2, 4]))
+
+ assert_that(my_set, is_not(has_item(3)))
+
+```
+
+Note that we can succinctly assert that the result has `1`, `2`, and `4` in any order since sets do not guarantee order.
+
+We also easily negate assertions with `is_not`. This helps us write _precise assertions_ , which allow us to limit ourselves to enforcing public contracts of functions.
+
+Sometimes, however, none of the built-in functionality is _precisely_ what we need. In those cases, Hamcrest allows us to write our own matchers.
+
+Imagine the following function:
+```
+def scale_one(a, b):
+
+ scale = random.randint(0, 5)
+
+ pick = random.choice([a,b])
+
+ return scale * pick
+
+```
+
+We can confidently assert that the result divides into at least one of the inputs evenly.
+
+A matcher inherits from `hamcrest.core.base_matcher.BaseMatcher`, and overrides two methods:
+```
+class DivisibleBy(hamcrest.core.base_matcher.BaseMatcher):
+
+
+
+ def __init__(self, factor):
+
+ self.factor = factor
+
+
+
+ def _matches(self, item):
+
+ return (item % self.factor) == 0
+
+
+
+ def describe_to(self, description):
+
+ description.append_text('number divisible by')
+
+ description.append_text(repr(self.factor))
+
+```
+
+Writing high-quality `describe_to` methods is important, since this is part of the message that will show up if the test fails.
+```
+def divisible_by(num):
+
+ return DivisibleBy(num)
+
+```
+
+By convention, we wrap matchers in a function. Sometimes this gives us a chance to further process the inputs, but in this case, no further processing is needed.
+```
+def test_scale():
+
+ result = scale_one(3, 7)
+
+ assert_that(result,
+
+ any_of(divisible_by(3),
+
+ divisible_by(7)))
+
+```
+
+Note that we combined our `divisible_by` matcher with the built-in `any_of` matcher to ensure that we test only what the contract commits to.
+
+While editing this article, I heard a rumor that the name "Hamcrest" was chosen as an anagram for "matches". Hrm...
+```
+>>> assert_that("matches", contains_inanyorder(*"hamcrest")
+
+Traceback (most recent call last):
+
+ File "", line 1, in
+
+ File "/home/moshez/src/devops-python/build/devops/lib/python3.6/site-packages/hamcrest/core/assert_that.py", line 43, in assert_that
+
+ _assert_match(actual=arg1, matcher=arg2, reason=arg3)
+
+ File "/home/moshez/src/devops-python/build/devops/lib/python3.6/site-packages/hamcrest/core/assert_that.py", line 57, in _assert_match
+
+ raise AssertionError(description)
+
+AssertionError:
+
+Expected: a sequence over ['h', 'a', 'm', 'c', 'r', 'e', 's', 't'] in any order
+
+ but: no item matches: 'r' in ['m', 'a', 't', 'c', 'h', 'e', 's']
+
+```
+
+Researching more, I found the source of the rumor: It is an anagram for "matchers".
+```
+>>> assert_that("matchers", contains_inanyorder(*"hamcrest"))
+
+>>>
+
+```
+
+If you are not yet writing unit tests for your Python code, now is a good time to start. If you are writing unit tests for your Python code, using Hamcrest will allow you to make your assertion _precise_ —neither more nor less than what you intend to test. This will lead to fewer false positives when modifying code and less time spent modifying tests for working code.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/robust-unit-tests-hamcrest
+
+作者:[Moshe Zadka][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/moshez
+[1]:https://martinfowler.com/bliki/TestPyramid.html
+[2]:http://hamcrest.org/
+[3]:https://www.python.org/
diff --git a/sources/tech/20180810 How To Quickly Serve Files And Folders Over HTTP In Linux.md b/sources/tech/20180810 How To Quickly Serve Files And Folders Over HTTP In Linux.md
new file mode 100644
index 0000000000..c4adc3ac07
--- /dev/null
+++ b/sources/tech/20180810 How To Quickly Serve Files And Folders Over HTTP In Linux.md
@@ -0,0 +1,168 @@
+How To Quickly Serve Files And Folders Over HTTP In Linux
+======
+
+
+
+Today, I came across a whole bunch of methods to serve a single file or entire directory with other systems in your local area network via a web browser. I tested all of them in my Ubuntu test machine, and everything worked just fine as described below. If you ever wondered how to easily and quickly serve files and folders over HTTP in Unix-like operating systems, one of the following methods will definitely help.
+
+### Serve Files And Folders Over HTTP In Linux
+
+**Disclaimer:** All the methods given here are meant to be used within a secure local area network. Since these methods doesn’t have any security mechanism, it is **not recommended to use them in production**. You have been warned!
+
+#### Method 1 – Using simpleHTTPserver (Python)
+
+We already have written a brief guide to setup a simple http server to share files and directories instantly in the following link. If you have a system with Python installed, this method is quite handy.
+
+#### Method 2 – Using Quickserve (Python)
+
+This method is specifically for Arch Linux and its variants. Check the following link for more details.
+
+#### Method 3 – Using Ruby**
+
+In this method, we use Ruby to serve files and folders over HTTP in Unix-like systems. Install Ruby and Rails as described in the following link.
+
+Once Ruby installed, go to the directory, for example ostechnix, that you want to share over the network:
+```
+$ cd ostechnix
+
+```
+
+And, run the following command:
+```
+$ ruby -run -ehttpd . -p8000
+[2018-08-10 16:02:55] INFO WEBrick 1.4.2
+[2018-08-10 16:02:55] INFO ruby 2.5.1 (2018-03-29) [x86_64-linux]
+[2018-08-10 16:02:55] INFO WEBrick::HTTPServer#start: pid=5859 port=8000
+
+```
+
+Make sure the port 8000 is opened in your router or firewall . If the port has already been used by some other services use different port.
+
+You can now access the contents of this folder from any remote system using URL – **http:// :8000/**.
+
+
+
+To stop sharing press **CTRL+C**.
+
+#### Method 4 – Using Http-server (NodeJS)
+
+[**Http-server**][1] is a simple, production ready command line http-server written in NodeJS. It requires zero configuration and can be used to instantly share files and directories via web browser.
+
+Install NodeJS as described below.
+
+Once NodeJS installed, run the following command to install http-server.
+```
+$ npm install -g http-server
+
+```
+
+Now, go to any directory and share its contents over HTTP as shown below.
+```
+$ cd ostechnix
+
+$ http-server -p 8000
+Starting up http-server, serving ./
+Available on:
+ http://127.0.0.1:8000
+ http://192.168.225.24:8000
+ http://192.168.225.20:8000
+Hit CTRL-C to stop the server
+
+```
+
+Now, you can access the contents of this directory from local or remote systems in the network using URL – **http:// :8000**.
+
+
+
+To stop sharing, press **CTRL+C**.
+
+#### Method 5 – Using Miniserve (Rust)
+
+[**Miniserve**][2] is yet another command line utility that allows you to quickly serve files over HTTP. It is very fast, easy-to-use, and cross-platform utility written in **Rust** programming language. Unlike the above utilities/methods, it provides authentication support, so you can setup username and password to the shares.
+
+Install Rust in your Linux system as described in the following link.
+
+After installing Rust, run the following command to install miniserve:
+```
+$ cargo install miniserve
+
+```
+
+Alternatively, you can download the binaries from [**the releases page**][3] and make it executable.
+```
+$ chmod +x miniserve-linux
+
+```
+
+And, then you can run it using command (assuming miniserve binary file is downloaded in the current working directory):
+```
+$ ./miniserve-linux
+
+```
+
+**Usage**
+
+To serve a directory:
+```
+$ miniserve
+
+```
+
+**Example:**
+```
+$ miniserve /home/sk/ostechnix/
+miniserve v0.2.0
+Serving path /home/sk/ostechnix at http://[::]:8080, http://localhost:8080
+Quit by pressing CTRL-C
+
+```
+
+Now, you can access the share from local system itself using URL – **** and/or from remote system with URL – **http:// :8080**.
+
+To serve a single file:
+```
+$ miniserve
+
+```
+
+**Example:**
+```
+$ miniserve ostechnix/file.txt
+
+```
+
+Serve file/folder with username and password:
+```
+$ miniserve --auth joe:123
+
+```
+
+Bind to multiple interfaces:
+```
+$ miniserve -i 192.168.225.1 -i 10.10.0.1 -i ::1 --
+
+```
+
+As you can see, I have given only 5 methods. But, there are few more methods given in the link attached at the end of this guide. Go and test them as well. Also, bookmark and revisit it from time to time to check if there are any new additions to the list in future.
+
+And, that’s all for now. Hope this was useful. More good stuffs to come. Stay tuned!
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/how-to-quickly-serve-files-and-folders-over-http-in-linux/
+
+作者:[SK][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://www.ostechnix.com/author/sk/
+[1]:https://www.npmjs.com/package/http-server
+[2]:https://github.com/svenstaro/miniserve
+[3]:https://github.com/svenstaro/miniserve/releases
diff --git a/sources/tech/20180810 How To Remove Or Disable Ubuntu Dock.md b/sources/tech/20180810 How To Remove Or Disable Ubuntu Dock.md
new file mode 100644
index 0000000000..65816f7d5c
--- /dev/null
+++ b/sources/tech/20180810 How To Remove Or Disable Ubuntu Dock.md
@@ -0,0 +1,142 @@
+How To Remove Or Disable Ubuntu Dock
+======
+
+
+
+**If you want to replace the Ubuntu Dock in Ubuntu 18.04 with some other dock (like Plank dock for example) or panel, and you want to remove or disable the Ubuntu Dock, here's what you can do and how.**
+
+Ubuntu Dock - the bar on the left-hand side of the screen which can be used to pin applications and access installed applications -
+
+
+### How to access the Activities Overview without Ubuntu Dock
+
+Without Ubuntu Dock, you may have no way of accessing the Activities / installed application list (which can be accessed from Ubuntu Dock by clicking on Show Applications button at the bottom of the dock). For example if you want to use Plank dock.
+
+Obviously, that's not the case if you install Dash to Panel extension to use it instead Ubuntu Dock, because Dash to Panel provides a button to access the Activities Overview / installed applications.
+
+Depending on what you plan to use instead of Ubuntu Dock, if there's no way of accessing the Activities Overview, you can enable the Activities Overview Hot Corner option and simply move your mouse to the upper left corner of the screen to open the Activities. Another way of accessing the installed application list is using a keyboard shortcut: `Super + A` .
+
+If you want to enable the Activities Overview hot corner, use this command:
+```
+gsettings set org.gnome.shell enable-hot-corners true
+
+```
+
+If later you want to undo this and disable the hot corners, you need to use this command:
+```
+gsettings set org.gnome.shell enable-hot-corners false
+
+```
+
+You can also enable or disable the Activities Overview Hot Corner option by using the Gnome Tweaks application (the option is in the `Top Bar` section of Gnome Tweaks), which can be installed by using this command:
+```
+sudo apt install gnome-tweaks
+
+```
+
+### How to remove or disable Ubuntu Dock
+
+Below you'll find 4 ways of getting rid of Ubuntu Dock which work in Ubuntu 18.04.
+
+**Option 1: Remove the Gnome Shell Ubuntu Dock package.**
+
+The easiest way of getting rid of the Ubuntu Dock is to remove the package.
+
+This completely removes the Ubuntu Dock extension from your system, but it also removes the `ubuntu-desktop` meta package. There's no immediate issue if you remove the `ubuntu-desktop` meta package because does nothing by itself. The `ubuntu-meta` package depends on a large number of packages which make up the Ubuntu Desktop. Its dependencies won't be removed and nothing will break. The issue is that if you want to upgrade to a newer Ubuntu version, any new `ubuntu-desktop` dependencies won't be installed.
+
+As a way around this, you can simply install the `ubuntu-desktop` meta package before upgrading to a newer Ubuntu version (for example if you want to upgrade from Ubuntu 18.04 to 18.10).
+
+If you're ok with this and want to remove the Ubuntu Dock extension package from your system, use the following command:
+```
+sudo apt remove gnome-shell-extension-ubuntu-dock
+
+```
+
+If later you want to undo the changes, simply install the extension back using this command:
+```
+sudo apt install gnome-shell-extension-ubuntu-dock
+
+```
+
+Or to install the `ubuntu-desktop` meta package back (this will install any ubuntu-desktop dependencies you may have removed, including Ubuntu Dock), you can use this command:
+```
+sudo apt install ubuntu-desktop
+
+```
+
+**Option 2: Install and use the vanilla Gnome session instead of the default Ubuntu session.**
+
+Another way to get rid of Ubuntu Dock is to install and use the vanilla Gnome session. Installing the vanilla Gnome session will also install other packages this session depends on, like Gnome Documents, Maps, Music, Contacts, Photos, Tracker and more.
+
+By installing the vanilla Gnome session, you'll also get the default Gnome GDM login / lock screen theme instead of the Ubuntu defaults as well as Adwaita Gtk theme and icons. You can easily change the Gtk and icon theme though, by using the Gnome Tweaks application.
+
+Furthermore, the AppIndicators extension will be disabled by default (so applications that make use of the AppIndicators tray won't show up on the top panel), but you can enable this by using Gnome Tweaks (under Extensions, enable the Ubuntu appindicators extension).
+
+In the same way, you can also enable or disable Ubuntu Dock from the vanilla Gnome session, which is not possible if you use the Ubuntu session (disabling Ubuntu Dock from Gnome Tweaks when using the Ubuntu session does nothing).
+
+If you don't want to install these extra packages required by the vanilla Gnome session, this option of removing Ubuntu Dock is not for you so check out the other options.
+
+If you are ok with this though, here's what you need to do. To install the vanilla Gnome session in Ubuntu, use this command:
+```
+sudo apt install vanilla-gnome-desktop
+
+```
+
+After the installation finishes, reboot your system and on the login screen, after you click on your username, click the gear icon next to the `Sign in` button, and select `GNOME` instead of `Ubuntu` , then proceed to login:
+
+
+
+In case you want to undo this and remove the vanilla Gnome session, you can purge the vanilla Gnome package and then remove the dependencies it installed (second command) using the following commands:
+```
+sudo apt purge vanilla-gnome-desktop
+sudo apt autoremove
+
+```
+
+Then reboot and select Ubuntu in the same way, from the GDM login screen.
+
+**Option 3: Permanently hide the Ubuntu Dock from your desktop instead of removing it.**
+
+If you prefer to permanently hide the Ubuntu Dock from showing up on your desktop instead of uninstalling it or using the vanilla Gnome session, you can easily do this using Dconf Editor. The drawback to this is that Ubuntu Dock will still use some system resources even though you're not using in on your desktop, but you'll also be able to easily revert this without installing or removing any packages.
+
+Ubuntu Dock is only hidden from your desktop though. When you go in overlay mode (Activities), you'll still see and be able to use Ubuntu Dock from there.
+
+To permanently hide Ubuntu Dock, use Dconf Editor to navigate to `/org/gnome/shell/extensions/dash-to-dock` and disable (set them to false) the following options: `autohide` , `dock-fixed` and `intellihide` .
+
+You can achieve this from the command line if you wish, buy running the commands below:
+```
+gsettings set org.gnome.shell.extensions.dash-to-dock autohide false
+gsettings set org.gnome.shell.extensions.dash-to-dock dock-fixed false
+gsettings set org.gnome.shell.extensions.dash-to-dock intellihide false
+
+```
+In case you change your mind and you want to undo this, you can either use Dconf Editor and re-enable (set them to true) autohide, dock-fixed and intellihide from `/org/gnome/shell/extensions/dash-to-dock` , or you can use these commands:
+```
+gsettings set org.gnome.shell.extensions.dash-to-dock autohide true
+gsettings set org.gnome.shell.extensions.dash-to-dock dock-fixed true
+gsettings set org.gnome.shell.extensions.dash-to-dock intellihide true
+
+```
+
+**Option 4: Use Dash to Panel extension.**
+
+You can install Dash to Panel from
+
+If you change your mind and you want Ubuntu Dock back, you can either disable Dash to Panel by using Gnome Tweaks app, or completely remove Dash to Panel by clicking the X button next to it from here:
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxuprising.com/2018/08/how-to-remove-or-disable-ubuntu-dock.html
+
+作者:[Logix][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://plus.google.com/118280394805678839070
+[1]:https://bugs.launchpad.net/ubuntu/+source/gnome-tweak-tool/+bug/1713020
+[2]:https://www.linuxuprising.com/2018/05/gnome-shell-dash-to-panel-v14-brings.html
+[3]:https://extensions.gnome.org/extension/1160/dash-to-panel/
diff --git a/sources/tech/20180810 Strawberry- Quality sound, open source music player.md b/sources/tech/20180810 Strawberry- Quality sound, open source music player.md
new file mode 100644
index 0000000000..6cc72dccfb
--- /dev/null
+++ b/sources/tech/20180810 Strawberry- Quality sound, open source music player.md
@@ -0,0 +1,105 @@
+Strawberry: Quality sound, open source music player
+======
+
+
+
+I recently received an email from [Jonas Kvinge][1] who forked the [Clementine open source music player][2]. Jonas writes:
+
+I started working on a modified version of Clementine already in 2013, but because of other priorities, I did not pick up the work again before last year. I had not decided then if I was creating a fork, or contributing to Clementine. I ended up doing both. I started to see that I wanted the program development in a different direction. My focus was to create a music player for playing local music files, and not having to maintain support for multiple internet features that I did not use, and some which I did not want in the program at all… I also saw more and more that I disagree with the authors of Clementine and some statements that have been made regarding high-resolution audio.
+
+Jonas and I are definitely working from the same perspective, at least in relation to high-resolution music files. Back in late 2016, [I looked at Clementine][3], and though it was in many ways delightful, it definitely missed the boat with respect to working with a dedicated high-resolution digital-analog converter (DAC) for music enjoyment. But that’s OK; Clementine just wasn’t built for me. Nor, it appears, was it for Jonas.
+
+So, given that Jonas and I share an interest in being able to play back high-resolution audio on a dedicated listening device, I thought I’d best give [Strawberry][4], Jonas’ fork of Clementine, a try. I grabbed the [2018/07/16 release for Ubuntu][5] from Jonas’ site. It was a .deb and very straightforward to install.
+```
+sudo dpkg -i strawberry_0.2.1-27-gb2c26eb_amd64.deb
+
+```
+
+As usual, some necessary packages weren’t installed on my system, so I used `apt install -f` to remedy that.
+
+Apt recommended the following packages:
+```
+graphicsmagick-dbg gxine xine-ui
+
+```
+
+and installed the following packages:
+```
+libgraphicsmagick-q16-3 libiso9660-10 liblastfm5-1 libqt5concurrent5 libvcdinfo0 libxine2 libxine2-bin libxine2-doc libxine2-ffmpeg libxine2-misc-plugins libxine2-plugins
+
+```
+
+Once that was all in hand, I started up Strawberry and saw this:
+
+
+
+I verified that I could point Strawberry at ALSA in general and at my dedicated DAC in particular.
+
+
+
+
+
+Then I was ready to update my collection, which took less than a minute (Clementine was similarly fast).
+
+The only thing I noticed that seemed a little odd was that Strawberry provided a software volume control, which isn’t of great interest to me (my hardware has a nice shiny knob on top for just that purpose).
+
+
+
+And then I got down to some quality listening. One of the things I found I liked right away is the status button (see the strawberry at the top left of the UI). This verifies the details of the currently playing track, as shown in the screen capture to the left. Note that the effective bit rate, bit rate, and word length are shown, as well as other useful information.
+
+The sound is glorious, as is customary with well-recorded high-resolution material (for those of you inclined to argue about the merits of high-resolution audio, before you post your opinions, whether pro or con, please read [this article][6], which actually treats the topic in a scientific fashion).
+
+What’s cool about Strawberry, besides audio quality? Well, it’s fun to see the spectrum analyzer operating on the bottom of the screen. The overall responsiveness is smooth and quick; the album cover slides up once the music starts. There isn’t a lot of wasted space in the UI. And, as Jonas says:
+
+For many people, Clementine will still be a better choice since it has features such as scrobbling and internet services, which Strawberry lacks and I do not plan to include.
+
+Evidently, this is a player focused on the quality of the music, rather than the quantity. I’ll be using this player more in the future; it’s right up my alley.
+
+### Fine sound collections
+
+On the topic of music, especially interesting and unusual music, many thanks to [Michael Lavorgna over at Audiostream][7], who mentions these two fine online sound collections: [Cultural Equity][8] and [Smithsonian Folkways Recordings][9]. What great sources for stuff that is of historical interest and just plain fun.
+
+Also thanks to Michael for reminding me about [Ektoplazm][10], a fine free music portal for those interested in “psytrance, techno, and downtempo music.” I’ve downloaded a few albums from this site in the past, and when the mood strikes, I really appreciate what it has to offer. It's especially wonderful that the music files are available in [FLAC][11].
+
+### And more music…
+
+In my last article, I spent so much time building that I didn’t have any time for listening. But since then, I’ve been to my favorite record store and picked up four new albums, some of which came with downloads. First up is [Jon Hopkins’][12] [Singularity][12]. I’ve been picking up the odd Jon Hopkins album since [Linn Records][13] (by the way, a great site for Linux users to buy downloads since no bloatware is required) was experimenting with a more broad-based music offering and introduced me to Jon. Some of his work is [available on Bandcamp][14] these days (including Singularity) which is a fine Linux-friendly site. For me, this is a great album—not really ambient, not really beatless, not really anything except what it is. Huge powerful swaths of music, staggering bass. Great fun! Go listen on [Bandcamp][14].
+
+And if, like me, you have bought a few [Putumayo Music][15] albums over the years, keep your eyes peeled for Putumayo’s absolutely wonderful vinyl LP release of [_Vintage Latino_][16]. This great LP of vintage salsa and cha-cha is also available there to buy as a CD; you can listen to [1:00 clips on Bandcamp][17].
+
+[Bombino][18] was in town last night. I had other stuff to do, but a friend went to the concert and loved it. I have three of his albums now; the last two I purchased on that fine open source medium, the vinyl LP, which came with downloads as well. His most recent album, _Deran_ , is more than worth it; check it out on the link above.
+
+
+Last but by no means least, I managed to find a copy of [Nils Frahm’s _All Melody_][19] on vinyl (which includes a download code). I’ve been enjoying the high-resolution digital version of this album that I bought earlier this year, but it’s great fun to have it on vinyl.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/strawberry-new-open-source-music-player
+
+作者:[Chris Hermansen][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/clhermansen
+[1]:https://github.com/jonaski
+[2]:https://www.clementine-player.org/
+[3]:https://opensource.com/life/16/10/4-open-music-players-compared
+[4]:http://www.strawbs.org/
+[5]:http://builds.jkvinge.net/ubuntu/bionic/strawberry_0.2.1-27-gb2c26eb_amd64.deb
+[6]:http://www.aes.org/e-lib/browse.cfm?elib=18296
+[7]:https://www.audiostream.com/content/alan-lomax-17000-sound-recordings-online-free
+[8]:http://research.culturalequity.org/audio-guide.jsp
+[9]:https://folkways.si.edu/radio-and-playlists/smithsonian
+[10]:http://www.ektoplazm.com/
+[11]:https://xiph.org/flac/
+[12]:https://pitchfork.com/reviews/albums/jon-hopkins-singularity/
+[13]:http://www.linnrecords.com/
+[14]:https://jonhopkins.bandcamp.com/album/singularity
+[15]:https://www.putumayo.com/
+[16]:https://www.putumayo.com/product-page/vintage-latino
+[17]:https://putumayo.bandcamp.com/album/vintage-latino
+[18]:http://www.bombinomusic.com/
+[19]:https://www.youtube.com/watch?v=1PTj1qIqcWM
diff --git a/sources/tech/20180810 Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank.md b/sources/tech/20180810 Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank.md
new file mode 100644
index 0000000000..29164e3510
--- /dev/null
+++ b/sources/tech/20180810 Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank.md
@@ -0,0 +1,77 @@
+Use Plank On Multiple Monitors Without Creating Multiple Docks With autoplank
+======
+
+
+
+**[autoplank][1] is a small tool written in Go which adds multi-monitor support to Plank dock without having to create [multiple][2] docks.**
+
+**When you move your mouse cursor to the bottom of a monitor, autoplank detect your mouse movement using** `xdotool` and it automatically moves Plank to that monitor. This tool **only works if Plank is set to run at the bottom of the screen** , at least for now.
+
+There's a slight delay until Plank actually shows up on the monitor where the mouse is though. The developer says this is intentional, to make sure you actually want to access Plank on that monitor. The time delay before showing plank is not currently configurable, but that may change in the future.
+
+autoplank should work with elementary OS, as well as any desktop environment or Linux distribution you use Plank dock on.
+
+Plank is a simple dock that shows icons of running applications / windows. The application allows pinning applications to the dock, and comes with a few built-in simple "docklets": a clipboard manager, clock, CPU monitor, show desktop and trash. To access its settings, hold down the `Ctrl` key while right clicking anywhere on the Plank dock, and then clicking on `Preferences` .
+
+Plank is used by default in elementary OS, but it can be used on any desktop environment or Linux distribution you wish.
+
+### Install autoplank
+
+On its GitHub page, it's mentioned that you need Go 1.8 or newer to build autoplank but I was able to successfully build it with Go 1.6 in Ubuntu 16.04 (elementary OS 0.4 Loki).
+
+The developer has said on
+
+**1\. Install required dependencies.**
+
+To build autoplank you'll need Go (`golang-go` in Debian, Ubuntu, elementary OS, etc.). To get the latest Git code you'll also need `git` , and for detecting the monitor on which you move the mose, you'll also need to install `xdotool` .
+
+Install these in Ubuntu, Debian, elementary OS and so on, by using this command:
+```
+sudo apt install git golang-go xdotool
+
+```
+
+**2\. Get the latest autoplank from[Git][1], build it, and install it in** `/usr/local/bin` :
+```
+git clone https://github.com/abiosoft/autoplank
+cd autoplank
+go build -o autoplank
+sudo mv autoplank /usr/local/bin/
+
+```
+
+You can remove the autoplank folder from your home directory now.
+
+When you want to uninstall autoplank, simply remove the `/usr/local/bin/autoplank` binary (`sudo rm /usr/local/bin/autoplank`).
+
+**3\. Add autoplank to startup.**
+
+If you want to try autoplank before adding it to startup or creating a systemd service for it, you can simply type `autoplank` in a terminal to start it.
+
+To have autoplank work between reboots, you'll need to add it to your startup applications. The exact steps for doing this depend on your desktop environments, so I won't tell you exactly how to do that for every desktop environment, but remember to use `/usr/local/bin/autoplank` as the executable in Startup Applications.
+
+In elementary OS, you can open `System Settings` , then in `Applications` , on the `Startup` tab, click the `+` button in the bottom left-hand side corner of the window, then add `/usr/local/bin/autoplank` in the `Type in a custom command` field:
+
+
+
+**Another way of using autoplank is by creating a systemd service for it, as explained[here][3].** Using a systemd service for autoplank has the advantage of restarting autoplank if it crashes for whatever reason. Use either the systemd service or add autoplank to your startup applications (don't use both).
+
+**4\. After you do this, logout, login and autoplank should be running so you can move the mouse at the bottom of a monitor to move Plank dock there.**
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.linuxuprising.com/2018/08/use-plank-on-multiple-monitors-without.html
+
+作者:[Logix][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://plus.google.com/118280394805678839070
+[1]:https://github.com/abiosoft/autoplank
+[2]:https://answers.launchpad.net/plank/+question/204593
+[3]:https://github.com/abiosoft/autoplank#optional-create-a-service
+[4]:https://www.reddit.com/r/elementaryos/comments/95a879/autoplank_use_plank_on_multimonitor_setup/e3r9saq/
diff --git a/sources/tech/20180814 5 open source strategy and simulation games for Linux.md b/sources/tech/20180814 5 open source strategy and simulation games for Linux.md
new file mode 100644
index 0000000000..1f7e94c22f
--- /dev/null
+++ b/sources/tech/20180814 5 open source strategy and simulation games for Linux.md
@@ -0,0 +1,111 @@
+5 open source strategy and simulation games for Linux
+======
+
+
+
+Gaming has traditionally been one of Linux's weak points. That has changed somewhat in recent years thanks to Steam, GOG, and other efforts to bring commercial games to multiple operating systems, but those games are often not open source. Sure, the games can be played on an open source operating system, but that is not good enough for an open source purist.
+
+So, can someone who only uses free and open source software find games that are polished enough to present a solid gaming experience without compromising their open source ideals? Absolutely. While open source games are unlikely ever to rival some of the AAA commercial games developed with massive budgets, there are plenty of open source games, in many genres, that are fun to play and can be installed from the repositories of most major Linux distributions. Even if a particular game is not packaged for a particular distribution, it is usually easy to download the game from the project's website to install and play it.
+
+This article looks at strategy and simulation games. I have already written about [arcade-style games][1], [board & card games][2], [puzzle games][3], [racing & flying games][4], and [role-playing games][5].
+
+### Freeciv
+
+
+
+[Freeciv][6] is an open source version of the [Civilization series][7] of computer games. Gameplay is most similar to the earlier games in the Civilization series, and Freeciv even has options to use Civilization 1 and Civilization 2 rule sets. Freeciv involves building cities, exploring the world map, developing technologies, and competing with other civilizations trying to do the same. Victory conditions include defeating all the other civilizations, developing a space colony, or hitting deadline if neither of the first two conditions are met. The game can be played against AI opponents or other human players. Different tile-sets are available to change the look of the game's map.
+
+To install Freeciv, run the following command:
+
+ * On Fedora: `dnf install freeciv`
+ * On Debian/Ubuntu: `apt install freeciv`
+
+
+
+### MegaGlest
+
+
+
+[MegaGlest][8] is an open source real-time strategy game in the style of Blizzard Entertainment's [Warcraft][9] and [StarCraft][10] games. Players control one of several different factions, building structures and recruiting units to explore the map and battle their opponents. At the beginning of the match, a player can build only the most basic buildings and recruit the weakest units. To build and recruit better things, players must work their way up their factions technology tree by building structures and recruiting units that unlock more advanced options. Combat units will attack when enemy units come into range, but for optimal strategy, it is best to manage the battle directly by controlling the units. Simultaneously managing the construction of new structures, recruiting new units, and managing battles can be a challenge, but that is the point of a real-time strategy game. MegaGlest provides a nice variety of factions, so there are plenty of reasons to try new and different strategies.
+
+To install MegaGlest, run the following command:
+
+ * On Fedora: `dnf install megaglest`
+ * On Debian/Ubuntu: `apt install megaglest`
+
+
+
+### OpenTTD
+
+
+
+[OpenTTD][11] (see also [our review][12]) is an open source implementation of [Transport Tycoon Deluxe][13]. The object of the game is to create a transportation network and earn money, which allows the player to build an even bigger transportation network. The network can include boats, buses, trains, trucks, and planes. By default, gameplay takes place between 1950 and 2050, with players aiming to get the highest performance rating possible before time runs out. The performance rating is based on things like the amount of cargo delivered, the number of vehicles they have, and how much money they earned.
+
+To install OpenTTD, run the following command:
+
+ * On Fedora: `dnf install openttd`
+ * On Debian/Ubuntu: `apt install openttd`
+
+
+
+### The Battle for Wesnoth
+
+
+
+[The Battle for Wesnoth][14] is one of the most polished open source games available. This turn-based strategy game has a fantasy setting. Play takes place on a hexagonal grid, where individual units battle each other for control. Each type of unit has unique strengths and weaknesses, which requires players to plan their attacks accordingly. There are many different campaigns available for The Battle for Wesnoth, each with different objectives and storylines. The Battle for Wesnoth also comes with a map editor for players interested in creating their own maps or campaigns.
+
+To install The Battle for Wesnoth, run the following command:
+
+ * On Fedora: `dnf install wesnoth`
+ * On Debian/Ubuntu: `apt install wesnoth`
+
+
+
+### UFO: Alien Invasion
+
+
+
+[UFO: Alien Invasion][15] is an open source tactical strategy game inspired by the [X-COM series][20]. There are two distinct gameplay modes: geoscape and tactical. In geoscape mode, the player takes control of the big picture and deals with managing their bases, researching new technologies, and controlling overall strategy. In tactical mode, the player controls a squad of soldiers and directly confronts the alien invaders in a turn-based battle. Both modes provide different gameplay styles, but both require complex strategy and tactics.
+
+To install UFO: Alien Invasion, run the following command:
+
+ * On Debian/Ubuntu: `apt install ufoai`
+
+
+
+Unfortunately, UFO: Alien Invasion is not packaged for Fedora.
+
+Did I miss one of your favorite open source strategy or simulation games? Share it in the comments below.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/strategy-simulation-games-linux
+
+作者:[Joshua Allen Holm][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/holmja
+[1]:https://opensource.com/article/18/1/arcade-games-linux
+[2]:https://opensource.com/article/18/3/card-board-games-linux
+[3]:https://opensource.com/article/18/6/puzzle-games-linux
+[4]:https://opensource.com/article/18/7/racing-flying-games-linux
+[5]:https://opensource.com/article/18/8/role-playing-games-linux
+[6]:http://www.freeciv.org/
+[7]:https://en.wikipedia.org/wiki/Civilization_(series)
+[8]:https://megaglest.org/
+[9]:https://en.wikipedia.org/wiki/Warcraft
+[10]:https://en.wikipedia.org/wiki/StarCraft
+[11]:https://www.openttd.org/
+[12]:https://opensource.com/life/15/7/linux-game-review-openttd
+[13]:https://en.wikipedia.org/wiki/Transport_Tycoon#Transport_Tycoon_Deluxe
+[14]:https://www.wesnoth.org/
+[15]:https://ufoai.org/
+[16]:https://opensource.com/downloads/cheat-sheets?intcmp=7016000000127cYAAQ
+[17]:https://opensource.com/alternatives?intcmp=7016000000127cYAAQ
+[18]:https://opensource.com/tags/linux?intcmp=7016000000127cYAAQ
+[19]:https://developers.redhat.com/cheat-sheets/advanced-linux-commands/?intcmp=7016000000127cYAAQ
+[20]:https://en.wikipedia.org/wiki/X-COM
diff --git a/sources/tech/20180814 HTTP request routing and validation with gorilla-mux.md b/sources/tech/20180814 HTTP request routing and validation with gorilla-mux.md
new file mode 100644
index 0000000000..410f692ad9
--- /dev/null
+++ b/sources/tech/20180814 HTTP request routing and validation with gorilla-mux.md
@@ -0,0 +1,674 @@
+HTTP request routing and validation with gorilla/mux
+======
+
+
+
+The Go networking library includes the `http.ServeMux` structure type, which supports HTTP request multiplexing (routing): A web server routes an HTTP request for a hosted resource, with a URI such as /sales4today, to a code handler; the handler performs the appropriate logic before sending an HTTP response, typically an HTML page. Here’s a sketch of the architecture:
+```
+ +------------+ +--------+ +---------+
+HTTP request---->| web server |---->| router |---->| handler |
+ +------------+ +--------+ +---------+
+```
+
+In a call to the `ListenAndServe` method to start an HTTP server
+```
+http.ListenAndServe(":8888", nil) // args: port & router
+```
+
+a second argument of `nil` means that the `DefaultServeMux` is used for request routing.
+
+The `gorilla/mux` package has a `mux.Router` type as an alternative to either the `DefaultServeMux` or a customized request multiplexer. In the `ListenAndServe` call, a `mux.Router` instance would replace `nil` as the second argument. What makes the `mux.Router` so appealing is best shown through a code example:
+
+### 1\. A sample crud web app
+
+The crud web application (see below) supports the four CRUD (Create Read Update Delete) operations, which match four HTTP request methods: POST, GET, PUT, and DELETE, respectively. In the crud app, the hosted resource is a list of cliche pairs, each a cliche and a conflicting cliche such as this pair:
+```
+Out of sight, out of mind. Absence makes the heart grow fonder.
+
+```
+
+New cliche pairs can be added, and existing ones can be edited or deleted.
+
+**The crud web app**
+```
+package main
+
+import (
+ "gorilla/mux"
+ "net/http"
+ "fmt"
+ "strconv"
+)
+
+const GETALL string = "GETALL"
+const GETONE string = "GETONE"
+const POST string = "POST"
+const PUT string = "PUT"
+const DELETE string = "DELETE"
+
+type clichePair struct {
+ Id int
+ Cliche string
+ Counter string
+}
+
+// Message sent to goroutine that accesses the requested resource.
+type crudRequest struct {
+ verb string
+ cp *clichePair
+ id int
+ cliche string
+ counter string
+ confirm chan string
+}
+
+var clichesList = []*clichePair{}
+var masterId = 1
+var crudRequests chan *crudRequest
+
+// GET /
+// GET /cliches
+func ClichesAll(res http.ResponseWriter, req *http.Request) {
+ cr := &crudRequest{verb: GETALL, confirm: make(chan string)}
+ completeRequest(cr, res, "read all")
+}
+
+// GET /cliches/id
+func ClichesOne(res http.ResponseWriter, req *http.Request) {
+ id := getIdFromRequest(req)
+ cr := &crudRequest{verb: GETONE, id: id, confirm: make(chan string)}
+ completeRequest(cr, res, "read one")
+}
+
+// POST /cliches
+
+func ClichesCreate(res http.ResponseWriter, req *http.Request) {
+
+ cliche, counter := getDataFromRequest(req)
+
+ cp := new(clichePair)
+
+ cp.Cliche = cliche
+
+ cp.Counter = counter
+
+ cr := &crudRequest{verb: POST, cp: cp, confirm: make(chan string)}
+
+ completeRequest(cr, res, "create")
+
+}
+
+
+
+// PUT /cliches/id
+
+func ClichesEdit(res http.ResponseWriter, req *http.Request) {
+
+ id := getIdFromRequest(req)
+
+ cliche, counter := getDataFromRequest(req)
+
+ cr := &crudRequest{verb: PUT, id: id, cliche: cliche, counter: counter, confirm: make(chan string)}
+
+ completeRequest(cr, res, "edit")
+
+}
+
+
+
+// DELETE /cliches/id
+
+func ClichesDelete(res http.ResponseWriter, req *http.Request) {
+
+ id := getIdFromRequest(req)
+
+ cr := &crudRequest{verb: DELETE, id: id, confirm: make(chan string)}
+
+ completeRequest(cr, res, "delete")
+
+}
+
+
+
+func completeRequest(cr *crudRequest, res http.ResponseWriter, logMsg string) {
+
+ crudRequests<-cr
+
+ msg := <-cr.confirm
+
+ res.Write([]byte(msg))
+
+ logIt(logMsg)
+
+}
+
+
+
+func main() {
+
+ populateClichesList()
+
+
+
+ // From now on, this gorountine alone accesses the clichesList.
+
+ crudRequests = make(chan *crudRequest, 8)
+
+ go func() { // resource manager
+
+ for {
+
+ select {
+
+ case req := <-crudRequests:
+
+ if req.verb == GETALL {
+
+ req.confirm<-readAll()
+
+ } else if req.verb == GETONE {
+
+ req.confirm<-readOne(req.id)
+
+ } else if req.verb == POST {
+
+ req.confirm<-addPair(req.cp)
+
+ } else if req.verb == PUT {
+
+ req.confirm<-editPair(req.id, req.cliche, req.counter)
+
+ } else if req.verb == DELETE {
+
+ req.confirm<-deletePair(req.id)
+
+ }
+
+ }
+
+ }()
+
+ startServer()
+
+}
+
+
+
+func startServer() {
+
+ router := mux.NewRouter()
+
+
+
+ // Dispatch map for CRUD operations.
+
+ router.HandleFunc("/", ClichesAll).Methods("GET")
+
+ router.HandleFunc("/cliches", ClichesAll).Methods("GET")
+
+ router.HandleFunc("/cliches/{id:[0-9]+}", ClichesOne).Methods("GET")
+
+
+
+ router.HandleFunc("/cliches", ClichesCreate).Methods("POST")
+
+ router.HandleFunc("/cliches/{id:[0-9]+}", ClichesEdit).Methods("PUT")
+
+ router.HandleFunc("/cliches/{id:[0-9]+}", ClichesDelete).Methods("DELETE")
+
+
+
+ http.Handle("/", router) // enable the router
+
+
+
+ // Start the server.
+
+ port := ":8888"
+
+ fmt.Println("\nListening on port " + port)
+
+ http.ListenAndServe(port, router); // mux.Router now in play
+
+}
+
+
+
+// Return entire list to requester.
+
+func readAll() string {
+
+ msg := "\n"
+
+ for _, cliche := range clichesList {
+
+ next := strconv.Itoa(cliche.Id) + ": " + cliche.Cliche + " " + cliche.Counter + "\n"
+
+ msg += next
+
+ }
+
+ return msg
+
+}
+
+
+
+// Return specified clichePair to requester.
+
+func readOne(id int) string {
+
+ msg := "\n" + "Bad Id: " + strconv.Itoa(id) + "\n"
+
+
+
+ index := findCliche(id)
+
+ if index >= 0 {
+
+ cliche := clichesList[index]
+
+ msg = "\n" + strconv.Itoa(id) + ": " + cliche.Cliche + " " + cliche.Counter + "\n"
+
+ }
+
+ return msg
+
+}
+
+
+
+// Create a new clichePair and add to list
+
+func addPair(cp *clichePair) string {
+
+ cp.Id = masterId
+
+ masterId++
+
+ clichesList = append(clichesList, cp)
+
+ return "\nCreated: " + cp.Cliche + " " + cp.Counter + "\n"
+
+}
+
+
+
+// Edit an existing clichePair
+
+func editPair(id int, cliche string, counter string) string {
+
+ msg := "\n" + "Bad Id: " + strconv.Itoa(id) + "\n"
+
+ index := findCliche(id)
+
+ if index >= 0 {
+
+ clichesList[index].Cliche = cliche
+
+ clichesList[index].Counter = counter
+
+ msg = "\nCliche edited: " + cliche + " " + counter + "\n"
+
+ }
+
+ return msg
+
+}
+
+
+
+// Delete a clichePair
+
+func deletePair(id int) string {
+
+ idStr := strconv.Itoa(id)
+
+ msg := "\n" + "Bad Id: " + idStr + "\n"
+
+ index := findCliche(id)
+
+ if index >= 0 {
+
+ clichesList = append(clichesList[:index], clichesList[index + 1:]...)
+
+ msg = "\nCliche " + idStr + " deleted\n"
+
+ }
+
+ return msg
+
+}
+
+
+
+//*** utility functions
+
+func findCliche(id int) int {
+
+ for i := 0; i < len(clichesList); i++ {
+
+ if id == clichesList[i].Id {
+
+ return i;
+
+ }
+
+ }
+
+ return -1 // not found
+
+}
+
+
+
+func getIdFromRequest(req *http.Request) int {
+
+ vars := mux.Vars(req)
+
+ id, _ := strconv.Atoi(vars["id"])
+
+ return id
+
+}
+
+
+
+func getDataFromRequest(req *http.Request) (string, string) {
+
+ // Extract the user-provided data for the new clichePair
+
+ req.ParseForm()
+
+ form := req.Form
+
+ cliche := form["cliche"][0] // 1st and only member of a list
+
+ counter := form["counter"][0] // ditto
+
+ return cliche, counter
+
+}
+
+
+
+func logIt(msg string) {
+
+ fmt.Println(msg)
+
+}
+
+
+
+func populateClichesList() {
+
+ var cliches = []string {
+
+ "Out of sight, out of mind.",
+
+ "A penny saved is a penny earned.",
+
+ "He who hesitates is lost.",
+
+ }
+
+ var counterCliches = []string {
+
+ "Absence makes the heart grow fonder.",
+
+ "Penny-wise and dollar-foolish.",
+
+ "Look before you leap.",
+
+ }
+
+
+
+ for i := 0; i < len(cliches); i++ {
+
+ cp := new(clichePair)
+
+ cp.Id = masterId
+
+ masterId++
+
+ cp.Cliche = cliches[i]
+
+ cp.Counter = counterCliches[i]
+
+ clichesList = append(clichesList, cp)
+
+ }
+
+}
+
+```
+
+To focus on request routing and validation, the crud app does not use HTML pages as responses to requests. Instead, requests result in plaintext response messages: A list of the cliche pairs is the response to a GET request, confirmation that a new cliche pair has been added to the list is a response to a POST request, and so on. This simplification makes it easy to test the app, in particular, the `gorilla/mux` components, with a command-line utility such as [curl][1].
+
+The `gorilla/mux` package can be installed from [GitHub][2]. The crud app runs indefinitely; hence, it should be terminated with a Control-C or equivalent. The code for the crud app, together with a README and sample curl tests, is available on [my website][3].
+
+### 2\. Request routing
+
+The `mux.Router` extends REST-style routing, which gives equal weight to the HTTP method (e.g., GET) and the URI or path at the end of a URL (e.g., /cliches). The URI serves as the noun for the HTTP verb (method). For example, in an HTTP request a startline such as
+```
+GET /cliches
+
+```
+
+means get all of the cliche pairs, whereas a startline such as
+```
+POST /cliches
+
+```
+
+means create a cliche pair from data in the HTTP body.
+
+In the crud web app, there are five functions that act as request handlers for five variations of an HTTP request:
+```
+ClichesAll(...) # GET: get all of the cliche pairs
+
+ClichesOne(...) # GET: get a specified cliche pair
+
+ClichesCreate(...) # POST: create a new cliche pair
+
+ClichesEdit(...) # PUT: edit an existing cliche pair
+
+ClichesDelete(...) # DELETE: delete a specified cliche pair
+
+```
+
+Each function takes two arguments: an `http.ResponseWriter` for sending a response back to the requester, and a pointer to an `http.Request`, which encapsulates information from the underlying HTTP request. The `gorilla/mux` package makes it easy to register these request handlers with the web server, and to perform regex-based validation.
+
+The `startServer` function in the crud app registers the request handlers. Consider this pair of registrations, with `router` as a `mux.Router` instance:
+```
+router.HandleFunc("/", ClichesAll).Methods("GET")
+
+router.HandleFunc("/cliches", ClichesAll).Methods("GET")
+
+```
+
+These statements mean that a GET request for either the single slash / or /cliches should be routed to the `ClichesAll` function, which then handles the request. For example, the curl request (with % as the command-line prompt)
+```
+% curl --request GET localhost:8888/
+
+```
+
+produces this response:
+```
+1: Out of sight, out of mind. Absence makes the heart grow fonder.
+
+2: A penny saved is a penny earned. Penny-wise and dollar-foolish.
+
+3: He who hesitates is lost. Look before you leap.
+
+```
+
+The three cliche pairs are the initial data in the crud app.
+
+In this pair of registration statements
+```
+router.HandleFunc("/cliches", ClichesAll).Methods("GET")
+
+router.HandleFunc("/cliches", ClichesCreate).Methods("POST")
+
+```
+
+the URI is the same (/cliches) but the verbs differ: GET in the first case, and POST in the second. This registration exemplifies REST-style routing because the difference in the verbs alone suffices to dispatch the requests to two different handlers.
+
+More than one HTTP method is allowed in a registration, although this strains the spirit of REST-style routing:
+```
+router.HandleFunc("/cliches", DoItAll).Methods("POST", "GET")
+
+```
+
+HTTP requests can be routed on features besides the verb and the URI. For example, the registration
+```
+router.HandleFunc("/cliches", ClichesCreate).Schemes("https").Methods("POST")
+
+```
+
+requires HTTPS access for a POST request to create a new cliche pair. In similar fashion, a registration might require a request to have a specified HTTP header element (e.g., an authentication credential).
+
+### 3\. Request validation
+
+The `gorilla/mux` package takes an easy, intuitive approach to request validation through regular expressions. Consider this request handler for a get one operation:
+```
+router.HandleFunc("/cliches/{id:[0-9]+}", ClichesOne).Methods("GET")
+
+```
+
+This registration rules out HTTP requests such as
+```
+% curl --request GET localhost:8888/cliches/foo
+
+```
+
+because foo is not a decimal numeral. The request results in the familiar 404 (Not Found) status code. Including the regex pattern in this handler registration ensures that the `ClichesOne` function is called to handle a request only if the request URI ends with a decimal integer value:
+```
+% curl --request GET localhost:8888/cliches/3 # ok
+
+```
+
+As a second example, consider the request
+```
+% curl --request PUT --data "..." localhost:8888/cliches
+
+```
+
+This request results in a status code of 405 (Bad Method) because the /cliches URI is registered, in the crud app, only for GET and POST requests. A PUT request, like a GET one request, must include a numeric id at the end of the URI:
+```
+router.HandleFunc("/cliches/{id:[0-9]+}", ClichesEdit).Methods("PUT")
+
+```
+
+### 4\. Concurrency issues
+
+The `gorilla/mux` router executes each call to a registered request handler as a separate goroutine, which means that concurrency is baked into the package. For example, if there are ten simultaneous requests such as
+```
+% curl --request POST --data "..." localhost:8888/cliches
+
+```
+
+then the `mux.Router` launches ten goroutines to execute the `ClichesCreate` handler.
+
+Of the five request operations GET all, GET one, POST, PUT, and DELETE, the last three alter the requested resource, the shared `clichesList` that houses the cliche pairs. Accordingly, the crudapp needs to guarantee safe concurrency by coordinating access to the `clichesList`. In different but equivalent terms, the crud app must prevent a race condition on the `clichesList`. In a production environment, a database system might be used to store a resource such as the `clichesList`, and safe concurrency then could be managed through database transactions.
+
+The crud app takes the recommended Go approach to safe concurrency:
+
+ * Only a single goroutine, the resource manager started in the crud app `startServer` function, has access to the `clichesList` once the web server starts listening for requests.
+ * The request handlers such as `ClichesCreate` and `ClichesAll` send a (pointer to) a `crudRequest` instance to a Go channel (thread-safe by default), and the resource manager alone reads from this channel. The resource manager then performs the requested operation on the `clichesList`.
+
+
+
+The safe-concurrency architecture can be sketched as follows:
+```
+ crudRequest read/write
+
+request handlers------------->resource manager------------>clichesList
+
+```
+
+With this architecture, no explicit locking of the `clichesList` is needed because only one goroutine, the resource manager, accesses the `clichesList` once CRUD requests start coming in.
+
+To keep the crud app as concurrent as possible, it’s essential to have an efficient division of labor between the request handlers, on the one side, and the single resource manager, on the other side. Here, for review, is the `ClichesCreate` request handler:
+```
+func ClichesCreate(res http.ResponseWriter, req *http.Request) {
+
+ cliche, counter := getDataFromRequest(req)
+
+ cp := new(clichePair)
+
+ cp.Cliche = cliche
+
+ cp.Counter = counter
+
+ cr := &crudRequest{verb: POST, cp: cp, confirm: make(chan string)}
+
+ completeRequest(cr, res, "create")
+
+}ClichesCreateres httpResponseWriterreqclichecountergetDataFromRequestreqcpclichePaircpClicheclichecpCountercountercr&crudRequestverbPOSTcpcpconfirmcompleteRequestcrres
+
+```
+
+`ClichesCreate` calls the utility function `getDataFromRequest`, which extracts the new cliche and counter-cliche from the POST request. The `ClichesCreate` function then creates a new `ClichePair`, sets two fields, and creates a `crudRequest` to be sent to the single resource manager. This request includes a confirmation channel, which the resource manager uses to return information back to the request handler. All of the setup work can be done without involving the resource manager because the `clichesList` is not being accessed yet.
+
+The request handlercalls the utility function, which extracts the new cliche and counter-cliche from the POST request. Thefunction then creates a new, sets two fields, and creates ato be sent to the single resource manager. This request includes a confirmation channel, which the resource manager uses to return information back to the request handler. All of the setup work can be done without involving the resource manager because theis not being accessed yet.
+
+The `completeRequest` utility function called at the end of the `ClichesCreate` function and the other request handlers
+```
+completeRequest(cr, res, "create") // shown above
+
+```
+
+brings the resource manager into play by putting a `crudRequest` into the `crudRequests` channel:
+```
+func completeRequest(cr *crudRequest, res http.ResponseWriter, logMsg string) {
+
+ crudRequests<-cr // send request to resource manager
+
+ msg := <-cr.confirm // await confirmation string
+
+ res.Write([]byte(msg)) // send confirmation back to requester
+
+ logIt(logMsg) // print to the standard output
+
+}
+
+```
+
+For a POST request, the resource manager calls the utility function `addPair`, which changes the `clichesList` resource:
+```
+func addPair(cp *clichePair) string {
+
+ cp.Id = masterId // assign a unique ID
+
+ masterId++ // update the ID counter
+
+ clichesList = append(clichesList, cp) // update the list
+
+ return "\nCreated: " + cp.Cliche + " " + cp.Counter + "\n"
+
+}
+
+```
+
+The resource manager calls similar utility functions for the other CRUD operations. It’s worth repeating that the resource manager is the only goroutine to read or write the `clichesList` once the web server starts accepting requests.
+
+For web applications of any type, the `gorilla/mux` package provides request routing, request validation, and related services in a straightforward, intuitive API. The crud web app highlights the package’s main features. Give the package a test drive, and you’ll likely be a buyer.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/http-request-routing-validation-gorillamux
+
+作者:[Marty Kalin][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/mkalindepauledu
+[1]:https://curl.haxx.se/
+[2]:https://github.com/gorilla/mux
+[3]:http://condor.depaul.edu/mkalin
diff --git a/sources/tech/20180814 Top Linux developers- recommended programming books.md b/sources/tech/20180814 Top Linux developers- recommended programming books.md
new file mode 100644
index 0000000000..d9337ed319
--- /dev/null
+++ b/sources/tech/20180814 Top Linux developers- recommended programming books.md
@@ -0,0 +1,95 @@
+Top Linux developers' recommended programming books
+======
+Without question, Linux was created by brilliant programmers who employed good computer science knowledge. Let the Linux programmers whose names you know share the books that got them started and the technology references they recommend for today's developers. How many of them have you read?
+
+Linux is, arguably, the operating system of the 21st century. While Linus Torvalds made a lot of good business and community decisions in building the open source community, the primary reason networking professionals and developers adopted Linux is the quality of its code and its usefulness. While Torvalds is a programming genius, he has been assisted by many other brilliant developers.
+
+I asked Torvalds and other top Linux developers which books helped them on their road to programming excellence. This is what they told me.
+
+### By shining C
+
+Linux was developed in the 1990s, as were other fundamental open source applications. As a result, the tools and languages the developers used reflected the times, which meant a lot of C programming language. While [C is no longer as popular][1], for many established developers it was their first serious language, which is reflected in their choice of influential books.
+
+“You shouldn't start programming with the languages I started with or the way I did,” says Torvalds. He started with BASIC, moved on to machine code (“not even assembly language, actual ‘just numbers’ machine code,” he explains), then assembly language and C.
+
+“None of those languages are what anybody should begin with anymore,” Torvalds says. “Some of them make no sense at all today (BASIC and machine code). And while C is still a major language, I don't think you should begin with it.”
+
+It's not that he dislikes C. After all, Linux is written in [GNU C][2]. "I still think C is a great language with a pretty simple syntax and is very good for many things,” he says. But the effort to get started with it is much too high for it to be a good beginner language by today's standards. “I suspect you'd just get frustrated. Going from your first ‘Hello World’ program to something you might actually use is just too big of a step."
+
+From that era, the only programming book that stood out for Torvalds is Brian W. Kernighan and Dennis M. Ritchie's [C Programming Language][3], known in serious programming circles as K&R. “It was small, clear, concise,” he explains. “But you need to already have a programming background to appreciate it."
+
+Torvalds is not the only open source developer to recommend K&R. Several others cite their well-thumbed copies as influential references, among them Wim Coekaerts, senior vice president for Linux and virtualization development at Oracle; Linux developer Alan Cox; Google Cloud CTO Brian Stevens; and Pete Graner, Canonical's vice president of technical operations.
+
+If you want to tackle C today, Jeremy Allison, co-founder of Samba, recommends [21st Century C][4]. Then, Allison suggests, follow it up with the older but still thorough [Expert C Programming][5] as well as the 20-year-old [Programming with POSIX Threads][6].
+
+### If not C, what?
+
+Linux developers’ recommendations for current programming books naturally are an offshoot of the tools and languages they think are most suitable for today’s development projects. They also reflect the developers’ personal preferences. For example, Allison thinks young developers would be well served by learning Go with the help of [The Go Programming Language][7] and Rust with [Programming Rust][8].
+
+But it may make sense to think beyond programming languages (and thus books to teach you their techniques). To do something meaningful today, “start from some environment with a toolkit that does 99 percent of the obscure details for you, so that you can script things around it," Torvalds recommends.
+
+"Honestly, the language itself isn't nearly as important as the infrastructure around it,” he continues. “Maybe you'd start with Java or Kotlin—not because of those languages per se, but because you want to write an app for your phone and the Android SDK ends up making those better choices. Or, maybe you're interested in games, so you start with one of the game engines, which often have some scripting language of their own."
+
+That infrastructure includes programming books specific to the operating system itself. Graner followed K&R by reading W. Richard Stevens' [Unix Network Programming][10] books. In particular, Stevens' [TCP/IP Illustrated, Volume 1: The Protocols][11] is considered still relevant even though it's almost 30 years old. Because Linux development is largely [relevant to networking infrastructure][12], Graner also recommends the many O’Reilly books on [Sendmail][13], [Bash][14], [DNS][15], and [IMAP/POP][16].
+
+Coekaerts is also fond of Maurice Bach's [The Design of the Unix Operating System][17]. So is James Bottomley, a Linux kernel developer who used Bach's tome to pull apart Linux when the OS was new.
+
+### Design knowledge never goes stale
+
+But even that may be too tech-specific. "All developers should start with design before syntax,” says Stevens. “[The Design of Everyday Things][18] is one of my favorites.”
+
+Coekaerts likes Kernighan and Rob Pike's [The Practice of Programming][19]. The design-practice book wasn't around when Coekaerts was in school, “but I recommend it to everyone to read," he says.
+
+Whenever you ask serious long-term developers about their favorite books, sooner or later someone's going to mention Donald Knuth’s [The Art of Computer Programming][20]. Dirk Hohndel, VMware's chief open source officer, considers it timeless though, admittedly, “not necessarily super-useful today."
+
+### Read code. Lots of code
+
+While programming books can teach you a lot, don’t miss another opportunity that is unique to the open source community: [reading the code][21]. There are untold megabytes of examples of how to solve a given programming problem—and how you can get in trouble, too. Stevens says his No. 1 “book” for honing programming skills is having access to the Unix source code.
+
+Don’t overlook the opportunity to learn in person, too. “I learned BASIC by being in a computer club with other people all learning together,” says Cox. “In my opinion, that is still by far the best way to learn." He learned machine code from [Mastering Machine Code on Your ZX81][22] and the Honeywell L66 B compiler manuals, but working with other developers made a big difference.
+
+“I still think the way to learn best remains to be with a group of people having fun and trying to solve a problem you care about together,” says Cox. “It doesn't matter if you are 5 or 55."
+
+What struck me the most about these recommendations is how often the top Linux developers started at a low level—not just C or assembly language but machine language. Obviously, it’s been very useful in helping developers understand how computing works at a very basic level.
+
+So, ready to give hard-core Linux development a try? Greg Kroah-Hartman, the Linux stable branch kernel maintainer, recommends Steve Oualline's [Practical C Programming][23] and Samuel Harbison and Guy Steele's [C: A Reference Manual][24]. Next, read "[HOWTO do Linux kernel development][25]." Then, says Kroah-Hartman, you'll be ready to start.
+
+In the meantime, study hard, program lots, and best of luck to you in following the footsteps of Linux's top programmers.
+
+--------------------------------------------------------------------------------
+
+via: https://www.hpe.com/us/en/insights/articles/top-linux-developers-recommended-programming-books-1808.html
+
+作者:[Steven Vaughan-Nichols][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://www.hpe.com/us/en/insights/contributors/steven-j-vaughan-nichols.html
+[1]:https://www.codingdojo.com/blog/7-most-in-demand-programming-languages-of-2018/
+[2]:https://www.gnu.org/software/gnu-c-manual/
+[3]:https://amzn.to/2nhyjEO
+[4]:https://amzn.to/2vsL8k9
+[5]:https://amzn.to/2KBbWn9
+[6]:https://amzn.to/2M0rfeR
+[7]:https://amzn.to/2nhyrnMe
+[8]:http://shop.oreilly.com/product/0636920040385.do
+[9]:https://www.hpe.com/us/en/resources/storage/containers-for-dummies.html?jumpid=in_510384402_linuxbooks_containerebook0818
+[10]:https://amzn.to/2MfpbyC
+[11]:https://amzn.to/2MpgrTn
+[12]:https://www.hpe.com/us/en/insights/articles/how-to-see-whats-going-on-with-your-linux-system-right-now-1807.html
+[13]:http://shop.oreilly.com/product/9780596510299.do
+[14]:http://shop.oreilly.com/product/9780596009656.do
+[15]:http://shop.oreilly.com/product/9780596100575.do
+[16]:http://shop.oreilly.com/product/9780596000127.do
+[17]:https://amzn.to/2vsCJgF
+[18]:https://amzn.to/2APzt3Z
+[19]:https://www.amazon.com/Practice-Programming-Addison-Wesley-Professional-Computing/dp/020161586X/ref=as_li_ss_tl?ie=UTF8&linkCode=sl1&tag=thegroovycorpora&linkId=e6bbdb1ca2182487069bf9089fc8107e&language=en_US
+[20]:https://amzn.to/2OknFsJ
+[21]:https://amzn.to/2M4VVL3
+[22]:https://amzn.to/2OjccJA
+[23]:http://shop.oreilly.com/product/9781565923065.do
+[24]:https://amzn.to/2OjzgrT
+[25]:https://www.kernel.org/doc/html/v4.16/process/howto.html
diff --git a/sources/tech/20180815 Happy birthday, GNOME- 6 reasons to love this Linux desktop.md b/sources/tech/20180815 Happy birthday, GNOME- 6 reasons to love this Linux desktop.md
new file mode 100644
index 0000000000..590a83a62d
--- /dev/null
+++ b/sources/tech/20180815 Happy birthday, GNOME- 6 reasons to love this Linux desktop.md
@@ -0,0 +1,71 @@
+Happy birthday, GNOME: 6 reasons to love this Linux desktop
+======
+
+
+
+GNOME has been my favorite [desktop environment][1] for quite some time. While I always make it a point to check out other environments from time to time, there are some aspects of the GNOME desktop that are hard to live without. While there are many great desktop environments out there, [GNOME][2] feels like home to me. Here are some of the features I enjoy most about GNOME.
+
+### Stability
+
+Having a stable working environment is the most important aspect of a desktop for me. After all, the feature set of an environment doesn't matter at all if it crashes constantly and you lose work. For me, GNOME is rock-solid. I have heard of others experiencing crashes and instability, but it always seems to be due to either the user running GNOME on unsupported hardware or due to faulty extensions (more on that later). On my end, I run GNOME primarily on hardware that is known to be well-supported in Linux ([System76][3], for example). I also have a few systems that are not as well supported (a custom-built desktop and a Dell Latitude laptop), and I actually don't have any issues there either. For me, GNOME is rock-solid. I have compared stability in other well-known desktop environments, and I had unfortunate results. Nothing comes close to GNOME when it comes to stability.
+
+### Extensions
+
+I really enjoy being able to add additional functionality to my environment. I don't necessarily require any extensions, because I am perfectly fine with stock-GNOME with no extensions whatsoever. However, having the ability to add a few things here and there, is welcome. GNOME features various extensions to do things such as add a weather display to your panel, and much more. This adds a level of customization that is not typical of other environments. That said, proceed with caution. Sometimes extensions are of varying quality and may lead to stability issues. I find though that if you only install extensions you absolutely need, and you make sure they're kept up to date (and aren't abandoned by the developer) you'll generally be in good shape.
+
+### Activities overview
+
+Activities overview is quite possibly the easiest feature to use in GNOME, and it's barely detailed enough to justify its own section in this article. However, when I use other desktop environments, I miss this feature the most.
+
+The thing is, I am very busy, with multiple projects going on at any one time, and dozens of different windows open. To access the activities overview, I simply press the Super key. Immediately, my workspace is "zoomed out" and I see all of my windows side-by-side. This is often a faster way to locate a window that is hidden behind others, and a good way overall to see what exactly is running on any given workspace.
+
+When using other desktop environments, I will often find myself pressing the Super key out of habit, only to remember that I'm not using GNOME at the time. There are ways of achieving similar behavior in other environments (such as installing and tweaking Compiz), but in GNOME this feature is built-in.
+
+### Dynamic workspaces
+
+While working, I am not sure up-front how many workspaces I will need. Sometimes I can be working on three projects at a time, or as many as ten. With most desktop environments, I can access the settings screen and add or remove workspaces as needed. But with GNOME, I have exactly as many workspaces as I need at any given time. Every time I open applications on a workspace, I am given another blank one that I can switch to in order to start another project. Typically, I keep all windows related to a specific project on their own workspace, so it makes it very easy to locate my workflow for a given project.
+
+Other desktop environments have really good implementations of the concept of workspaces, but GNOME's implementation works best for me.
+
+### Simplicity
+
+Another thing I love about GNOME is that it's simple and straight to the point. By default, there is only one panel, and it's at the top of the screen. This panel shows you a small amount of information, such as the date, time, and battery usage. GNOME 2 had two panels, so seeing GNOME stripped down to a single panel is welcome and saves room on the screen. Most of the things you don't need to see all the time are hidden within the Activities overview, leaving you with the maximum amount of screen space for the application(s) you are working on. GNOME just stays out of the way and lets you focus on getting your work done, and stays away from fancy widgets and desktop gadgets that just aren't necessary.
+
+
+In addition, GNOME has really great support for keyboard shortcuts. Most of GNOME's features I can access without needing to touch my mouse, such as SUPER+Page Up and Super Page Down to switch workspaces, Super+Up arrow to maximize windows, etc. In addition, I am able to easily create my own keyboard shortcuts for all of my favorite applications.
+
+### GNOME Boxes
+
+GNOME's Boxes app is an underrated gem. This utility makes it very easy to spin up a virtual machine, which is a godsend among developers and those that like to test configurations on multiple distributions and platforms. With Boxes, you can spin up a virtual machine at any time, and it will even automate the installation process for you. For example, if you want a new Ubuntu VM, you simply choose Ubuntu as your desired platform, fill out your username and any related information, and you will have a new Ubuntu VM in a few minutes. When you're done with it, you can power it down or trash it.
+
+For me, I do a lot of DevOps-style work as well as system administration. Being able to test a configuration on a virtual machine before deploying to another environment is great. Sure, you can do the exact same thing in VirtualBox, and VirtualBox is a great piece of software. However, Boxes is built right into GNOME, and desktop environments generally don't offer their own solution for virtualization.
+
+### GNOME Music
+
+While I work, I have difficulty tuning out noise in my environment. Therefore, I like to listen to music while I complete projects and tune out the rest of the world. GNOME's Music app is very simplistic and works very well. With most of the music industry gravitating toward streaming music online, and many once-popular [open source music players][7] becoming abandoned projects, it's nice to see GNOME support a built-in music player that can play my music collection. It's great to listen to my music collection while I work, and it helps me zone-in to what I am doing.
+
+### GNOME Games
+
+When work is done for the day, it's time to play! There's nothing like playing a classic game such as Final Fantasy VI or Super Metroid after a hard day's work. The thing is, I am a huge fan of classic gaming, and I have 22 working gaming consoles and somewhere near 1,000 physical games in my collection. But I may not always have a moment to hook up one of my retro-consoles, so GNOME Games allows me quick-access to emulated versions of my collection. In addition to that, it also works with Libretro cores as well, so it seems to me that the developers of this application have really thought-out what fans of classic gaming like me are looking for in a frontend for gaming.
+
+These are the major features I enjoy most in the GNOME desktop. What are some of yours?
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/8/what-i-love-about-gnome
+
+作者:[Jay LaCroix][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/jlacroix
+[1]:https://opensource.com/article/18/8/how-navigate-your-gnome-linux-desktop-only-keyboard
+[2]:https://opensource.com/article/17/8/reasons-i-come-back-gnome
+[3]:https://opensource.com/article/16/12/open-gaming-news-december-31
+[4]:https://opensource.com/file/407221
+[5]:https://opensource.com/sites/default/files/uploads/gnome3-cheatsheet.png (GNOME 3 Cheat Sheet)
+[6]:https://opensource.com/downloads/cheat-sheet-gnome-3
+[7]:https://opensource.com/article/18/6/open-source-music-players
diff --git a/sources/tech/20180815 How to Create M3U Playlists in Linux [Quick Tip].md b/sources/tech/20180815 How to Create M3U Playlists in Linux [Quick Tip].md
new file mode 100644
index 0000000000..3c0b63d63b
--- /dev/null
+++ b/sources/tech/20180815 How to Create M3U Playlists in Linux [Quick Tip].md
@@ -0,0 +1,84 @@
+translating by lujun9972
+How to Create M3U Playlists in Linux [Quick Tip]
+======
+**Brief: A quick tip on how to create M3U playlists in Linux terminal from unordered files to play them in a sequence.**
+
+![Create M3U playlists in Linux Terminal][1]
+
+I am a fan of foreign tv series and it’s not always easy to get them on DVD or on streaming services like [Netflix][2]. Thankfully, you can find some of them on YouTube and [download them from YouTube][3].
+
+Now there comes a problem. Your files might not be sorted in a particular order. In GNU/Linux files are not naturally sort ordered by number sequencing so I had to make a .m3u playlist so [MPV video player][4] would play the videos in sequence and not out of sequence.
+
+Also sometimes the numbers are in the middle or the end like ‘My Web Series S01E01.mkv’ as an example. The episode information here is in the middle of the filename, the ‘S01E01’ which tells us, humans, which is the first episode and which needs to come in next.
+
+So what I did was to generate an m3u playlist in the video directory and tell MPV to play the .m3u playlist and it would take care of playing them in the sequence.
+
+### What is an M3U file?
+
+[M3U][5] is basically a text file that contains filenames in a specific order. When a player like MPV or VLC opens an M3U file, it tries to play the specified files in the given sequence.
+
+### Creating M3U to play audio/video files in a sequence
+
+In my case, I used the following command:
+```
+$/home/shirish/Videos/web-series-video/$ ls -1v |grep .mkv > /tmp/1.m3u && mv /tmp/1.m3u .
+
+```
+
+Let’s break it down a bit and see each bit as to what it means –
+
+**ls -1v** = This is using the plain ls or listing entries in the directory. The -1 means list one file per line. while -v natural sort of (version) numbers within text
+
+**| grep .mkv** = It’s basically telling `ls` to look for files which are ending in .mkv . It could be .mp4 or any other media file format that you want.
+
+It’s usually a good idea to do a dry run by running the command on the console:
+```
+ls -1v |grep .mkv
+My Web Series S01E01 [Episode 1 Name] Multi 480p WEBRip x264 - xRG.mkv
+My Web Series S01E02 [Episode 2 Name] Multi 480p WEBRip x264 - xRG.mkv
+My Web Series S01E03 [Episode 3 Name] Multi 480p WEBRip x264 - xRG.mkv
+My Web Series S01E04 [Episode 4 Name] Multi 480p WEBRip x264 - xRG.mkv
+My Web Series S01E05 [Episode 5 Name] Multi 480p WEBRip x264 - xRG.mkv
+My Web Series S01E06 [Episode 6 Name] Multi 480p WEBRip x264 - xRG.mkv
+My Web Series S01E07 [Episode 7 Name] Multi 480p WEBRip x264 - xRG.mkv
+My Web Series S01E08 [Episode 8 Name] Multi 480p WEBRip x264 - xRG.mkv
+
+```
+
+This tells me that what I’m trying to do is correct. Now just have to make that the output is in the form of a .m3u playlist which is the next part.
+```
+ls -1v |grep .mkv > /tmp/web_playlist.m3u && mv /tmp/web_playlist.m3u .
+
+```
+
+This makes the .m3u generate in the current directory. The .m3u playlist is nothing but a .txt file with the same contents as above with the .m3u extension. You can edit it manually as well and add the exact filenames in an order you desire.
+
+After that you just have to do something like this:
+```
+mpv web_playlist.m3u
+
+```
+
+The great thing about MPV and the playlists, in general, is that you don’t have to binge-watch. You can see however much you want to do in one sitting and see the rest in the next session or the session after that.
+
+I hope to do articles featuring MPV as well as how to make mkv files embedding subtitles in a media file but that’s in the future.
+
+Note: It’s FOSS doesn’t encourage piracy.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/create-m3u-playlist-linux/
+
+作者:[Shirsh][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/shirish/
+[1]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/08/Create-M3U-Playlists.jpeg
+[2]:https://itsfoss.com/netflix-open-source-ai/
+[3]:https://itsfoss.com/download-youtube-linux/
+[4]:https://itsfoss.com/mpv-video-player/
+[5]:https://en.wikipedia.org/wiki/M3U
diff --git a/sources/tech/20180816 An introduction to the Django Python web app framework.md b/sources/tech/20180816 An introduction to the Django Python web app framework.md
new file mode 100644
index 0000000000..ab7dba9526
--- /dev/null
+++ b/sources/tech/20180816 An introduction to the Django Python web app framework.md
@@ -0,0 +1,1250 @@
+Translating by MjSeven
+
+
+An introduction to the Django Python web app framework
+======
+
+
+
+In the first three articles of this four-part series comparing different Python web frameworks, we covered the [Pyramid][1], [Flask][2], and [Tornado][3] web frameworks. We've built the same app three times and have finally made our way to [Django][4]. Django is, by and large, the major web framework for Python developers these days and it's not too hard to see why. It excels in hiding a lot of the configuration logic and letting you focus on being able to build big, quickly.
+
+That said, when it comes to small projects, like our To-Do List app, Django can be a bit like bringing a firehose to a water gun fight. Let's see how it all comes together.
+
+### About Django
+
+Django styles itself as "a high-level Python web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of web development, so you can focus on writing your app without needing to reinvent the wheel." And they really mean it! This massive web framework comes with so many batteries included that oftentimes during development it can be a mystery as to how everything manages to work together.
+
+In addition to the framework itself being large, the Django community is absolutely massive. In fact, it's so big and active that there's [a whole website][5] devoted to the third-party packages people have designed to plug into Django to do a whole host of things. This includes everything from authentication and authorization, to full-on Django-powered content management systems, to e-commerce add-ons, to integrations with Stripe. Talk about not re-inventing the wheel; chances are if you want something done with Django, someone has already done it and you can just pull it into your project.
+
+For this purpose, we want to build a REST API with Django, so we'll leverage the always popular [Django REST framework][6]. Its job is to turn the Django framework, which was made to serve fully rendered HTML pages built with Django's own templating engine, into a system specifically geared toward effectively handling REST interactions. Let's get going with that.
+
+### Django startup and configuration
+```
+$ mkdir django_todo
+
+$ cd django_todo
+
+$ pipenv install --python 3.6
+
+$ pipenv shell
+
+(django-someHash) $ pipenv install django djangorestframework
+
+```
+
+For reference, we're working with `django-2.0.7` and `djangorestframework-3.8.2`.
+
+Unlike Flask, Tornado, and Pyramid, we don't need to write our own `setup.py` file. We're not making an installable Python distribution. As with many things, Django takes care of that for us in its own Django way. We'll still need a `requirements.txt` file to track all our necessary installs for deployment elsewhere. However, as far as targeting modules within our Django project goes, Django will let us list the subdirectories we want access to, then allow us to import from those directories as if they're installed packages.
+
+First, we have to create a Django project.
+
+When we installed Django, we also installed the command-line script `django-admin`. Its job is to manage all the various Django-related commands that help put our project together and maintain it as we continue to develop. Instead of having us build up the entire Django ecosystem from scratch, the `django-admin` will allow us to get started with all the absolutely necessary files (and more) we need for a standard Django project.
+
+The syntax for invoking `django-admin`'s start-project command is `django-admin startproject `. We want the files to exist in our current working directory, so:
+```
+(django-someHash) $ django-admin startproject django_todo .
+
+```
+
+Typing `ls` will show one new file and one new directory.
+```
+(django-someHash) $ ls
+
+manage.py django_todo
+
+```
+
+`manage.py` is a command-line-executable Python file that ends up just being a wrapper around `django-admin`. As such, its job is the same: to help us manage our project. Hence the name `manage.py`.
+
+The directory it created, the `django_todo` inside of `django_todo`, represents the configuration root for our project. Let's dig into that now.
+
+### Configuring Django
+
+By calling the `django_todo` directory the "configuration root," we mean this directory holds the files necessary for generally configuring our Django project. Pretty much everything outside this directory will be focused solely on the "business logic" associated with the project's models, views, routes, etc. All points that connect the project together will lead here.
+
+Calling `ls` within `django_todo` reveals four files:
+```
+(django-someHash) $ cd django_todo
+
+(django-someHash) $ ls
+
+__init__.py settings.py urls.py wsgi.py
+
+```
+
+ * `__init__.py` is empty, solely existing to turn this directory into an importable Python package.
+ * `settings.py` is where most configuration items will be set, like whether the project's in DEBUG mode, what databases are in use, where Django should look for files, etc. It is the "main configuration" part of the configuration root, and we'll dig into that momentarily.
+ * `urls.py` is, as the name implies, where the URLs are set. While we don't have to explicitly write every URL for the project in this file, we **do** need to make this file aware of any other places where URLs have been declared. If this file doesn't point to other URLs, those URLs don't exist. **Period.**
+ * `wsgi.py` is for serving the application in production. Just like how Pyramid, Tornado, and Flask exposed some "app" object that was the configured application to be served, Django must also expose one. That's done here. It can then be served with something like [Gunicorn][7], [Waitress][8], or [uWSGI][9].
+
+
+
+#### Setting the settings
+
+Taking a look inside `settings.py` will reveal its considerable size—and these are just the defaults! This doesn't even include hooks for the database, static files, media files, any cloud integration, or any of the other dozens of ways that a Django project can be configured. Let's see, top to bottom, what we've been given:
+
+ * `BASE_DIR` sets the absolute path to the base directory, or the directory where `manage.py` is located. This is useful for locating files.
+ * `SECRET_KEY` is a key used for cryptographic signing within the Django project. In practice, it's used for things like sessions, cookies, CSRF protection, and auth tokens. As soon as possible, preferably before the first commit, the value for `SECRET_KEY` should be changed and moved into an environment variable.
+ * `DEBUG` tells Django whether to run the project in development mode or production mode. This is an extremely critical distinction.
+ * In development mode, when an error pops up, Django will show the full stack trace that led to the error, as well as all the settings and configurations involved in running the project. This can be a massive security issue if `DEBUG` was set to `True` in a production environment.
+ * In production, Django shows a plain error page when things go wrong. No information is given beyond an error code.
+ * A simple way to safeguard our project is to set `DEBUG` to an environment variable, like `bool(os.environ.get('DEBUG', ''))`.
+ * `ALLOWED_HOSTS` is the literal list of hostnames from which the application is being served. In development this can be empty, but in production our Django project will not run if the host that serves the project is not among the list of ALLOWED_HOSTS. Another thing for the box of environment variables.
+ * `INSTALLED_APPS` is the list of Django "apps" (think of them as subdirectories; more on this later) that our Django project has access to. We're given a few by default to provide…
+ * The built-in Django administrative website
+ * Django's built-in authentication system
+ * Django's one-size-fits-all manager for data models
+ * Session management
+ * Cookie and session-based messaging
+ * Usage of static files inherent to the site, like `css` files, `js` files, any images that are a part of our site's design, etc.
+ * `MIDDLEWARE` is as it sounds: the middleware that helps our Django project run. Much of it is for handling various types of security, although we can add others as we need them.
+ * `ROOT_URLCONF` sets the import path of our base-level URL configuration file. That `urls.py` that we saw before? By default, Django points to that file to gather all our URLs. If we want Django to look elsewhere, we'll set the import path to that location here.
+ * `TEMPLATES` is the list of template engines that Django would use for our site's frontend if we were relying on Django to build our HTML. Since we're not, it's irrelevant.
+ * `WSGI_APPLICATION` sets the import path of our WSGI application—the thing that gets served when in production. By default, it points to an `application` object in `wsgi.py`. This rarely, if ever, needs to be modified.
+ * `DATABASES` sets which databases our Django project will access. The `default` database must be set. We can set others by name, as long as we provide the `HOST`, `USER`, `PASSWORD`, `PORT`, database `NAME`, and appropriate `ENGINE`. As one might imagine, these are all sensitive pieces of information, so it's best to hide them away in environment variables. [Check the Django docs][10] for more details.
+ * Note: If instead of providing individual pieces of a database's location, you'd rather provide the full database URL, check out [dj_database_url][11].
+ * `AUTH_PASSWORD_VALIDATORS` is effectively a list of functions that run to check input passwords. We get a few by default, but if we had other, more complex validation needs—more than merely checking if the password matches a user's attribute, if it exceeds the minimum length, if it's one of the 1,000 most common passwords, or if the password is entirely numeric—we could list them here.
+ * `LANGUAGE_CODE` will set the language for the site. By default it's US English, but we could switch it up to be other languages.
+ * `TIME_ZONE` is the time zone for any autogenerated timestamps in our Django project. I cannot stress enough how important it is that we stick to UTC and perform any time zone-specific processing elsewhere instead of trying to reconfigure this setting. As [this article][12] states, UTC is the common denominator among all time zones because there are no offsets to worry about. If offsets are that important, we could calculate them as needed with an appropriate offset from UTC.
+ * `USE_I18N` will let Django use its own translation services to translate strings for the front end. I18N = internationalization (18 characters between "i" and "n")
+ * `USE_L10N` (L10N = localization [10 characters between "l" and "n"]) will use the common local formatting of data if set to `True`. A great example is dates: in the US it's MM-DD-YYYY. In Europe, dates tend to be written DD-MM-YYYY
+ * `STATIC_URL` is part of a larger body of settings for serving static files. We'll be building a REST API, so we won't need to worry about static files. In general, this sets the root path after the domain name for every static file. So, if we had a logo image to serve, it'd be `http:////logo.gif`
+
+
+
+These settings are pretty much ready to go by default. One thing we'll have to change is the `DATABASES` setting. First, we create the database that we'll be using with:
+```
+(django-someHash) $ createdb django_todo
+
+```
+
+We want to use a PostgreSQL database like we did with Flask, Pyramid, and Tornado. That means we'll have to change the `DATABASES` setting to allow our server to access a PostgreSQL database. First: the engine. By default, the database engine is `django.db.backends.sqlite3`. We'll be changing that to `django.db.backends.postgresql`.
+
+For more information about Django's available engines, [check the docs][13]. Note that while it is technically possible to incorporate a NoSQL solution into a Django project, out of the box, Django is strongly biased toward SQL solutions.
+
+Next, we have to specify the key-value pairs for the different parts of the connection parameters.
+
+ * `NAME` is the name of the database we just created.
+ * `USER` is an individual's Postgres database username
+ * `PASSWORD` is the password needed to access the database
+ * `HOST` is the host for the database. `localhost` or `127.0.0.1` will work, as we're developing locally.
+ * `PORT` is whatever PORT we have open for Postgres; it's typically `5432`.
+
+
+
+`settings.py` expects us to provide string values for each of these keys. However, this is highly sensitive information. That's not going to work for any responsible developer. There are several ways to address this problem, but we'll just set up environment variables.
+```
+DATABASES = {
+
+ 'default': {
+
+ 'ENGINE': 'django.db.backends.postgresql',
+
+ 'NAME': os.environ.get('DB_NAME', ''),
+
+ 'USER': os.environ.get('DB_USER', ''),
+
+ 'PASSWORD': os.environ.get('DB_PASS', ''),
+
+ 'HOST': os.environ.get('DB_HOST', ''),
+
+ 'PORT': os.environ.get('DB_PORT', ''),
+
+ }
+
+}
+
+```
+
+Before going forward, make sure to set the environment variables or Django will not work. Also, we need to install `psycopg2` into this environment so we can talk to our database.
+
+### Django routes and views
+
+Let's make something function inside this project. We'll be using Django REST Framework to construct our REST API, so we have to make sure we can use it by adding `rest_framework` to the end of `INSTALLED_APPS` in `settings.py`.
+```
+INSTALLED_APPS = [
+
+ 'django.contrib.admin',
+
+ 'django.contrib.auth',
+
+ 'django.contrib.contenttypes',
+
+ 'django.contrib.sessions',
+
+ 'django.contrib.messages',
+
+ 'django.contrib.staticfiles',
+
+ 'rest_framework'
+
+]
+
+```
+
+While Django REST Framework doesn't exclusively require class-based views (like Tornado) to handle incoming requests, it is the preferred method for writing views. Let's define one.
+
+Let's create a file called `views.py` in `django_todo`. Within `views.py`, we'll create our "Hello, world!" view.
+```
+# in django_todo/views.py
+
+from rest_framework.response import JsonResponse
+
+from rest_framework.views import APIView
+
+
+
+class HelloWorld(APIView):
+
+ def get(self, request, format=None):
+
+ """Print 'Hello, world!' as the response body."""
+
+ return JsonResponse("Hello, world!")
+
+```
+
+Every Django REST Framework class-based view inherits either directly or indirectly from `APIView`. `APIView` handles a ton of stuff, but for our purposes it does these specific things:
+
+ * Sets up the methods needed to direct traffic based on the HTTP method (e.g. GET, POST, PUT, DELETE)
+ * Populates the `request` object with all the data and attributes we'll need for parsing and processing any incoming request
+ * Takes the `Response` or `JsonResponse` that every dispatch method (i.e., methods named `get`, `post`, `put`, `delete`) returns and constructs a properly formatted HTTP response.
+
+
+
+Yay, we have a view! On its own it does nothing. We need to connect it to a route.
+
+If we hop into `django_todo/urls.py`, we reach our default URL configuration file. As mentioned earlier: If a route in our Django project is not included here, it doesn't exist.
+
+We add desired URLs by adding them to the given `urlpatterns` list. By default, we get a whole set of URLs for Django's built-in site administration backend. We'll delete that completely.
+
+We also get some very helpful doc strings that tell us exactly how to add routes to our Django project. We'll need to provide a call to `path()` with three parameters:
+
+ * The desired route, as a string (without the leading slash)
+ * The view function (only ever a function!) that will handle that route
+ * The name of the route in our Django project
+
+
+
+Let's import our `HelloWorld` view and attach it to the home route `"/"`. We can also remove the path to the `admin` from `urlpatterns`, as we won't be using it.
+```
+# django_todo/urls.py, after the big doc string
+
+from django.urls import path
+
+from django_todo.views import HelloWorld
+
+
+
+urlpatterns = [
+
+ path('', HelloWorld.as_view(), name="hello"),
+
+]
+
+```
+
+Well, this is different. The route we specified is just a blank string. Why does that work? Django assumes that every path we declare begins with a leading slash. We're just specifying routes to resources after the initial domain name. If a route isn't going to a specific resource and is instead just the home page, the route is just `""`, or effectively "no resource."
+
+The `HelloWorld` view is imported from that `views.py` file we just created. In order to do this import, we need to update `settings.py` to include `django_todo` in the list of `INSTALLED_APPS`. Yeah, it's a bit weird. Here's one way to think about it.
+
+`INSTALLED_APPS` refers to the list of directories or packages that Django sees as importable. It's Django's way of treating individual components of a project like installed packages without going through a `setup.py`. We want the `django_todo` directory to be treated like an importable package, so we include that directory in `INSTALLED_APPS`. Now, any module within that directory is also importable. So we get our view.
+
+The `path` function will ONLY take a view function as that second argument, not just a class-based view on its own. Luckily, all valid Django class-based views include this `.as_view()` method. Its job is to roll up all the goodness of the class-based view into a view function and return that view function. So, we never have to worry about making that translation. Instead, we only have to think about the business logic, letting Django and Django REST Framework handle the rest.
+
+Let's crack this open in the browser!
+
+Django comes packaged with its own local development server, accessible through `manage.py`. Let's navigate to the directory containing `manage.py` and type:
+```
+(django-someHash) $ ./manage.py runserver
+
+Performing system checks...
+
+
+
+System check identified no issues (0 silenced).
+
+August 01, 2018 - 16:47:24
+
+Django version 2.0.7, using settings 'django_todo.settings'
+
+Starting development server at http://127.0.0.1:8000/
+
+Quit the server with CONTROL-C.
+
+```
+
+When `runserver` is executed, Django does a check to make sure the project is (more or less) wired together correctly. It's not fool-proof, but it does catch some glaring issues. It also notifies us if our database is out of sync with our code. Undoubtedly ours is because we haven't committed any of our application's stuff to our database, but that's fine for now. Let's visit `http://127.0.0.1:8000` to see the output of the `HelloWorld` view.
+
+Huh. That's not the plaintext data we saw in Pyramid, Flask, and Tornado. When Django REST Framework is used, the HTTP response (when viewed in the browser) is this sort of rendered HTML, showing our actual JSON response in red.
+
+But don't fret! If we do a quick `curl` looking at `http://127.0.0.1:8000` in the command line, we don't get any of that fancy HTML. Just the content.
+```
+# Note: try this in a different terminal window, outside of the virtual environment above
+
+$ curl http://127.0.0.1:8000
+
+"Hello, world!"
+
+```
+
+Bueno!
+
+Django REST Framework wants us to have a human-friendly interface when using the browser. This makes sense; if JSON is viewed in the browser, it's typically because a human wants to check that it looks right or get a sense of what the JSON response will look like as they design some consumer of an API. It's a lot like what you'd get from a service like [Postman][14].
+
+Either way, we know our view is working! Woo! Let's recap what we've done:
+
+ 1. Started the project with `django-admin startproject `
+ 2. Updated the `django_todo/settings.py` to use environment variables for `DEBUG`, `SECRET_KEY`, and values in the `DATABASES` dict
+ 3. Installed `Django REST Framework` and added it to the list of `INSTALLED_APPS`
+ 4. Created `django_todo/views.py` to include our first view class to say Hello to the World
+ 5. Updated `django_todo/urls.py` with a path to our new home route
+ 6. Updated `INSTALLED_APPS` in `django_todo/settings.py` to include the `django_todo` package
+
+
+
+### Creating models
+
+Let's create our data models now.
+
+A Django project's entire infrastructure is built around data models. It's written so each data model can have its own little universe with its own views, its own set of URLs that concern its resources, and even its own tests (if we are so inclined).
+
+If we wanted to build a simple Django project, we could circumvent this by just writing our own `models.py` file in the `django_todo` directory and importing it into our views. However, we're trying to write a Django project the "right" way, so we should divide up our models as best we can into their own little packages The Django Way™.
+
+The Django Way involves creating what are called Django "apps." Django "apps" aren't separate applications per se; they don't have their own settings and whatnot (although they can). They can, however, have just about everything else one might think of being in a standalone application:
+
+ * Set of self-contained URLs
+ * Set of self-contained HTML templates (if we want to serve HTML)
+ * One or more data models
+ * Set of self-contained views
+ * Set of self-contained tests
+
+
+
+They are made to be independent so they can be easily shared like standalone applications. In fact, Django REST Framework is an example of a Django app. It comes packaged with its own views and HTML templates for serving up our JSON. We just leverage that Django app to turn our project into a full-on RESTful API with less hassle.
+
+To create the Django app for our To-Do List items, we'll want to use the `startapp` command with `manage.py`.
+```
+(django-someHash) $ ./manage.py startapp todo
+
+```
+
+The `startapp` command will succeed silently. We can check that it did what it should've done by using `ls`.
+```
+(django-someHash) $ ls
+
+Pipfile Pipfile.lock django_todo manage.py todo
+
+```
+
+Look at that: We've got a brand new `todo` directory. Let's look inside!
+```
+(django-someHash) $ ls todo
+
+__init__.py admin.py apps.py migrations models.py tests.py views.py
+
+```
+
+Here are the files that `manage.py startapp` created:
+
+ * `__init__.py` is empty; it exists so this directory can be seen as a valid import path for models, views, etc.
+ * `admin.py` is not quite empty; it's used for formatting this app's models in the Django admin, which we're not getting into in this article.
+ * `apps.py` … not much work to do here either; it helps with formatting models for the Django admin.
+ * `migrations` is a directory that'll contain snapshots of our data models; it's used for updating our database. This is one of the few frameworks that comes with database management built-in, and part of that is allowing us to update our database instead of having to tear it down and rebuild it to change the schema.
+ * `models.py` is where the data models live.
+ * `tests.py` is where tests would go—if we wrote any.
+ * `views.py` is for the views we write that pertain to the models in this app. They don't have to be written here. We could, for example, write all our views in `django_todo/views.py`. It's here, however, so it's easier to separate our concerns. This becomes far more relevant with sprawling applications that cover many conceptual spaces.
+
+
+
+What hasn't been created for us is a `urls.py` file for this app. We can make that ourselves.
+```
+(django-someHash) $ touch todo/urls.py
+
+```
+
+Before moving forward we should do ourselves a favor and add this new Django app to our list of `INSTALLED_APPS` in `django_todo/settings.py`.
+```
+# in settings.py
+
+INSTALLED_APPS = [
+
+ 'django.contrib.admin',
+
+ 'django.contrib.auth',
+
+ 'django.contrib.contenttypes',
+
+ 'django.contrib.sessions',
+
+ 'django.contrib.messages',
+
+ 'django.contrib.staticfiles',
+
+ 'rest_framework',
+
+ 'django_todo',
+
+ 'todo' # <--- the line was added
+
+]
+
+```
+
+Inspecting `todo/models.py` shows that `manage.py` already wrote a bit of code for us to get started. Diverging from how models were created in the Flask, Tornado, and Pyramid implementations, Django doesn't leverage a third party to manage database sessions or the construction of its object instances. It's all rolled into Django's `django.db.models` submodule.
+
+The way a model is built, however, is more or less the same. To create a model in Django, we'll need to build a `class` that inherits from `models.Model`. All the fields that will apply to instances of that model should appear as class attributes. Instead of importing columns and field types from SQLAlchemy like we have in the past, all of our fields will come directly from `django.db.models`.
+```
+# todo/models.py
+
+from django.db import models
+
+
+
+class Task(models.Model):
+
+ """Tasks for the To Do list."""
+
+ name = models.CharField(max_length=256)
+
+ note = models.TextField(blank=True, null=True)
+
+ creation_date = models.DateTimeField(auto_now_add=True)
+
+ due_date = models.DateTimeField(blank=True, null=True)
+
+ completed = models.BooleanField(default=False)
+
+```
+
+While there are some definite differences between what Django needs and what SQLAlchemy-based systems need, the overall contents and structure are more or less the same. Let's point out the differences.
+
+We no longer need to declare a separate field for an auto-incremented ID number for our object instances. Django builds one for us unless we specify a different field as the primary key.
+
+Instead of instantiating `Column` objects that are passed datatype objects, we just directly reference the datatypes as the columns themselves.
+
+The `Unicode` field became either `models.CharField` or `models.TextField`. `CharField` is for small text fields of a specific maximum length, whereas `TextField` is for any amount of text.
+
+The `TextField` should be able to be blank, and we specify this in TWO ways. `blank=True` says that when an instance of this model is constructed, and the data attached to this field is being validated, it's OK for that data to be empty. This is different from `null=True`, which says when the table for this model class is constructed, the column corresponding to `note` will allow for blank or `NULL` entries. So, to sum that all up, `blank=True` controls how data gets added to model instances while `null=True` controls how the database table holding that data is constructed in the first place.
+
+The `DateTime` field grew some muscle and became able to do some work for us instead of us having to modify the `__init__` method for the class. For the `creation_date` field, we specify `auto_now_add=True`. What this means in a practical sense is that when a new model instance is created Django will automatically record the date and time of now as that field's value. That's handy!
+
+When neither `auto_now_add` nor its close cousin `auto_now` are set to `True`, `DateTimeField` will expect data like any other field. It'll need to be fed with a proper `datetime` object to be valid. The `due_date` column has `blank` and `null` both set to `True` so that an item on the To-Do List can just be an item to be done at some point in the future, with no defined date or time.
+
+`BooleanField` just ends up being a field that can take one of two values: `True` or `False`. Here, the default value is set to be `False`.
+
+#### Managing the database
+
+As mentioned earlier, Django has its own way of doing database management. Instead of having to write… really any code at all regarding our database, we leverage the `manage.py` script that Django provided on construction. It'll manage not just the construction of the tables for our database, but also any updates we wish to make to those tables without necessarily having to blow the whole thing away!
+
+Because we've constructed a new model, we need to make our database aware of it. First, we need to put into code the schema that corresponds to this model. The `makemigrations` command of `manage.py` will take a snapshot of the model class we built and all its fields. It'll take that information and package it into a Python script that'll live in this particular Django app's `migrations` directory. There will never be a reason to run this migration script directly. It'll exist solely so that Django can use it as a basis to update our database table or to inherit information when we update our model class.
+```
+(django-someHash) $ ./manage.py makemigrations
+
+Migrations for 'todo':
+
+ todo/migrations/0001_initial.py
+
+ - Create model Task
+
+```
+
+This will look at every app listed in `INSTALLED_APPS` and check for models that exist in those apps. It'll then check the corresponding `migrations` directory for migration files and compare them to the models in each of those `INSTALLED_APPS` apps. If a model has been upgraded beyond what the latest migration says should exist, a new migration file will be created that inherits from the most recent one. It'll be automatically named and also be given a message that says what changed since the last migration.
+
+If it's been a while since you last worked on your Django project and can't remember if your models were in sync with your migrations, you have no need to fear. `makemigrations` is an idempotent operation; your `migrations` directory will have only one copy of the current model configuration whether you run `makemigrations` once or 20 times. Even better than that, when we run `./manage.py runserver`, Django will detect that our models are out of sync with our migrations, and it'll just flat out tell us in colored text so we can make the appropriate choice.
+
+This next point is something that trips everybody up at least once: Creating a migration file does not immediately affect our database. When we ran `makemigrations`, we prepared our Django project to define how a given table should be created and end up looking. It's still on us to apply those changes to our database. That's what the `migrate` command is for.
+```
+(django-someHash) $ ./manage.py migrate
+
+Operations to perform:
+
+ Apply all migrations: admin, auth, contenttypes, sessions, todo
+
+Running migrations:
+
+ Applying contenttypes.0001_initial... OK
+
+ Applying auth.0001_initial... OK
+
+ Applying admin.0001_initial... OK
+
+ Applying admin.0002_logentry_remove_auto_add... OK
+
+ Applying contenttypes.0002_remove_content_type_name... OK
+
+ Applying auth.0002_alter_permission_name_max_length... OK
+
+ Applying auth.0003_alter_user_email_max_length... OK
+
+ Applying auth.0004_alter_user_username_opts... OK
+
+ Applying auth.0005_alter_user_last_login_null... OK
+
+ Applying auth.0006_require_contenttypes_0002... OK
+
+ Applying auth.0007_alter_validators_add_error_messages... OK
+
+ Applying auth.0008_alter_user_username_max_length... OK
+
+ Applying auth.0009_alter_user_last_name_max_length... OK
+
+ Applying sessions.0001_initial... OK
+
+ Applying todo.0001_initial... OK
+
+```
+
+When we apply our migrations, Django first checks to see if the other `INSTALLED_APPS` have migrations to be applied. It checks them in roughly the order they're listed. We want our app to be listed last, because we want to make sure that, in case our model depends on any of Django's built-in models, the database updates we make don't suffer from dependency problems.
+
+We have another model to build: the User model. However, the game has changed a bit since we're using Django. So many applications require some sort of User model that Django's `django.contrib.auth` package built its own for us to use. If it weren't for the authentication token we require for our users, we could just move on and use it instead of reinventing the wheel.
+
+However, we need that token. There are a couple of ways we can handle this.
+
+ * Inherit from Django's `User` object, making our own object that extends it by adding a `token` field
+ * Create a new object that exists in a one-to-one relationship with Django's `User` object, whose only purpose is to hold a token
+
+
+
+I'm in the habit of building object relationships, so let's go with the second option. Let's call it an `Owner` as it basically has a similar connotation as a `User`, which is what we want.
+
+Out of sheer laziness, we could just include this new `Owner` object in `todo/models.py`, but let's refrain from that. `Owner` doesn't explicitly have to do with the creation or maintenance of items on the task list. Conceptually, the `Owner` is simply the owner of the task. There may even come a time where we want to expand this `Owner` to include other data that has absolutely nothing to do with tasks.
+
+Just to be safe, let's make an `owner` app whose job is to house and handle this `Owner` object.
+```
+(django-someHash) $ ./manage.py startapp owner
+
+```
+
+Don't forget to add it to the list of `INSTALLED_APPS` in `settings.py`.
+```
+INSTALLED_APPS = [
+
+ 'django.contrib.admin',
+
+ 'django.contrib.auth',
+
+ 'django.contrib.contenttypes',
+
+ 'django.contrib.sessions',
+
+ 'django.contrib.messages',
+
+ 'django.contrib.staticfiles',
+
+ 'rest_framework',
+
+ 'django_todo',
+
+ 'todo',
+
+ 'owner'
+
+]
+
+```
+
+If we look at the root of our Django project, we now have two Django apps:
+```
+(django-someHash) $ ls
+
+Pipfile Pipfile.lock django_todo manage.py owner todo
+
+```
+
+In `owner/models.py`, let's build this `Owner` model. As mentioned earlier, it'll have a one-to-one relationship with Django's built-in `User` object. We can enforce this relationship with Django's `models.OneToOneField`
+```
+# owner/models.py
+
+from django.db import models
+
+from django.contrib.auth.models import User
+
+import secrets
+
+
+
+class Owner(models.Model):
+
+ """The object that owns tasks."""
+
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
+
+ token = models.CharField(max_length=256)
+
+
+
+ def __init__(self, *args, **kwargs):
+
+ """On construction, set token."""
+
+ self.token = secrets.token_urlsafe(64)
+
+ super().__init__(*args, **kwargs)
+
+```
+
+This says the `Owner` object is linked to the `User` object, with one `owner` instance per `user` instance. `on_delete=models.CASCADE` dictates that if the corresponding `User` gets deleted, the `Owner` instance it's linked to will also get deleted. Let's run `makemigrations` and `migrate` to bake this new model into our database.
+```
+(django-someHash) $ ./manage.py makemigrations
+
+Migrations for 'owner':
+
+ owner/migrations/0001_initial.py
+
+ - Create model Owner
+
+(django-someHash) $ ./manage.py migrate
+
+Operations to perform:
+
+ Apply all migrations: admin, auth, contenttypes, owner, sessions, todo
+
+Running migrations:
+
+ Applying owner.0001_initial... OK
+
+```
+
+Now our `Owner` needs to own some `Task` objects. It'll be very similar to the `OneToOneField` seen above, except that we'll stick a `ForeignKey` field on the `Task` object pointing to an `Owner`.
+```
+# todo/models.py
+
+from django.db import models
+
+from owner.models import Owner
+
+
+
+class Task(models.Model):
+
+ """Tasks for the To Do list."""
+
+ name = models.CharField(max_length=256)
+
+ note = models.TextField(blank=True, null=True)
+
+ creation_date = models.DateTimeField(auto_now_add=True)
+
+ due_date = models.DateTimeField(blank=True, null=True)
+
+ completed = models.BooleanField(default=False)
+
+ owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
+
+```
+
+Every To-Do List task has exactly one owner who can own multiple tasks. When that owner is deleted, any task they own goes with them.
+
+Let's now run `makemigrations` to take a new snapshot of our data model setup, then `migrate` to apply those changes to our database.
+```
+(django-someHash) django $ ./manage.py makemigrations
+
+You are trying to add a non-nullable field 'owner' to task without a default; we can't do that (the database needs something to populate existing rows).
+
+Please select a fix:
+
+ 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
+
+ 2) Quit, and let me add a default in models.py
+
+```
+
+Oh no! We have a problem! What happened? Well, when we created the `Owner` object and added it as a `ForeignKey` to `Task`, we basically required that every `Task` requires an `Owner`. However, the first migration we made for the `Task` object didn't include that requirement. So, even though there's no data in our database's table, Django is doing a pre-check on our migrations to make sure they're compatible and this new migration we're proposing is not.
+
+There are a few ways to deal with this sort of problem:
+
+ 1. Blow away the current migration and build a new one that includes the current model configuration
+ 2. Add a default value to the `owner` field on the `Task` object
+ 3. Allow tasks to have `NULL` values for the `owner` field.
+
+
+
+Option 2 wouldn't make much sense here; we'd be proposing that any `Task` that was created would, by default, be linked to some default owner despite none necessarily existing.
+
+Option 1 would require us to destroy and rebuild our migrations. We should leave those alone.
+
+Let's go with option 3. In this circumstance, it won't be the end of the world if we allow the `Task` table to have null values for the owners; any tasks created from this point forward will necessarily have an owner. If you're in a situation where that isn't an acceptable schema for your database table, blow away your migrations, drop the table, and rebuild the migrations.
+```
+# todo/models.py
+
+from django.db import models
+
+from owner.models import Owner
+
+
+
+class Task(models.Model):
+
+ """Tasks for the To Do list."""
+
+ name = models.CharField(max_length=256)
+
+ note = models.TextField(blank=True, null=True)
+
+ creation_date = models.DateTimeField(auto_now_add=True)
+
+ due_date = models.DateTimeField(blank=True, null=True)
+
+ completed = models.BooleanField(default=False)
+
+ owner = models.ForeignKey(Owner, on_delete=models.CASCADE, null=True)
+
+(django-someHash) $ ./manage.py makemigrations
+
+Migrations for 'todo':
+
+ todo/migrations/0002_task_owner.py
+
+ - Add field owner to task
+
+(django-someHash) $ ./manage.py migrate
+
+Operations to perform:
+
+ Apply all migrations: admin, auth, contenttypes, owner, sessions, todo
+
+Running migrations:
+
+ Applying todo.0002_task_owner... OK
+
+```
+
+Woo! We have our models! Welcome to the Django way of declaring objects.
+
+For good measure, let's ensure that whenever a `User` is made, it's automatically linked with a new `Owner` object. We can do this using Django's `signals` system. Basically, we say exactly what we intend: "When we get the signal that a new `User` has been constructed, construct a new `Owner` and set that new `User` as that `Owner`'s `user` field." In practice that looks like:
+```
+# owner/models.py
+
+from django.contrib.auth.models import User
+
+from django.db import models
+
+from django.db.models.signals import post_save
+
+from django.dispatch import receiver
+
+
+
+import secrets
+
+
+
+
+
+class Owner(models.Model):
+
+ """The object that owns tasks."""
+
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
+
+ token = models.CharField(max_length=256)
+
+
+
+ def __init__(self, *args, **kwargs):
+
+ """On construction, set token."""
+
+ self.token = secrets.token_urlsafe(64)
+
+ super().__init__(*args, **kwargs)
+
+
+
+
+
+@receiver(post_save, sender=User)
+
+def link_user_to_owner(sender, **kwargs):
+
+ """If a new User is saved, create a corresponding Owner."""
+
+ if kwargs['created']:
+
+ owner = Owner(user=kwargs['instance'])
+
+ owner.save()
+
+```
+
+We set up a function that listens for signals to be sent from the `User` object built into Django. It's waiting for just after a `User` object has been saved. This can come from either a new `User` or an update to an existing `User`; we discern between the two scenarios within the listening function.
+
+If the thing sending the signal was a newly created instance, `kwargs['created']` will have the value of `True`. We only want to do something if this is `True`. If it's a new instance, we create a new `Owner`, setting its `user` field to be the new `User` instance that was created. After that, we `save()` the new `Owner`. This will commit our change to the database if all is well. It'll fail if the data doesn't validate against the fields we declared.
+
+Now let's talk about how we're going to access the data.
+
+### Accessing model data
+
+In the Flask, Pyramid, and Tornado frameworks, we accessed model data by running queries against some database session. Maybe it was attached to a `request` object, maybe it was a standalone `session` object. Regardless, we had to establish a live connection to the database and query on that connection.
+
+This isn't the way Django works. Django, by default, doesn't leverage any third-party object-relational mapping (ORM) to converse with the database. Instead, Django allows the model classes to maintain their own conversations with the database.
+
+Every model class that inherits from `django.db.models.Model` will have attached to it an `objects` object. This will take the place of the `session` or `dbsession` we've become so familiar with. Let's open the special shell that Django gives us and investigate how this `objects` object works.
+```
+(django-someHash) $ ./manage.py shell
+
+Python 3.7.0 (default, Jun 29 2018, 20:13:13)
+
+[Clang 9.1.0 (clang-902.0.39.2)] on darwin
+
+Type "help", "copyright", "credits" or "license" for more information.
+
+(InteractiveConsole)
+
+>>>
+
+```
+
+The Django shell is different from a normal Python shell in that it's aware of the Django project we've been building and can do easy imports of our models, views, settings, etc. without having to worry about installing a package. We can access our models with a simple `import`.
+```
+>>> from owner.models import Owner
+
+>>> Owner
+
+