" > test1.html
-```
-
-Now view index.html and see the difference.
-
-Of course you can put a lot of additional HTML around the actual content line to make a more complete and standard web page. That more complete version as shown below will still display the same results in the browser, but it also forms the basis for more standardized web site. Go ahead and use this content for your index.html file and display it in your browser.
-```
-
-
-
-My Web Page
-
-
-
Hello World
-
-
-```
-
-I built a couple static websites using these techniques, but my life was about to change.
-
-## Dynamic web pages for a new job
-
-I took a new job in which my primary task was to create and maintain the CGI ([Common Gateway Interface][6]) code for a very dynamic website. In this context, dynamic means that the HTML needed to produce the web page on a browser was generated from data that could be different every time the page was accessed. This includes input from the user on a web form that is used to look up data in a database. The resulting data is surrounded by appropriate HTML and displayed on the requesting browser. But it does not need to be that complex.
-
-Using CGI scripts for a website allows you to create simple or complex interactive programs that can be run to provide a dynamic web page that can change based on input, calculations, current conditions in the server, and so on. There are many languages that can be used for CGI scripts. We will look at two of them, Perl and Bash. Other popular CGI languages include PHP and Python.
-
-This article does not cover installation and setup of Apache or any other web server. If you have access to a web server that you can experiment with, you can directly view the results as they would appear in a browser. Otherwise, you can still run the programs from the command line and view the HTML that would be created. You can also redirect that HTML output to a file and then display the resulting file in your browser.
-
-### Using Perl
-
-Perl is a very popular language for CGI scripts. Its strength is that it is a very powerful language for the manipulation of text.
-
-To get CGI scripts to execute, you need the following line in the in httpd.conf for the website you are using. This tells the web server where your executable CGI files are located. For this experiment, let's not worry about that.
-```
-ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
-```
-
-Add the following Perl code to the file index.cgi, which should be located in your home directory for your experimentation. Set the ownership of the file to apache.apache when you use a web server, and set the permissions to 755 because it must be executable no matter where it is located.
-
-```
-#!/usr/bin/perl
-print "Content-type: text/html\n\n";
-print "\n";
-print "
Hello World
\n";
-print "Using Perl
\n";
-print "\n";
-```
-
-Run this program from the command line and view the results. It should display the HTML code it will generate.
-
-Now view the index.cgi in your browser. Well, all you get is the contents of the file. Browsers really need to have this delivered as CGI content. Apache does not really know that it needs to run the file as a CGI program unless the Apache configuration for the web site includes the "ScriptAlias" definition as shown above. Without that bit of configuration Apache simply send the data in the file to the browser. If you have access to a web server, you could try this out with your executable index files in the /var/www/cgi-bin directory.
-
-To see what this would look like in your browser, run the program again and redirect the output to a new file. Name it whatever you want. Then use your browser to view the file that contains the generated content.
-
-The above CGI program is still generating static content because it always displays the same output. Add the following line to your CGI program immediately after the "Hello World" line. The Perl "system" command executes the commands following it in a system shell, and returns the result to the program. In this case, we simply grep the current RAM usage out of the results from the free command.
-
-```
-system "free | grep Mem\n";
-```
-
-Now run the program again and redirect the output to the results file. Reload the file in the browser. You should see an additional line so that displays the system memory statistics. Run the program and refresh the browser a couple more times and notice that the memory usage should change occasionally.
-
-### Using Bash
-
-Bash is probably the simplest language of all for use in CGI scripts. Its primary strength for CGI programming is that it has direct access to all of the standard GNU utilities and system programs.
-
-Rename the existing index.cgi to Perl.index.cgi and create a new index.cgi with the following content. Remember to set the permissions correctly to executable.
-
-```
-#!/bin/bash
-echo "Content-type: text/html"
-echo ""
-echo ''
-echo '
'
-free | grep Mem
-echo ''
-echo ''
-exit 0
-```
-
-Execute this program from the command line and view the output, then run it and redirect the output to the temporary results file you created before. Then refresh the browser to view what it looks like displayed as a web page.
-
-## Conclusion
-
-It is actually very simple to create CGI programs that can be used to generate a wide range of dynamic web pages. This is a trivial example but you should now see some of the possibilities.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/17/12/cgi-scripts
-
-作者:[David Both][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/dboth
-[1]:http://december.com/html/4/element/html.html
-[2]:http://december.com/html/4/element/head.html
-[3]:http://december.com/html/4/element/title.html
-[4]:http://december.com/html/4/element/body.html
-[5]:http://december.com/html/4/element/h1.html
-[6]:https://en.wikipedia.org/wiki/Common_Gateway_Interface
-[7]:http://perldoc.perl.org/functions/system.html
diff --git a/sources/tech/20171231 Why You Should Still Love Telnet.md b/sources/tech/20171231 Why You Should Still Love Telnet.md
deleted file mode 100644
index 201ee91bd4..0000000000
--- a/sources/tech/20171231 Why You Should Still Love Telnet.md
+++ /dev/null
@@ -1,161 +0,0 @@
-XYenChi is translating
-Why You Should Still Love Telnet
-======
-Telnet, the protocol and the command line tool, were how system administrators used to log into remote servers. However, due to the fact that there is no encryption all communication, including passwords, are sent in plaintext meant that Telnet was abandoned in favour of SSH almost as soon as SSH was created.
-
-For the purposes of logging into a remote server, you should never, and probably have never considered it. This does not mean that the `telnet` command is not a very useful tool when used for debugging remote connection problems.
-
-In this guide, we will explore using `telnet` to answer the all too common question, "Why can't I ###### connect‽".
-
-This frustrated question is usually encountered after installing a application server like a web server, an email server, an ssh server, a Samba server etc, and for some reason, the client won't connect to the server.
-
-`telnet` isn't going to solve your problem but it will, very quickly, narrow down where you need to start looking to fix your problem.
-
-`telnet` is a very simple command to use for debugging network related issues and has the syntax:
-```
-telnet
-
-```
-
-Because `telnet` will initially simply establish a connection to the port without sending any data it can be used with almost any protocol including encrypted protocols.
-
-There are four main errors that you will encounter when trying to connect to a problem server. We will look at all four, explore what they mean and look at how you should fix them.
-
-For this guide we will assume that we have just installed a [Samba][1] server at `samba.example.com` and we can't get a local client to connect to the server.
-
-### Error 1 - The connection that hangs forever
-
-First, we need to attempt to connect to the Samba server with `telnet`. This is done with the following command (Samba listens on port 445):
-```
-telnet samba.example.com 445
-
-```
-
-Sometimes, the connection will get to this point stop indefinitely:
-```
-telnet samba.example.com 445
-Trying 172.31.25.31...
-
-```
-
-This means that `telnet` has not received any response to its request to establish a connection. This can happen for two reasons:
-
- 1. There is a router down between you and the server.
- 2. There is a firewall dropping your request.
-
-
-
-In order to rule out **1.** run a quick [`mtr samba.example.com`][2] to the server. If the server is accessible then it's a firewall (note: it's almost always a firewall).
-
-Firstly, check if there are any firewall rules on the server itself with the following command `iptables -L -v -n`, if there are none then you will get the following output:
-```
-iptables -L -v -n
-Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
- pkts bytes target prot opt in out source destination
-
-Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
- pkts bytes target prot opt in out source destination
-
-Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
- pkts bytes target prot opt in out source destination
-
-```
-
-If you see anything else then this is likely the problem. In order to check, stop `iptables` for a moment and run `telnet samba.example.com 445` again and see if you can connect. If you still can't connect see if your provider and/or office has a firewall in place that is blocking you.
-
-### Error 2 - DNS problems
-
-A DNS issue will occur if the hostname you are using does not resolve to an IP address. The error that you will see is as follows:
-```
-telnet samba.example.com 445
-Server lookup failure: samba.example.com:445, Name or service not known
-
-```
-
-The first step here is to substitute the IP address of the server for the hostname. If you can connect to the IP but not the hostname then the problem is the hostname.
-
-This can happen for many reasons (I have seen all of the following):
-
- 1. Is the domain registered? Use `whois` to find out if it is.
- 2. Is the domain expired? Use `whois` to find out if it is.
- 3. Are you using the correct hostname? Use `dig` or `host` to ensure that the hostname you are using resolves to the correct IP.
- 4. Is your **A** record correct? Check that you didn 't accidentally create an **A** record for something like `smaba.example.com`.
-
-
-
-Always double check the spelling and the correct hostname (is it `samba.example.com` or `samba1.example.com`) as this will often trip you up especially with long, complicated or foreign hostnames.
-
-### Error 3 - The server isn't listening on that port
-
-This error occurs when `telnet` is able to reach to the server but there is nothing listening on the port you specified. The error looks like this:
-```
-telnet samba.example.com 445
-Trying 172.31.25.31...
-telnet: Unable to connect to remote host: Connection refused
-
-```
-
-This can happen for a couple of reasons:
-
- 1. Are you **sure** you 're connecting to the right server?
- 2. Your application server is not listening on the port you think it is. Check exactly what it's doing by running `netstat -plunt` on the server and see what port it is, in fact, listening on.
- 3. The application server isn't running. This can happen when the application server exits immediately and silently after you start it. Start the server and run `ps auxf` or `systemctl status application.service` to check it's running.
-
-
-
-### Error 4 - The connection was closed by the server
-
-This error happens when the connection was successful but the application server has a build in security measure that killed the connection as soon as it was made. This error looks like:
-```
-telnet samba.example.com 445
-Trying 172.31.25.31...
-Connected to samba.example.com.
-Escape character is '^]'.
-��Connection closed by foreign host.
-
-```
-
-The last line `Connection closed by foreign host.` indicates that the connection was actively terminated by the server. In order to fix this, you need to look at the security configuration of the application server to ensure your IP or user is allowed to connect to it.
-
-### A successful connection
-
-This is what a successful `telnet` connection attempt looks like:
-```
-telnet samba.example.com 445
-Trying 172.31.25.31...
-Connected to samba.example.com.
-Escape character is '^]'.
-
-```
-
-The connection will stay open for a while depending on the timeout of the application server you are connected to.
-
-A telnet connection is closed by typing `CTRL+]` and then when you see the `telnet>` prompt, type "quit" and hit ENTER i.e.:
-```
-telnet samba.example.com 445
-Trying 172.31.25.31...
-Connected to samba.example.com.
-Escape character is '^]'.
-^]
-telnet> quit
-Connection closed.
-
-```
-
-### Conclusion
-
-There are a lot of reasons that a client application can't connect to a server. The exact reason can be difficult to establish especially when the client is a GUI that offers little or no error information. Using `telnet` and observing the output will allow you to very rapidly narrow down where the problem lies and save you a whole lot of time.
-
---------------------------------------------------------------------------------
-
-via: https://bash-prompt.net/guides/telnet/
-
-作者:[Elliot Cooper][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://bash-prompt.net
-[1]:https://www.samba.org/
-[2]:https://www.systutorials.com/docs/linux/man/8-mtr/
diff --git a/sources/tech/20180103 How To Find The Installed Proprietary Packages In Arch Linux.md b/sources/tech/20180103 How To Find The Installed Proprietary Packages In Arch Linux.md
index 69b523426c..8dc2e92513 100644
--- a/sources/tech/20180103 How To Find The Installed Proprietary Packages In Arch Linux.md
+++ b/sources/tech/20180103 How To Find The Installed Proprietary Packages In Arch Linux.md
@@ -1,3 +1,4 @@
+Translating by stevenzdg988
How To Find The Installed Proprietary Packages In Arch Linux
======

diff --git a/sources/tech/20180103 How to preconfigure LXD containers with cloud-init.md b/sources/tech/20180103 How to preconfigure LXD containers with cloud-init.md
deleted file mode 100644
index ed6eacd2fb..0000000000
--- a/sources/tech/20180103 How to preconfigure LXD containers with cloud-init.md
+++ /dev/null
@@ -1,197 +0,0 @@
-How to preconfigure LXD containers with cloud-init
-======
-You are creating containers and you want them to be somewhat preconfigured. For example, you want them to run automatically **apt update** as soon as they are launched. Or, get some packages pre-installed, or run a few commands. Here is how to perform this early initialization with [**cloud-init**][1] through [LXD to container images that support **cloud-init**][2].
-
-In the following, we are creating a separate LXD profile with some cloud-init instructions, then launch a container using that profile.
-
-### How to create a new LXD profile
-
-Let's see the existing profiles.
-```
-$ **lxc profile list**
-+---------|---------+
-| NAME | USED BY |
-+---------|---------+
-| default | 11 |
-+---------|---------+
-```
-
-There is one profile, **default**. We copy it to a new name, so that we can start adding our instructions on that profile.
-```
-$ **lxc profile copy default devprofile**
-
-$ **lxc profile list**
-+------------|---------+
-| NAME | USED BY |
-+------------|---------+
-| default | 11 |
-+------------|---------+
-| devprofile | 0 |
-+------------|---------+
-```
-
-We have a new profile to work on, **devprofile**. Here is how it looks,
-```
-$ **lxc profile show devprofile**
-config:
- environment.TZ: ""
-description: Default LXD profile
-devices:
- eth0:
- nictype: bridged
- parent: lxdbr0
- type: nic
- root:
- path: /
- pool: default
- type: disk
-name: devprofile
-used_by: []
-```
-
-Note the main sections, **config:** , **description:** , **devices:** , **name:** , and **used_by:**. There is careful indentation in the profile, and when you make edits, you need to take care of the indentation.
-
-### How to add cloud-init to an LXD profile
-
-In the **config:** section of a LXD profile, we can insert [cloud-init][1] instructions. Those[ cloud-init][1] instructions will be passed to the container and will be used when it is first launched.
-
-Here are those that we are going to use in the example,
-```
- package_upgrade: true
- packages:
- - build-essential
- locale: es_ES.UTF-8
- timezone: Europe/Madrid
- runcmd:
- - [touch, /tmp/simos_was_here]
-```
-
-**package_upgrade: true** means that we want **cloud-init** to run **sudo apt upgrade** when the container is first launched. Under **packages:** we list the packages that we want to get automatically installed. Then we set the **locale** and **timezone**. In the Ubuntu container images, the default locale for **root** is **C.UTF-8** , for the **ubuntu** account it 's **en_US.UTF-8**. The timezone is **Etc/UTC**. Finally, we show [how to run a Unix command with **runcmd**][3].
-
-The part that needs a bit of attention is how to insert the **cloud-init** instructions into the LXD profile. My preferred way is
-```
-$ **lxc profile edit devprofile**
-```
-
-This opens up a text editor and allows to paste the instructions. Here is [how the result should look like][4],
-```
-$ **lxc profile show devprofile**
-config:
- environment.TZ: ""
-
-
- user.user-data: |
- #cloud-config
- package_upgrade: true
- packages:
- - build-essential
- locale: es_ES.UTF-8
- timezone: Europe/Madrid
- runcmd:
- - [touch, /tmp/simos_was_here]
-
-
-description: Default LXD profile
-devices:
- eth0:
- nictype: bridged
- parent: lxdbr0
- type: nic
- root:
- path: /
- pool: default
- type: disk
-name: devprofile
-used_by: []
-```
-
-WordPress can get a bit messed with indentation when you copy/paste, therefore, you may use [this pastebin][4] instead.
-
-### How to launch a container using a profile
-
-Let's launch a new container using the profile **devprofile**.
-```
-$ **lxc launch --profile devprofile ubuntu:x mydev**
-```
-
-Let's get into the container and figure out whether our instructions took effect.
-```
-$ **lxc exec mydev bash**
-root@mydev:~# **ps ax**
- PID TTY STAT TIME COMMAND
- 1 ? Ss 0:00 /sbin/init
- ...
- 427 ? Ss 0:00 /usr/bin/python3 /usr/bin/cloud-init modules --mode=f
- 430 ? S 0:00 /bin/sh -c tee -a /var/log/cloud-init-output.log
- 431 ? S 0:00 tee -a /var/log/cloud-init-output.log
- 432 ? S 0:00 /usr/bin/apt-get --option=Dpkg::Options::=--force-con
- 437 ? S 0:00 /usr/lib/apt/methods/http
- 438 ? S 0:00 /usr/lib/apt/methods/http
- 440 ? S 0:00 /usr/lib/apt/methods/gpgv
- 570 ? Ss 0:00 bash
- 624 ? S 0:00 /usr/lib/apt/methods/store
- 625 ? R+ 0:00 ps ax
-root@mydev:~#
-```
-
-We connected quite quickly, and **ps ax** shows that the package update is indeed taking place! We can get the full output at /var/log/cloud-init-output.log and in there,
-```
-Generating locales (this might take a while)...
- es_ES.UTF-8... done
-Generation complete.
-```
-
-The locale got set. The **root** user keeps having the **C.UTF-8** default locale. It is only the non-root account **ubuntu** that gets the new locale.
-```
-Hit:1 http://archive.ubuntu.com/ubuntu xenial InRelease
-Get:2 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]
-Get:3 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
-```
-
-Here is **apt update** that is required before installing packages.
-```
-The following packages will be upgraded:
- libdrm2 libseccomp2 squashfs-tools unattended-upgrades
-4 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
-Need to get 211 kB of archives.
-```
-
-Here is runs **package_upgrade: true** and installs any available packages.
-```
-The following NEW packages will be installed:
- binutils build-essential cpp cpp-5 dpkg-dev fakeroot g++ g++-5 gcc gcc-5
- libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl
-```
-
-This is from our instruction to install the **build-essential** meta-package.
-
-What about the **runcmd** instruction?
-```
-root@mydev:~# **ls -l /tmp/**
-total 1
--rw-r--r-- 1 root root 0 Jan 3 15:23 simos_was_here
-root@mydev:~#
-```
-
-It worked as well!
-
-### Conclusion
-
-When we launch LXD containers, we often need some configuration to be enabled by default and avoid repeated actions. The way to solve this, is to create LXD profiles. Each profile captures those configurations. Finally, when we launch the new container, we specify which LXD profile to use.
-
-
---------------------------------------------------------------------------------
-
-via: https://blog.simos.info/how-to-preconfigure-lxd-containers-with-cloud-init/
-
-作者:[Simos Xenitellis][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://blog.simos.info/author/simos/
-[1]:http://cloudinit.readthedocs.io/en/latest/index.html
-[2]:https://github.com/lxc/lxd/blob/master/doc/cloud-init.md
-[3]:http://cloudinit.readthedocs.io/en/latest/topics/modules.html#runcmd
-[4]:https://paste.ubuntu.com/26313399/
diff --git a/sources/tech/20180104 4 Tools for Network Snooping on Linux.md b/sources/tech/20180104 4 Tools for Network Snooping on Linux.md
new file mode 100644
index 0000000000..0ba60006ee
--- /dev/null
+++ b/sources/tech/20180104 4 Tools for Network Snooping on Linux.md
@@ -0,0 +1,197 @@
+4 Tools for Network Snooping on Linux
+======
+Computer networking data has to be exposed, because packets can't travel blindfolded, so join us as we use `whois`, `dig`, `nmcli`, and `nmap` to snoop networks.
+
+Do be polite and don't run `nmap` on any network but your own, because probing other people's networks can be interpreted as a hostile act.
+
+### Thin and Thick whois
+
+You may have noticed that our beloved old `whois` command doesn't seem to give the level of detail that it used to. Check out this example for Linux.com:
+```
+$ whois linux.com
+Domain Name: LINUX.COM
+Registry Domain ID: 4245540_DOMAIN_COM-VRSN
+Registrar WHOIS Server: whois.namecheap.com
+Registrar URL: http://www.namecheap.com
+Updated Date: 2018-01-10T12:26:50Z
+Creation Date: 1994-06-02T04:00:00Z
+Registry Expiry Date: 2018-06-01T04:00:00Z
+Registrar: NameCheap Inc.
+Registrar IANA ID: 1068
+Registrar Abuse Contact Email: abuse@namecheap.com
+Registrar Abuse Contact Phone: +1.6613102107
+Domain Status: ok https://icann.org/epp#ok
+Name Server: NS5.DNSMADEEASY.COM
+Name Server: NS6.DNSMADEEASY.COM
+Name Server: NS7.DNSMADEEASY.COM
+DNSSEC: unsigned
+[...]
+
+```
+
+There is quite a bit more, mainly annoying legalese. But where is the contact information? It is sitting on whois.namecheap.com (see the third line of output above):
+```
+$ whois -h whois.namecheap.com linux.com
+
+```
+
+I won't print the output here, as it is very long, containing the Registrant, Admin, and Tech contact information. So what's the deal, Lucille? Some registries, such as .com and .net are "thin" registries, storing a limited subset of domain data. To get complete information use the `-h`, or `--host` option, to get the complete dump from the domain's `Registrar WHOIS Server`.
+
+Most of the other top-level domains are thick registries, such as .info. Try `whois blockchain.info` to see an example.
+
+Want to get rid of the obnoxious legalese? Use the `-H` option.
+
+### Digging DNS
+
+Use the `dig` command to compare the results from different name servers to check for stale entries. DNS records are cached all over the place, and different servers have different refresh intervals. This is the simplest usage:
+```
+$ dig linux.com
+<<>> DiG 9.10.3-P4-Ubuntu <<>> linux.com
+;; global options: +cmd
+;; Got answer:
+;; ->>HEADER<<<- opcode: QUERY, status: NOERROR, id: 13694
+;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1
+
+;; OPT PSEUDOSECTION:
+; EDNS: version: 0, flags:; udp: 1440
+;; QUESTION SECTION:
+;linux.com. IN A
+
+;; ANSWER SECTION:
+linux.com. 10800 IN A 151.101.129.5
+linux.com. 10800 IN A 151.101.65.5
+linux.com. 10800 IN A 151.101.1.5
+linux.com. 10800 IN A 151.101.193.5
+
+;; Query time: 92 msec
+;; SERVER: 127.0.1.1#53(127.0.1.1)
+;; WHEN: Tue Jan 16 15:17:04 PST 2018
+;; MSG SIZE rcvd: 102
+
+```
+
+Take notice of the SERVER: 127.0.1.1#53(127.0.1.1) line near the end of the output. This is your default caching resolver. When the address is localhost, that means there is a DNS server installed on your machine. In my case that is Dnsmasq, which is being used by Network Manager:
+```
+$ ps ax|grep dnsmasq
+2842 ? S 0:00 /usr/sbin/dnsmasq --no-resolv --keep-in-foreground
+--no-hosts --bind-interfaces --pid-file=/var/run/NetworkManager/dnsmasq.pid
+--listen-address=127.0.1.1
+
+```
+
+The `dig` default is to return A records, which define the domain name. IPv6 has AAAA records:
+```
+$ $ dig linux.com AAAA
+[...]
+;; ANSWER SECTION:
+linux.com. 60 IN AAAA 64:ff9b::9765:105
+linux.com. 60 IN AAAA 64:ff9b::9765:4105
+linux.com. 60 IN AAAA 64:ff9b::9765:8105
+linux.com. 60 IN AAAA 64:ff9b::9765:c105
+[...]
+
+```
+
+Checkitout, Linux.com has IPv6 addresses. Very good! If your Internet service provider supports IPv6 then you can connect over IPv6. (Sadly, my overpriced mobile broadband does not.)
+
+Suppose you make some DNS changes to your domain, or you're seeing `dig` results that don't look right. Try querying with a public DNS service, like OpenNIC:
+```
+$ dig @69.195.152.204 linux.com
+[...]
+;; Query time: 231 msec
+;; SERVER: 69.195.152.204#53(69.195.152.204)
+
+```
+
+`dig` confirms that you're getting your lookup from 69.195.152.204. You can query all kinds of servers and compare results.
+
+### Upstream Name Servers
+
+I want to know what my upstream name servers are. To find this, I first look in `/etc/resolv/conf`:
+```
+$ cat /etc/resolv.conf
+# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
+# DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
+nameserver 127.0.1.1
+
+```
+
+Thanks, but I already knew that. Your Linux distribution may be configured differently, and you'll see your upstream servers. Let's try `nmcli`, the Network Manager command-line tool:
+```
+$ nmcli dev show | grep DNS
+IP4.DNS[1]: 192.168.1.1
+
+```
+
+Now we're getting somewhere, as that is the address of my mobile hotspot, and I should have thought of that myself. I can log in to its weird little Web admin panel to see its upstream servers. A lot of consumer Internet gateways don't let you view or change these settings, so try an external service such as [What's my DNS server?][1]
+
+### List IPv4 Addresses on your Network
+
+Which IPv4 addresses are up and in use on your network?
+```
+$ nmap -sn 192.168.1.0/24
+Starting Nmap 7.01 ( https://nmap.org ) at 2018-01-14 14:03 PST
+Nmap scan report for Mobile.Hotspot (192.168.1.1)
+Host is up (0.011s latency).
+Nmap scan report for studio (192.168.1.2)
+Host is up (0.000071s latency).
+Nmap scan report for nellybly (192.168.1.3)
+Host is up (0.015s latency)
+Nmap done: 256 IP addresses (2 hosts up) scanned in 2.23 seconds
+
+```
+
+Everyone wants to scan their network for open ports. This example looks for services and their versions:
+```
+$ nmap -sV 192.168.1.1/24
+
+Starting Nmap 7.01 ( https://nmap.org ) at 2018-01-14 16:46 PST
+Nmap scan report for Mobile.Hotspot (192.168.1.1)
+Host is up (0.0071s latency).
+Not shown: 997 closed ports
+PORT STATE SERVICE VERSION
+22/tcp filtered ssh
+53/tcp open domain dnsmasq 2.55
+80/tcp open http GoAhead WebServer 2.5.0
+
+Nmap scan report for studio (192.168.1.102)
+Host is up (0.000087s latency).
+Not shown: 998 closed ports
+PORT STATE SERVICE VERSION
+22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
+631/tcp open ipp CUPS 2.1
+Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
+
+Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
+Nmap done: 256 IP addresses (2 hosts up) scanned in 11.65 seconds
+
+```
+
+These are interesting results. Let's try the same run from a different Internet account, to see if any of these services are exposed to big bad Internet. You have a second network if you have a smartphone. There are probably apps you can download, or use your phone as a hotspot to your faithful Linux computer. Fetch the WAN IP address from the hotspot control panel and try again:
+```
+$ nmap -sV 12.34.56.78
+
+Starting Nmap 7.01 ( https://nmap.org ) at 2018-01-14 17:05 PST
+Nmap scan report for 12.34.56.78
+Host is up (0.0061s latency).
+All 1000 scanned ports on 12.34.56.78 are closed
+
+```
+
+That's what I like to see. Consult the fine man pages for these commands to learn more fun snooping techniques.
+
+Learn more about Linux through the free ["Introduction to Linux" ][2]course from The Linux Foundation and edX.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/learn/intro-to-linux/2018/1/4-tools-network-snooping-linux
+
+作者:[Carla Schroder][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/cschroder
+[1]:http://www.whatsmydnsserver.com/
+[2]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180104 How does gdb call functions.md b/sources/tech/20180104 How does gdb call functions.md
index a62b30ea31..c88fae999e 100644
--- a/sources/tech/20180104 How does gdb call functions.md
+++ b/sources/tech/20180104 How does gdb call functions.md
@@ -1,3 +1,5 @@
+translating by ucasFL
+
How does gdb call functions?
============================================================
diff --git a/sources/tech/20180106 Meltdown and Spectre Linux Kernel Status.md b/sources/tech/20180106 Meltdown and Spectre Linux Kernel Status.md
deleted file mode 100644
index d98fddad78..0000000000
--- a/sources/tech/20180106 Meltdown and Spectre Linux Kernel Status.md
+++ /dev/null
@@ -1,103 +0,0 @@
-translated by hopefully2333
-
-Meltdown and Spectre Linux Kernel Status
-============================================================
-
-
-By now, everyone knows that something “big” just got announced regarding computer security. Heck, when the [Daily Mail does a report on it][1] , you know something is bad…
-
-Anyway, I’m not going to go into the details about the problems being reported, other than to point you at the wonderfully written [Project Zero paper on the issues involved here][2]. They should just give out the 2018 [Pwnie][3] award right now, it’s that amazingly good.
-
-If you do want technical details for how we are resolving those issues in the kernel, see the always awesome [lwn.net writeup for the details][4].
-
-Also, here’s a good summary of [lots of other postings][5] that includes announcements from various vendors.
-
-As for how this was all handled by the companies involved, well this could be described as a textbook example of how _NOT_ to interact with the Linux kernel community properly. The people and companies involved know what happened, and I’m sure it will all come out eventually, but right now we need to focus on fixing the issues involved, and not pointing blame, no matter how much we want to.
-
-### What you can do right now
-
-If your Linux systems are running a normal Linux distribution, go update your kernel. They should all have the updates in them already. And then keep updating them over the next few weeks, we are still working out lots of corner case bugs given that the testing involved here is complex given the huge variety of systems and workloads this affects. If your distro does not have kernel updates, then I strongly suggest changing distros right now.
-
-However there are lots of systems out there that are not running “normal” Linux distributions for various reasons (rumor has it that it is way more than the “traditional” corporate distros). They rely on the LTS kernel updates, or the normal stable kernel updates, or they are in-house franken-kernels. For those people here’s the status of what is going on regarding all of this mess in the upstream kernels you can use.
-
-### Meltdown – x86
-
-Right now, Linus’s kernel tree contains all of the fixes we currently know about to handle the Meltdown vulnerability for the x86 architecture. Go enable the CONFIG_PAGE_TABLE_ISOLATION kernel build option, and rebuild and reboot and all should be fine.
-
-However, Linus’s tree is currently at 4.15-rc6 + some outstanding patches. 4.15-rc7 should be out tomorrow, with those outstanding patches to resolve some issues, but most people do not run a -rc kernel in a “normal” environment.
-
-Because of this, the x86 kernel developers have done a wonderful job in their development of the page table isolation code, so much so that the backport to the latest stable kernel, 4.14, has been almost trivial for me to do. This means that the latest 4.14 release (4.14.12 at this moment in time), is what you should be running. 4.14.13 will be out in a few more days, with some additional fixes in it that are needed for some systems that have boot-time problems with 4.14.12 (it’s an obvious problem, if it does not boot, just add the patches now queued up.)
-
-I would personally like to thank Andy Lutomirski, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, Peter Zijlstra, Josh Poimboeuf, Juergen Gross, and Linus Torvalds for all of the work they have done in getting these fixes developed and merged upstream in a form that was so easy for me to consume to allow the stable releases to work properly. Without that effort, I don’t even want to think about what would have happened.
-
-For the older long term stable (LTS) kernels, I have leaned heavily on the wonderful work of Hugh Dickins, Dave Hansen, Jiri Kosina and Borislav Petkov to bring the same functionality to the 4.4 and 4.9 stable kernel trees. I had also had immense help from Guenter Roeck, Kees Cook, Jamie Iles, and many others in tracking down nasty bugs and missing patches. I want to also call out David Woodhouse, Eduardo Valentin, Laura Abbott, and Rik van Riel for their help with the backporting and integration as well, their help was essential in numerous tricky places.
-
-These LTS kernels also have the CONFIG_PAGE_TABLE_ISOLATION build option that should be enabled to get complete protection.
-
-As this backport is very different from the mainline version that is in 4.14 and 4.15, there are different bugs happening, right now we know of some VDSO issues that are getting worked on, and some odd virtual machine setups are reporting strange errors, but those are the minority at the moment, and should not stop you from upgrading at all right now. If you do run into problems with these releases, please let us know on the stable kernel mailing list.
-
-If you rely on any other kernel tree other than 4.4, 4.9, or 4.14 right now, and you do not have a distribution supporting you, you are out of luck. The lack of patches to resolve the Meltdown problem is so minor compared to the hundreds of other known exploits and bugs that your kernel version currently contains. You need to worry about that more than anything else at this moment, and get your systems up to date first.
-
-Also, go yell at the people who forced you to run an obsoleted and insecure kernel version, they are the ones that need to learn that doing so is a totally reckless act.
-
-### Meltdown – ARM64
-
-Right now the ARM64 set of patches for the Meltdown issue are not merged into Linus’s tree. They are [staged and ready to be merged][6] into 4.16-rc1 once 4.15 is released in a few weeks. Because these patches are not in a released kernel from Linus yet, I can not backport them into the stable kernel releases (hey, we have [rules][7] for a reason…)
-
-Due to them not being in a released kernel, if you rely on ARM64 for your systems (i.e. Android), I point you at the [Android Common Kernel tree][8] All of the ARM64 fixes have been merged into the [3.18,][9] [4.4,][10] and [4.9 branches][11] as of this point in time.
-
-I would strongly recommend just tracking those branches as more fixes get added over time due to testing and things catch up with what gets merged into the upstream kernel releases over time, especially as I do not know when these patches will land in the stable and LTS kernel releases at this point in time.
-
-For the 4.4 and 4.9 LTS kernels, odds are these patches will never get merged into them, due to the large number of prerequisite patches required. All of those prerequisite patches have been long merged and tested in the android-common kernels, so I think it is a better idea to just rely on those kernel branches instead of the LTS release for ARM systems at this point in time.
-
-Also note, I merge all of the LTS kernel updates into those branches usually within a day or so of being released, so you should be following those branches no matter what, to ensure your ARM systems are up to date and secure.
-
-### Spectre
-
-Now things get “interesting”…
-
-Again, if you are running a distro kernel, you _might_ be covered as some of the distros have merged various patches into them that they claim mitigate most of the problems here. I suggest updating and testing for yourself to see if you are worried about this attack vector
-
-For upstream, well, the status is there is no fixes merged into any upstream tree for these types of issues yet. There are numerous patches floating around on the different mailing lists that are proposing solutions for how to resolve them, but they are under heavy development, some of the patch series do not even build or apply to any known trees, the series conflict with each other, and it’s a general mess.
-
-This is due to the fact that the Spectre issues were the last to be addressed by the kernel developers. All of us were working on the Meltdown issue, and we had no real information on exactly what the Spectre problem was at all, and what patches were floating around were in even worse shape than what have been publicly posted.
-
-Because of all of this, it is going to take us in the kernel community a few weeks to resolve these issues and get them merged upstream. The fixes are coming in to various subsystems all over the kernel, and will be collected and released in the stable kernel updates as they are merged, so again, you are best off just staying up to date with either your distribution’s kernel releases, or the LTS and stable kernel releases.
-
-It’s not the best news, I know, but it’s reality. If it’s any consolation, it does not seem that any other operating system has full solutions for these issues either, the whole industry is in the same boat right now, and we just need to wait and let the developers solve the problem as quickly as they can.
-
-The proposed solutions are not trivial, but some of them are amazingly good. The [Retpoline][12] post from Paul Turner is an example of some of the new concepts being created to help resolve these issues. This is going to be an area of lots of research over the next years to come up with ways to mitigate the potential problems involved in hardware that wants to try to predict the future before it happens.
-
-### Other arches
-
-Right now, I have not seen patches for any other architectures than x86 and arm64\. There are rumors of patches floating around in some of the enterprise distributions for some of the other processor types, and hopefully they will surface in the weeks to come to get merged properly upstream. I have no idea when that will happen, if you are dependant on a specific architecture, I suggest asking on the arch-specific mailing list about this to get a straight answer.
-
-### Conclusion
-
-Again, update your kernels, don’t delay, and don’t stop. The updates to resolve these problems will be continuing to come for a long period of time. Also, there are still lots of other bugs and security issues being resolved in the stable and LTS kernel releases that are totally independent of these types of issues, so keeping up to date is always a good idea.
-
-Right now, there are a lot of very overworked, grumpy, sleepless, and just generally pissed off kernel developers working as hard as they can to resolve these issues that they themselves did not cause at all. Please be considerate of their situation right now. They need all the love and support and free supply of their favorite beverage that we can provide them to ensure that we all end up with fixed systems as soon as possible.
-
---------------------------------------------------------------------------------
-
-via: http://kroah.com/log/blog/2018/01/06/meltdown-status/
-
-作者:[Greg Kroah-Hartman ][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:http://kroah.com
-[1]:http://www.dailymail.co.uk/sciencetech/article-5238789/Intel-says-security-updates-fix-Meltdown-Spectre.html
-[2]:https://googleprojectzero.blogspot.fr/2018/01/reading-privileged-memory-with-side.html
-[3]:https://pwnies.com/
-[4]:https://lwn.net/Articles/743265/
-[5]:https://lwn.net/Articles/742999/
-[6]:https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=kpti
-[7]:https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
-[8]:https://android.googlesource.com/kernel/common/
-[9]:https://android.googlesource.com/kernel/common/+/android-3.18
-[10]:https://android.googlesource.com/kernel/common/+/android-4.4
-[11]:https://android.googlesource.com/kernel/common/+/android-4.9
-[12]:https://support.google.com/faqs/answer/7625886
diff --git a/sources/talk/20180108 You GNOME it- Windows and Apple devs get a compelling reason to turn to Linux.md b/sources/tech/20180108 You GNOME it- Windows and Apple devs get a compelling reason to turn to Linux.md
similarity index 100%
rename from sources/talk/20180108 You GNOME it- Windows and Apple devs get a compelling reason to turn to Linux.md
rename to sources/tech/20180108 You GNOME it- Windows and Apple devs get a compelling reason to turn to Linux.md
diff --git a/sources/tech/20180110 Best Linux Screenshot and Screencasting Tools.md b/sources/tech/20180110 Best Linux Screenshot and Screencasting Tools.md
deleted file mode 100644
index fbd10d2194..0000000000
--- a/sources/tech/20180110 Best Linux Screenshot and Screencasting Tools.md
+++ /dev/null
@@ -1,147 +0,0 @@
-Best Linux Screenshot and Screencasting Tools
-======
-
-
-There comes a time you want to capture an error on your screen and send it to the developers or want help from _Stack Overflow,_ you need the right tools to take that screenshot and save it or send it. There are tools in the form of programs and others as shell extensions for GNOME. Not to worry, here are the best Linux Screenshot taking tools that you can use to take those screenshots or make a screencast.
-
-## Best Linux Screenshot Or Screencasting Tools
-
-### 1\. Shutter
-
- [][2]
-
-[Shutter][3] is one of the best Linux screenshot taking tools. It has the advantage of taking different screenshots depending on what you want to take on your screen. After you take the screenshot, it allows you to see the screenshot before saving it after you take the screenshot. It also includes an extension menu that shows up on your top panel for GNOME. That makes accessing the app much easier and much convenient for anyone to use.
-
-You can take screenshots of a selection, a window, desktop, window under cursor, section, menu, tooltip or web. Shutter allows you to upload the screenshots directly to the cloud using the preferred cloud services provider. This Linux tool also allows you to edit your screenshots before you save them. It also comes with plugins that you can add or remove.
-
-To install it, you will have to type the following in the terminal:
-
-```
-sudo add-apt-repository -y ppa:shutter/ppa
-sudo apt-get update && sudo apt-get install shutter
-```
-
-### 2. Vokoscreen
-
- [][4]
-
-
-[Vokoscreen][5] is an app that allows you to record your screen as you show around and narrate what you are doing on the screen. It is easy to use, has a simple interface and includes a top panel menu for easy access when you are recording your screen.
-
-
-
-You can choose to record the whole screen, a window or just a selection of an area. Customizing the recording is easy to get the type of screen recording you want to achieve. Vokoscreen even allows you to create a gif as a screen recording. You can also record yourself using the webcam in case you were narrating as tutorials so that you can engage the learners. Once you are done, you can playback the recording right from the application so that you don’t have to keep navigating to find the recording.
-
- [][6]
-
-You can install Vocoscreen from your distro repository. Or download the package from [pkgs.org][7] , select the Linux distro you are using.
-
-```
-sudo dpkg -i vokoscreen_2.5.0-1_amd64.deb
-```
-
-### 3. OBS
-
- [][8]
-
-[OBS][9] can be used to record your screen as well as record streams from the internet. It allows you to see whatever you are recording as you stream or as you narrate your screen recording. It allows you to choose the quality of your recording according to your preferences. It also allows you to choose the type of file you want your recording to save to. In addition to the feature of recording, you can switch to Studio mode allowing you to edit your recording to make a complete video without having to use any other external editing software. To install OBS in your Linux distribution, you must have FFmpeg installed on your machine. To install FFmpeg type the following in the terminal for ubuntu 14.04 and earlier:
-
-```
-sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next
-
-sudo apt-get update && sudo apt-get install ffmpeg
-```
-
-For ubuntu 15.04 and later you can just type the following in the terminal to install FFmpeg:
-
-```
-sudo apt-get install ffmpeg
-```
-
-If you have already installed FFmpeg, type the following in the terminal to install OBS:
-
-```
-sudo add-apt-repository ppa:obsproject/obs-studio
-
-sudo apt-get update
-
-sudo apt-get install obs-studio
-```
-
-### 4. Green Recorder
-
- [][10]
-
-[Green recorder][11] is a simple interface based program that allows you to record the screen. You can choose what to record including video or just audio and allow you to show the mouse pointer and even follow it as you record your screen. You can record a window or just a selected area on your screen so that only what you want to record shows up in your recording. You can customize the number of frames to record in your final video. In case you want to start recording after a delay, you have the option to configure the delay you wish to set. You have the option to run a command after the recording is done that will run on your machine immediately after you stop recording.
-
-
-
-To install green recorder, type the following in the terminal:
-
-```
-sudo add-apt-repository ppa:fossproject/ppa
-
-sudo apt update && sudo apt install green-recorder
-```
-
-### 5. Kazam
-
- [][12]
-
-[Kazam][13] Linux screenshot tool is very popular amongst Linux users. It is an intuitive simple to use app that allows you to take a screencast or a screenshot allowing you to customise the delay before taking a screencast or screenshot. It allows you to select the area, window or fullscreen you want to capture. Kazam’s interface is well laid out and not as complicated as other apps. Its features will leave you happy about taking your screenshots. Kazam also includes a system tray icon and menu that allows you to take the screenshot without going to the application itself.
-
-
-
-To install Kazam, type the following in the terminal:
-
-```
-sudo apt-get install kazam
-```
-
-If the PPA is not found, you can install it manually using the following commands:
-
-```
-sudo add-apt-repository ppa:kazam-team/stable-series
-
-sudo apt-get update && sudo apt-get install kazam
-```
-
-### 6. Screenshot tool GNOME extension
-
- [][1]
-
-There is a GNOME extension just named screenshot tool that always shows up on the system panel until you disable it. It is convenient since it just sits on the system panel until you will trigger it to take a screenshot. The main advantage of this tool is that it is the quickest to access since it is always in your system panel unless you deactivate it in the tweak utility tool. The tool also has a preferences window allowing you to tweak it to your preferences. To install it on your GNOME desktop, head to extensions.gnome.org and search for “_Screenshot Tool”._
-
-You must have the gnome extensions chrome extension installed as well as GNOME tweaks tool installed to use the tool.
-
- [][14]
-
-The **Linux screenshot tools** are quite helpful especially when you don’t know what to do when you come across a problem and want to share the error with [the Linux community][15] or the developers of a program that you are using. Learning developers or programmers or anyone else need it will find these tools useful to share your screenshots. Youtubers and tutorial makers will find the screencasting tools even more useful when they use them to record their tutorials and post them.
-
-
---------------------------------------------------------------------------------
-
-via: http://www.linuxandubuntu.com/home/best-linux-screenshot-screencasting-tools
-
-作者:[linuxandubuntu][a]
-译者:[译者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/gnome-screenshot-extension-compressed_orig.jpg
-[2]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/shutter-linux-screenshot-taking-tools_orig.jpg
-[3]:http://shutter-project.org/
-[4]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/vokoscreen-screencasting-tool-for-linux_orig.jpg
-[5]:https://github.com/vkohaupt/vokoscreen
-[6]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/vokoscreen-preferences_orig.jpg
-[7]:https://pkgs.org/download/vokoscreen
-[8]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/obs-linux-screencasting-tool_orig.jpg
-[9]:https://obsproject.com/
-[10]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/green-recording-linux-tool_orig.jpg
-[11]:https://github.com/foss-project/green-recorder
-[12]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/kazam-screencasting-tool-for-linux_orig.jpg
-[13]:https://launchpad.net/kazam
-[14]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/gnome-screenshot-extension-preferences_orig.jpg
-[15]:http://www.linuxandubuntu.com/home/top-10-communities-to-help-you-learn-linux
diff --git a/sources/tech/20180111 Multimedia Apps for the Linux Console.md b/sources/tech/20180111 Multimedia Apps for the Linux Console.md
deleted file mode 100644
index 6cdd3ef857..0000000000
--- a/sources/tech/20180111 Multimedia Apps for the Linux Console.md
+++ /dev/null
@@ -1,112 +0,0 @@
-Translating by Yinr
-
-Multimedia Apps for the Linux Console
-======
-
-
-The Linux console supports multimedia, so you can enjoy music, movies, photos, and even read PDF files.
-
-When last we met, we learned that the Linux console supports multimedia. Yes, really! You can enjoy music, movies, photos, and even read PDF files without being in an X session with MPlayer, fbi, and fbgs. And, as a bonus, you can enjoy a Matrix-style screensaver for the console, CMatrix.
-
-You will probably have make some tweaks to your system to make this work. The examples used here are for Ubuntu Linux 16.04.
-
-### MPlayer
-
-You're probably familiar with the amazing and versatile MPlayer, which supports almost every video and audio format, and runs on nearly everything, including Linux, Android, Windows, Mac, Kindle, OS/2, and AmigaOS. Using MPLayer in your console will probably require some tweaking, depending on your Linux distribution. To start, try playing a video:
-```
-$ mplayer [video name]
-
-```
-
-If it works, then hurrah, and you can invest your time in learning useful MPlayer options, such as controlling the size of the video screen. However, some Linux distributions are managing the framebuffer differently than in the olden days, and you may have to adjust some settings to make it work. This is how to make it work on recent Ubuntu releases.
-
-First, add yourself to the video group.
-
-Second, verify that `/etc/modprobe.d/blacklist-framebuffer.conf` has this line: `#blacklist vesafb`. It should already be commented out, and if it isn't then comment it. All the other module lines should be un-commented, which prevents them from loading. Side note: if you want to dig more deeply into managing your framebuffer, the module for your video card may give better performance.
-
-Add these two modules to the end of `/etc/initramfs-tools/modules`, `vesafb` and `fbcon`, then rebuild the initramfs image:
-```
-$ sudo nano /etc/initramfs-tools/modules
- # List of modules that you want to include in your initramfs.
- # They will be loaded at boot time in the order below.
- fbcon
- vesafb
-
-$ sudo update-initramfs -u
-
-```
-
-[fbcon][1] is the Linux framebuffer console. It runs on top of the framebuffer and adds graphical features. It requires a framebuffer device, which is supplied by the `vesafb` module.
-
-Now you must edit your GRUB2 configuration. In `/etc/default/grub` you should see a line like this:
-```
-GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
-
-```
-
-It may have some other options, but it should be there. Add `vga=789`:
-```
-GRUB_CMDLINE_LINUX_DEFAULT="quiet splash vga=789"
-
-```
-
-Reboot and enter your console (Ctrl+Alt+F1), and try playing a video. This command selects the `fbdev2` video device; I haven't learned yet how to know which one to use, but I had to use it to play the video. The default screen size is 320x240, so I scaled it to 960:
-```
-$ mplayer -vo fbdev2 -vf scale -zoom -xy 960 AlienSong_mp4.mov
-```
-
-And behold Figure 1. It's grainy because I have a low-fi copy of this video, not because MPlayer is making it grainy.
-
-MPLayer plays CDs, DVDs, network streams, and has a giant batch of playback options, which I shall leave as your homework to explore.
-
-### fbi Image Viewer
-
-`fbi`, the framebuffer image viewer, comes in the [fbida][2] package on most Linuxes. It has native support for the common image file formats, and uses `convert` (from Image Magick), if it is installed, for other formats. Its simplest use is to view a single image file:
-```
-$ fbi filename
-
-```
-
-Use the arrow keys to scroll a large image, + and - to zoom, and r and l to rotate 90 degress right and left. Press the Escape key to close the image. You can play a slideshow by giving `fbi` a list of files:
-```
-$ fbi --list file-list.txt
-
-```
-
-`fbi` supports autozoom. With `-a` `fbi` controls the zoom factor. `--autoup` and `--autodown` tell `fbi` to only zoom up or down. Control the blend time between images with `--blend [time]`, in milliseconds. Press the k and j keys to jump behind and ahead in your file list.
-
-`fbi` has commands for creating file lists from images you have viewed, and for exporting your commands to a file, and a host of other cool options. Check out `man fbi` for complete options.
-
-### CMatrix Console Screensaver
-
-The Matrix screensaver is still my favorite (Figure 2), second only to the bouncing cow. [CMatrix][3] runs on the console. Simply type `cmatrix` to start it, and Ctrl+C stops it. Run `cmatrix -s` to launch it in screensaver mode, which exits on any keypress. `-C` changes the color. Your choices are green, red, blue, yellow, white, magenta, cyan, and black.
-
-CMatrix supports asynchronous key presses, which means you can change options while it's running.
-
-`-B` is all bold text, and `-B` is partially bold.
-
-### fbgs PDF Viewer
-
-It seems that the addiction to PDF documents is pandemic and incurable, though PDFs are better than they used to be, with live hyperlinks, copy-paste, and good text search. The `fbgs` console PDF viewer is part of the `fbida` package. Options include page size, resolution, page selections, and most `fbi` options, with the exceptions listed in `man fbgs`. The main option I use is page size; you get `-l`, `xl`, and `xxl` to choose from:
-```
-$ fbgs -xl annoyingpdf.pdf
-
-```
-
-Learn more about Linux through the free ["Introduction to Linux" ][4]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/learn/intro-to-linux/2018/1/multimedia-apps-linux-console
-
-作者:[Carla Schroder][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/cschroder
-[1]:https://www.mjmwired.net/kernel/Documentation/fb/fbcon.txt
-[2]:https://www.kraxel.org/blog/linux/fbida/
-[3]:http://www.asty.org/cmatrix/
-[4]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180111 What is the deal with GraphQL.md b/sources/tech/20180111 What is the deal with GraphQL.md
new file mode 100644
index 0000000000..98edcf18e0
--- /dev/null
+++ b/sources/tech/20180111 What is the deal with GraphQL.md
@@ -0,0 +1,41 @@
+What is the deal with GraphQL?
+======
+
+
+
+There has been lots of talks lately about this thing called [GraphQL][1]. It is a relatively new technology coming out of Facebook and is starting to be widely adopted by large companies like [Github][2], Facebook, Twitter, Yelp, and many others. Basically, GraphQL is an alternative to REST, it replaces many dumb endpoints, `/user/1`, `/user/1/comments` with `/graphql` and you use the post body or query string to request the data you need, like, `/graphql?query={user(id:1){id,username,comments{text}}}`. You pick the pieces of data you need and can nest down to relations to avoid multiple calls. This is a different way of thinking about a backend, but in some situations, it makes practical sense.
+
+### My Experience with GraphQL
+
+Originally when I heard about it I was very skeptical, after dabbling in [Apollo Server][3] I was not convinced. Why would you use some silly new technology when you can simply build REST endpoints! But after digging deeper and learning more about its use cases, I came around. I still think REST has a place and will be important for the foreseeable future, but with how bad many APIs and their documentation are, this can be a breath of fresh air...
+
+### Why Use GraphQL Over REST?
+
+Although I have used GraphQL, and think it is a compelling and exciting technology, I believe it does not replace REST. That being said there are compelling reasons to pick GraphQL over REST in some situations. When you are building mobile apps or web apps which are made with high mobile traffic in mind GraphQL really shines. The reason for this is mobile data. REST uses many calls and often returns unused data whereas, with GraphQL, you can define precisely what you want to be returned for minimal data usage.
+
+You can get do all the above with REST by making multiple endpoints available, but that also adds complexity to the project. It also means there will be back and forth between the front and backend teams.
+
+### What Should You Use?
+
+GraphQL is a new technology which is now mainstream. But many developers are not aware of it or choose not to learn it because they think it's a fad. I feel like for most projects you can get away using either REST or GraphQL. Developing using GraphQL has great benefits like enforcing documentation, which helps teams work better together, and provides clear expectations for each query. This will likely speed up development after the initial hurdle of wrapping your head around GraphQL.
+
+Although I have been comparing GraphQL and REST, I think in most cases a mixture of the two will produce the best results. Combine the strengths of both instead of seeing it strightly as just using GraphQL or just using REST.
+
+### Final Thoughts
+
+Both technologies are here to stay. And done right both technologies can make fast and efficient backends. GraphQL has an edge up because it allows the client to query only the data they need by default, but that is at a potential sacrifice of endpoint speed. Ultimately, if I were starting a new project, I would go with a mix of both GraphQL and REST.
+
+--------------------------------------------------------------------------------
+
+via: https://ryanmccue.ca/what-is-the-deal-with-graphql/
+
+作者:[Ryan McCue][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://ryanmccue.ca/author/ryan/
+[1]:http://graphql.org/
+[2]:https://developer.github.com/v4/
+[3]:https://github.com/apollographql/apollo-server
diff --git a/sources/tech/20180112 Top 5 Firefox extensions to install now.md b/sources/tech/20180112 Top 5 Firefox extensions to install now.md
deleted file mode 100644
index 3717b7c96d..0000000000
--- a/sources/tech/20180112 Top 5 Firefox extensions to install now.md
+++ /dev/null
@@ -1,85 +0,0 @@
-translating by ypingcn
-
-Top 5 Firefox extensions to install now
-======
-
-The right extensions can greatly enhance your browser's capabilities, but it's important to choose carefully. Here are five that are worth a look.
-
-
-
-The web browser has become a critical component of the computing experience for many users. Modern browsers have evolved into powerful and extensible platforms. As part of this, _extensions_ can add or modify their functionality. Extensions for Firefox are built using the WebExtensions API, a cross-browser development system.
-
-Which extensions should you install? Generally, that decision comes down to how you use your browser, your views on privacy, how much you trust extension developers, and other personal preferences.
-
-First, I'd like to point out that browser extensions often require the ability to read and/or change everything on the web pages you visit. You should consider the ramifications of this _very_ carefully. If an extension has modify access to all the web pages you visit, it could act as a key logger, intercept credit card information, track you online, insert advertisements, and perform a variety of other nefarious activities.
-
-That doesn't mean every extension will surreptitiously do these things, but you should carefully consider the installation source, the permissions involved, your risk profile, and other factors before you install any extension. Keep in mind you can use profiles to manage how an extension impacts your attack surface--for example, using a dedicated profile with no extensions to perform tasks such as online banking.
-
-With that in mind, here are five Firefox extensions that you may want to consider.
-
-### uBlock Origin
-
-![ublock origin ad blocker screenshot][2]
-
-
-Ublock Origin blocks ads and malware while enabling users to define their own content filters.
-
-[uBlock Origin][3] is a fast, low-memory, wide-spectrum blocker that not only blocks ads but also lets you enforce your own content filtering. The default behavior of uBlock Origin is to block ads, trackers, and malware sites using multiple predefined filter lists. From there it allows you to arbitrarily add lists and rules, or even lock down to a default-deny mode. In addition to being powerful, this extension has proven to be efficient and performant.
-
-### Privacy Badger
-
-![privacy badger ad blocker][5]
-
-
-Privacy Badger uses algorithms to seamlessly block ads and trackers that violate the principles of user consent.
-
-As its name indicates, [Privacy Badger][6] is a privacy-focused extension that blocks ads and third-party trackers. From the EFF: "Privacy Badger was born out of our desire to be able to recommend a single extension that would automatically analyze and block any tracker or ad that violated the principle of user consent; which could function well without any settings, knowledge, or configuration by the user; which is produced by an organization that is unambiguously working for its users rather than for advertisers; and which uses algorithmic methods to decide what is and isn't tracking."
-
-Why is Privacy Badger on this list when it may seem so similar to uBlock Origin? One reason is that it fundamentally works differently than uBlock Origin. Another is that a practice of defense in depth is a sound policy to follow.
-
-### LastPass
-
-![lastpass password manager screenshot][8]
-
-
-LastPass is a user-friendly password manager plugin that supports two-factor authorization.
-
-This is likely a controversial addition for many. Whether you should use a password manager at all--and if you do, whether you should choose one that has a browser plugin--is a hotly debated topic, and the answer very much depends on your personal risk profile. I'd assert that most casual computer users should use one, because it's much better than the most common alternative: using the same weak password everywhere.
-
-[LastPass][9] is user-friendly, supports two-factor authentication, and is reasonably secure. The company has had a few security incidents in the past, but it responded well and is well-funded moving forward. Keep in mind that using a password manager isn't an all-or-nothing proposition. Many users choose to use it for the majority of their passwords, while keeping a few complicated, well-constructed passwords for important sites such as banking and multi-factor authentication in their head.
-
-### Xmarks Sync
-
-[Xmarks Sync][10] is a convenient extension that will sync your bookmarks, open tabs, profiles, and browser history across instances. If you have multiple machines, want to sync across desktop and mobile, or use multiple different browsers on the same machine, take a look at Xmarks Sync. (Note that this extension was recently acquired by LastPass.)
-
-### Awesome Screenshot Plus
-
-[Awesome Screenshot Plus][11] allows you to easily capture all or part of any web page, as well as add annotations and comments, blur sensitive information, and more. You can also share images using an optional online service. I've found this tool great for capturing parts of sites for debugging issues, discussing design, and sharing information. It's one of those tools you'll find yourself using more than you might have expected.
-
-I've found all five of these extensions useful, and I recommend them to others. That said, there are many browser extensions out there. I'm curious about which ones other Opensource.com community members currently use and recommend. Let me know in the comments.
-
-![Awesome Screenshot Plus screenshot][13]
-
-
-Awesome Screenshot Plus allows you to easily capture all or part of any web page.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/18/1/top-5-firefox-extensions
-
-作者:[Jeremy Garcia][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/jeremy-garcia
-[2]:https://opensource.com/sites/default/files/ublock.png (ublock origin ad blocker screenshot)
-[3]:https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/
-[5]:https://opensource.com/sites/default/files/images/life-uploads/privacy_badger_1.0.1.png (privacy badger ad blocker screenshot)
-[6]:https://www.eff.org/privacybadger
-[8]:https://opensource.com/sites/default/files/images/life-uploads/lastpass4.jpg (lastpass password manager screenshot)
-[9]:https://addons.mozilla.org/en-US/firefox/addon/lastpass-password-manager/
-[10]:https://addons.mozilla.org/en-US/firefox/addon/xmarks-sync/
-[11]:https://addons.mozilla.org/en-US/firefox/addon/screenshot-capture-annotate/
-[13]:https://opensource.com/sites/default/files/screenshot_from_2018-01-04_17-11-32.png (Awesome Screenshot Plus screenshot)
diff --git a/sources/tech/20180115 How To Boot Into Linux Command Line.md b/sources/tech/20180115 How To Boot Into Linux Command Line.md
deleted file mode 100644
index 7a63f47f90..0000000000
--- a/sources/tech/20180115 How To Boot Into Linux Command Line.md
+++ /dev/null
@@ -1,61 +0,0 @@
-How To Boot Into Linux Command Line
-======
-
-
-There may be times where you need or want to boot up a [Linux][1] system without using a GUI, that is with no X, but rather opt for the command line. Whatever the reason, fortunately, booting straight into the Linux **command-line** is very simple. It requires a simple change to the boot parameter after the other kernel options. This change specifies the runlevel to boot the system into.
-
-### Why Do This?
-
-If your system does not run Xorg because the configuration is invalid, or if the display manager is broken, or whatever may prevent the GUI from starting properly, booting into the command-line will allow you to troubleshoot by logging into a terminal (assuming you know what you’re doing to start with) and do whatever you need to do. Booting into the command-line is also a great way to become more familiar with the terminal, otherwise, you can do it just for fun.
-
-### Accessing GRUB Menu
-
-On startup, you will need access to the GRUB boot menu. You may need to hold the SHIFT key down before the system boots if the menu isn’t set to display every time the computer is started. In the menu, the [Linux distribution][2] entry must be selected. Once highlighted, press ‘e’ to edit the boot parameters.
-
- [][3]
-
- Older GRUB versions follow a similar mechanism. The boot manager should provide instructions on how to edit the boot parameters.
-
-### Specify the Runlevel
-
-An editor will appear and you will see the options that GRUB parses to the kernel. Navigate to the line that starts with ‘linux’ (older GRUB versions may be ‘kernel’; select that and follow the instructions). This specifies parameters to parse into the kernel. At the end of that line (may appear to span multiple lines, depending on resolution), you simply specify the runlevel to boot into, which is 3 (multi-user mode, text-only).
-
- [][4]
-
-Pressing Ctrl-X or F10 will boot the system using those parameters. Boot-up will continue as normal. The only thing that has changed is the runlevel to boot into.
-
-
-
-This is what was started up:
-
- [][5]
-
-### Runlevels
-
-You can specify different runlevels to boot into with runlevel 5 being the default one. 1 boots into “single-user” mode, which boots into a root shell. 3 provides a multi-user, command-line only system.
-
-### Switch From Command-Line
-
-At some point, you may want to run the display manager again to use a GUI, and the quickest way to do that is running this:
-```
-$ sudo init 5
-```
-
-And it is as simple as that. Personally, I find the command-line much more exciting and hands-on than using GUI tools; however, that’s just my preference.
-
---------------------------------------------------------------------------------
-
-via: http://www.linuxandubuntu.com/home/how-to-boot-into-linux-command-line
-
-作者:[LinuxAndUbuntu][a]
-译者:[译者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/home/category/linux
-[2]:http://www.linuxandubuntu.com/home/category/distros
-[3]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/gnu-grub_orig.png
-[4]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/runlevel_orig.png
-[5]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/runlevel_1_orig.png
diff --git a/sources/tech/20180116 SPARTA - Network Penetration Testing GUI Toolkit.md b/sources/tech/20180116 SPARTA - Network Penetration Testing GUI Toolkit.md
new file mode 100644
index 0000000000..06427c101d
--- /dev/null
+++ b/sources/tech/20180116 SPARTA - Network Penetration Testing GUI Toolkit.md
@@ -0,0 +1,107 @@
+SPARTA – Network Penetration Testing GUI Toolkit
+======
+
+
+
+SPARTA is GUI application developed with python and inbuild Network Penetration Testing Kali Linux tool. It simplifies scanning and enumeration phase with faster results.
+
+Best thing of SPARTA GUI Toolkit it scans detects the service running on the target port.
+
+Also, it provides Bruteforce attack for scanned open ports and services as a part of enumeration phase.
+
+
+Also Read: Network Pentesting Checklist][1]
+
+## Installation
+
+Please clone the latest version of SPARTA from github:
+
+```
+git clone https://github.com/secforce/sparta.git
+```
+
+Alternatively, download the latest zip file [here][2].
+```
+cd /usr/share/
+git clone https://github.com/secforce/sparta.git
+```
+Place the "sparta" file in /usr/bin/ and make it executable.
+Type 'sparta' in any terminal to launch the application.
+
+
+## The scope of Network Penetration Testing Work:
+
+ * Organizations security weaknesses in their network infrastructures are identified by a list of host or targeted host and add them to the scope.
+ * Select menu bar - File > Add host(s) to scope
+
+
+
+[![Network Penetration Testing][3]][4]
+
+[![Network Penetration Testing][5]][6]
+
+ * Above figures show target Ip is added to the scope.According to your network can add the range of IPs to scan.
+ * After adding Nmap scan will begin and results will be very faster.now scanning phase is done.
+
+
+
+## Open Ports & Services:
+
+ * Nmap results will provide target open ports and services.
+
+
+
+[![Network Penetration Testing][7]][8]
+
+ * Above figure shows that target operating system, Open ports and services are discovered as scan results.
+
+
+
+## Brute Force Attack on Open ports:
+
+ * Let us Brute force Server Message Block (SMB) via port 445 to enumerate the list of users and their valid passwords.
+
+
+
+[![Network Penetration Testing][9]][10]
+
+ * Right-click and Select option Send to Brute.Also, select discovered Open ports and service on target.
+ * Browse and add dictionary files for Username and password fields.
+
+
+
+[![Network Penetration Testing][11]][12]
+
+ * Click Run to start the Brute force attack on the target.Above Figure shows Brute force attack is successfully completed on the target IP and the valid password is Found!
+ * Always think failed login attempts will be logged as Event logs in Windows.
+ * Password changing policy should be 15 to 30 days will be a good practice.
+ * Always recommended to use a strong password as per policy.Password lockout policy is a good one to stop brute force attacks (After 5 failure attempts account will be locked)
+ * The integration of business-critical asset to SIEM( security incident & Event Management) will detect these kinds of attacks as soon as possible.
+
+
+
+SPARTA is timing saving GUI Toolkit for pentesters for scanning and enumeration phase.SPARTA Scans and Bruteforce various protocols.It has many more features! Happy Hacking.
+
+--------------------------------------------------------------------------------
+
+via: https://gbhackers.com/sparta-network-penetration-testing-gui-toolkit/
+
+作者:[Balaganesh][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://gbhackers.com/author/balaganesh/
+[1]:https://gbhackers.com/network-penetration-testing-checklist-examples/
+[2]:https://github.com/SECFORCE/sparta/archive/master.zip
+[3]:https://i0.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-526.png?resize=696%2C495&ssl=1
+[4]:https://i0.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-526.png?ssl=1
+[5]:https://i2.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-527.png?resize=696%2C516&ssl=1
+[6]:https://i2.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-527.png?ssl=1
+[7]:https://i2.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-528.png?resize=696%2C519&ssl=1
+[8]:https://i2.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-528.png?ssl=1
+[9]:https://i1.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-529.png?resize=696%2C525&ssl=1
+[10]:https://i1.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-529.png?ssl=1
+[11]:https://i2.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-531.png?resize=696%2C523&ssl=1
+[12]:https://i2.wp.com/gbhackers.com/wp-content/uploads/2018/01/Screenshot-531.png?ssl=1
diff --git a/sources/tech/20180117 Linux tee Command Explained for Beginners (6 Examples).md b/sources/tech/20180117 Linux tee Command Explained for Beginners (6 Examples).md
deleted file mode 100644
index e1be9e3da2..0000000000
--- a/sources/tech/20180117 Linux tee Command Explained for Beginners (6 Examples).md
+++ /dev/null
@@ -1,130 +0,0 @@
-Linux tee Command Explained for Beginners (6 Examples)
-======
-
-There are times when you want to manually track output of a command and also simultaneously make sure the output is being written to a file so that you can refer to it later. If you are looking for a Linux tool which can do this for you, you'll be glad to know there exists a command **tee** that's built for this purpose.
-
-In this tutorial, we will discuss the basics of the tee command using some easy to understand examples. But before we do that, it's worth mentioning that all examples used in this article have been tested on Ubuntu 16.04 LTS.
-
-### Linux tee command
-
-The tee command basically reads from the standard input and writes to standard output and files. Following is the syntax of the command:
-
-```
-tee [OPTION]... [FILE]...
-```
-
-And here's how the man page explains it:
-```
-Copy standard input to each FILE, and also to standard output.
-```
-
-The following Q&A-styled examples should give you a better idea on how the command works.
-
-### Q1. How to use tee command in Linux?
-
-Suppose you are using the ping command for some reason.
-
-ping google.com
-
-[![How to use tee command in Linux][1]][2]
-
-And what you want, is that the output should also get written to a file in parallel. Then here's where you can use the tee command.
-
-```
-ping google.com | tee output.txt
-```
-
-The following screenshot shows the output was written to the 'output.txt' file along with being written on stdout.
-
-[![tee command output][3]][4]
-
-So that should clear the basic usage of tee.
-
-### Q2. How to make sure tee appends information in files?
-
-By default, the tee command overwrites information in a file when used again. However, if you want, you can change this behavior by using the -a command line option.
-
-```
-[command] | tee -a [file]
-```
-
-So basically, the -a option forces tee to append information to the file.
-
-### Q3. How to make tee write to multiple files?
-
-That's pretty easy. You just have to mention their names.
-
-```
-[command] | tee [file1] [file2] [file3]
-```
-
-For example:
-
-```
-ping google.com | tee output1.txt output2.txt output3.txt
-```
-
-[![How to make tee write to multiple files][5]][6]
-
-### Q4. How to make tee redirect output of one command to another?
-
-You can not only use tee to simultaneously write output to files, but also to pass on the output as input to other commands. For example, the following command will not only store the filenames in 'output.txt' but also let you know - through wc - the number of entries in the output.txt file.
-
-```
-ls file* | tee output.txt | wc -l
-```
-
-[![How to make tee redirect output of one command to another][7]][8]
-
-### Q5. How to write to a file with elevated privileges using tee?
-
-Suppose you opened a file in the [Vim editor][9], made a lot of changes, and then when you tried saving those changes, you got an error that made you realize that it's a root-owned file, meaning you need to have sudo privileges to save these changes.
-
-[![How to write to a file with elevated privileges using tee][10]][11]
-
-In scenarios like these, you can use tee to elevate privileges on the go.
-
-```
-:w !sudo tee %
-```
-
-The aforementioned command will ask you for root password, and then let you save the changes.
-
-### Q6. How to make tee ignore interrupt?
-
-The -i command line option enables tee to ignore the interrupt signal (`SIGINT`), which is usually issued when you press the crl+c key combination.
-
-```
-[command] | tee -i [file]
-```
-
-This is useful when you want to kill the command with ctrl+c but want tee to exit gracefully.
-
-### Conclusion
-
-You'll likely agree now that tee is an extremely useful command. We've discussed it's basic usage as well as majority of its command line options here. The tool doesn't have a steep learning curve, so just practice all these examples, and you should be good to go. For more information, head to the tool's [man page][12].
-
-
---------------------------------------------------------------------------------
-
-via: https://www.howtoforge.com/linux-tee-command/
-
-作者:[Himanshu Arora][a]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]:https://www.howtoforge.com
-[1]:https://www.howtoforge.com/images/command-tutorial/ping-example.png
-[2]:https://www.howtoforge.com/images/command-tutorial/big/ping-example.png
-[3]:https://www.howtoforge.com/images/command-tutorial/ping-with-tee.png
-[4]:https://www.howtoforge.com/images/command-tutorial/big/ping-with-tee.png
-[5]:https://www.howtoforge.com/images/command-tutorial/tee-mult-files1.png
-[6]:https://www.howtoforge.com/images/command-tutorial/big/tee-mult-files1.png
-[7]:https://www.howtoforge.com/images/command-tutorial/tee-redirect-output.png
-[8]:https://www.howtoforge.com/images/command-tutorial/big/tee-redirect-output.png
-[9]:https://www.howtoforge.com/vim-basics
-[10]:https://www.howtoforge.com/images/command-tutorial/vim-write-error.png
-[11]:https://www.howtoforge.com/images/command-tutorial/big/vim-write-error.png
-[12]:https://linux.die.net/man/1/tee
diff --git a/sources/tech/20180118 Getting Started with ncurses.md b/sources/tech/20180118 Getting Started with ncurses.md
new file mode 100644
index 0000000000..78e53efa79
--- /dev/null
+++ b/sources/tech/20180118 Getting Started with ncurses.md
@@ -0,0 +1,214 @@
+leemeans translating
+Getting Started with ncurses
+======
+How to use curses to draw to the terminal screen.
+
+While graphical user interfaces are very cool, not every program needs to run with a point-and-click interface. For example, the venerable vi editor ran in plain-text terminals long before the first GUI.
+
+The vi editor is one example of a screen-oriented program that draws in "text" mode, using a library called curses, which provides a set of programming interfaces to manipulate the terminal screen. The curses library originated in BSD UNIX, but Linux systems provide this functionality through the ncurses library.
+
+[For a "blast from the past" on ncurses, see ["ncurses: Portable Screen-Handling for Linux"][1], September 1, 1995, by Eric S. Raymond.]
+
+Creating programs that use curses is actually quite simple. In this article, I show an example program that leverages curses to draw to the terminal screen.
+
+### Sierpinski's Triangle
+
+One simple way to demonstrate a few curses functions is by generating Sierpinski's Triangle. If you aren't familiar with this method to generate Sierpinski's Triangle, here are the rules:
+
+1. Set three points that define a triangle.
+
+2. Randomly select a point anywhere (x,y).
+
+Then:
+
+1. Randomly select one of the triangle's points.
+
+2. Set the new x,y to be the midpoint between the previous x,y and the triangle point.
+
+3. Repeat.
+
+So with those instructions, I wrote this program to draw Sierpinski's Triangle to the terminal screen using the curses functions:
+
+```
+
+ 1 /* triangle.c */
+ 2
+ 3 #include
+ 4 #include
+ 5
+ 6 #include "getrandom_int.h"
+ 7
+ 8 #define ITERMAX 10000
+ 9
+ 10 int main(void)
+ 11 {
+ 12 long iter;
+ 13 int yi, xi;
+ 14 int y[3], x[3];
+ 15 int index;
+ 16 int maxlines, maxcols;
+ 17
+ 18 /* initialize curses */
+ 19
+ 20 initscr();
+ 21 cbreak();
+ 22 noecho();
+ 23
+ 24 clear();
+ 25
+ 26 /* initialize triangle */
+ 27
+ 28 maxlines = LINES - 1;
+ 29 maxcols = COLS - 1;
+ 30
+ 31 y[0] = 0;
+ 32 x[0] = 0;
+ 33
+ 34 y[1] = maxlines;
+ 35 x[1] = maxcols / 2;
+ 36
+ 37 y[2] = 0;
+ 38 x[2] = maxcols;
+ 39
+ 40 mvaddch(y[0], x[0], '0');
+ 41 mvaddch(y[1], x[1], '1');
+ 42 mvaddch(y[2], x[2], '2');
+ 43
+ 44 /* initialize yi,xi with random values */
+ 45
+ 46 yi = getrandom_int() % maxlines;
+ 47 xi = getrandom_int() % maxcols;
+ 48
+ 49 mvaddch(yi, xi, '.');
+ 50
+ 51 /* iterate the triangle */
+ 52
+ 53 for (iter = 0; iter < ITERMAX; iter++) {
+ 54 index = getrandom_int() % 3;
+ 55
+ 56 yi = (yi + y[index]) / 2;
+ 57 xi = (xi + x[index]) / 2;
+ 58
+ 59 mvaddch(yi, xi, '*');
+ 60 refresh();
+ 61 }
+ 62
+ 63 /* done */
+ 64
+ 65 mvaddstr(maxlines, 0, "Press any key to quit");
+ 66
+ 67 refresh();
+ 68
+ 69 getch();
+ 70 endwin();
+ 71
+ 72 exit(0);
+ 73 }
+
+```
+
+Let me walk through that program by way of explanation. First, the getrandom_int() is my own wrapper to the Linux getrandom() system call, but it's guaranteed to return a positive integer value. Otherwise, you should be able to identify the code lines that initialize and then iterate Sierpinski's Triangle, based on the above rules. Aside from that, let's look at the curses functions I used to draw the triangle on a terminal.
+
+Most curses programs will start with these four instructions. 1) The initscr() function determines the terminal type, including its size and features, and sets up the curses environment based on what the terminal can support. The cbreak() function disables line buffering and sets curses to take one character at a time. The noecho() function tells curses not to echo the input back to the screen, and the clear() function clears the screen:
+
+```
+
+ 20 initscr();
+ 21 cbreak();
+ 22 noecho();
+ 23
+ 24 clear();
+
+```
+
+The program then sets a few variables to define the three points that define a triangle. Note the use of LINES and COLS here, which were set by initscr(). These values tell the program how many lines and columns exist on the terminal. Screen coordinates start at zero, so the top-left of the screen is row 0, column 0\. The bottom-right of the screen is row LINES - 1, column COLS - 1\. To make this easy to remember, my program sets these values in the variables maxlines and maxcols, respectively.
+
+Two simple methods to draw text on the screen are the addch() and addstr() functions. To put text at a specific screen location, use the related mvaddch() and mvaddstr() functions. My program uses these functions in several places. First, the program draws the three points that define the triangle, labeled "0", "1" and "2":
+
+```
+
+ 40 mvaddch(y[0], x[0], '0');
+ 41 mvaddch(y[1], x[1], '1');
+ 42 mvaddch(y[2], x[2], '2');
+
+```
+
+To draw the random starting point, the program makes a similar call:
+
+```
+
+ 49 mvaddch(yi, xi, '.');
+
+```
+
+And to draw each successive point in Sierpinski's Triangle iteration:
+
+```
+
+ 59 mvaddch(yi, xi, '*');
+
+```
+
+When the program is done, it displays a helpful message at the lower-left corner of the screen (at row maxlines, column 0):
+
+```
+
+ 65 mvaddstr(maxlines, 0, "Press any key to quit");
+
+```
+
+It's important to note that curses maintains a version of the screen in memory and updates the screen only when you ask it to. This provides greater performance, especially if you want to display a lot of text to the screen. This is because curses can update only those parts of the screen that changed since the last update. To cause curses to update the terminal screen, use the refresh() function.
+
+In my example program, I've chosen to update the screen after "drawing" each successive point in Sierpinski's Triangle. By doing so, users should be able to observe each iteration in the triangle.
+
+Before exiting, I use the getch() function to wait for the user to press a key. Then I call endwin() to exit the curses environment and return the terminal screen to normal control:
+
+```
+
+ 69 getch();
+ 70 endwin();
+
+```
+
+### Compiling and Sample Output
+
+Now that you have your first sample curses program, it's time to compile and run it. Remember that Linux systems implement the curses functionality via the ncurses library, so you need to link with -lncurses when you compile—for example:
+
+```
+
+$ ls
+getrandom_int.c getrandom_int.h triangle.c
+
+$ gcc -Wall -lncurses -o triangle triangle.c getrandom_int.c
+
+```
+
+Running the triangle program on a standard 80x24 terminal is not very interesting. You just can't see much detail in Sierpinski's Triangle at that resolution. If you run a terminal window and set a very small font size, you can see the fractal nature of Sierpinski's Triangle more easily. On my system, the output looks like Figure 1.
+
+
+
+Figure 1. Output of the triangle Program
+
+Despite the random nature of the iteration, every run of Sierpinski's Triangle will look pretty much the same. The only difference will be where the first few points are drawn to the screen. In this example, you can see the single dot that starts the triangle, near point 1\. It looks like the program picked point 2 next, and you can see the asterisk halfway between the dot and the "2". And it looks like the program randomly picked point 2 for the next random number, because you can see the asterisk halfway between the first asterisk and the "2". From there, it's impossible to tell how the triangle was drawn, because all of the successive dots fall within the triangle area.
+
+### Starting to Learn ncurses
+
+This program is a simple example of how to use the curses functions to draw characters to the screen. You can do so much more with curses, depending on what you need your program to do. In a follow up article, I will show how to use curses to allow the user to interact with the screen. If you are interested in getting a head start with curses, I encourage you to read Pradeep Padala's ["NCURSES Programming HOWTO"][2], at the Linux Documentation Project.
+
+### About the author
+
+Jim Hall is an advocate for free and open-source software, best known for his work on the FreeDOS Project, and he also focuses on the usability of open-source software. Jim is the Chief Information Officer at Ramsey County, Minn.
+
+--------------------------------------------------------------------------------
+
+via: http://www.linuxjournal.com/content/getting-started-ncurses
+
+作者:[Jim Hall][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://www.linuxjournal.com/users/jim-hall
+[1]:http://www.linuxjournal.com/article/1124
+[2]:http://tldp.org/HOWTO/NCURSES-Programming-HOWTO
diff --git a/sources/tech/20180118 How To List and Delete iptables Firewall Rules.md b/sources/tech/20180118 How To List and Delete iptables Firewall Rules.md
new file mode 100644
index 0000000000..b6b875ad11
--- /dev/null
+++ b/sources/tech/20180118 How To List and Delete iptables Firewall Rules.md
@@ -0,0 +1,106 @@
+How To List and Delete iptables Firewall Rules
+======
+![How To List and Delete iptables Firewall Rules][1]
+
+We'll show you, how to list and delete iptables firewall rules. Iptables is a command line utility that allows system administrators to configure the packet filtering rule set on Linux. iptables requires elevated privileges to operate and must be executed by user root, otherwise it fails to function.
+
+### How to List iptables Firewall Rules
+
+Iptables allows you to list all the rules which are already added to the packet filtering rule set. In order to be able to check this you need to have SSH access to the server. [Connect to your Linux VPS via SSH][2] and run the following command:
+```
+sudo iptables -nvL
+```
+
+To run the command above your user need to have `sudo` privileges. Otherwise, you need to [add sudo user on your Linux VPS][3] or use the root user.
+
+If there are no rules added to the packet filtering ruleset the output should be similar to the one below:
+```
+Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
+ pkts bytes target prot opt in out source destination
+
+Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
+ pkts bytes target prot opt in out source destination
+
+Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
+ pkts bytes target prot opt in out source destination
+
+```
+
+Since NAT (Network Address Translation) can also be configured via iptables, you can use iptables to list the NAT rules:
+```
+sudo iptables -t nat -n -L -v
+```
+
+The output will be similar to the one below if there are no rules added:
+```
+Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
+ pkts bytes target prot opt in out source destination
+
+Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
+ pkts bytes target prot opt in out source destination
+
+Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
+ pkts bytes target prot opt in out source destination
+
+```
+
+If this is the case we recommend you to check our tutorial on How to [Set Up a Firewall with iptables on Ubuntu and CentOS][4] to make your server more secure.
+
+### How to Delete iptables Firewall Rules
+
+At some point, you may need to remove a specific iptables firewall rule on your server. For that purpose you need to use the following syntax:
+```
+iptables [-t table] -D chain rulenum
+```
+
+For example, if you have a firewall rule to block all connections from 111.111.111.111 to your server on port 22 and you want to remove that rule, you can use the following command:
+```
+sudo iptables -D INPUT -s 111.111.111.111 -p tcp --dport 22 -j DROP
+```
+
+Now that you removed the iptables firewall rule you need to save the changes to make them persistent.
+
+In case you are using [Ubuntu VPS][5] you need to install additional package for that purpose. To install the required package use the following command:
+```
+sudo apt-get install iptables-persistent
+```
+
+On **Ubutnu 14.04** you can save and reload the firewall rules using the commands below:
+```
+sudo /etc/init.d/iptables-persistent save
+sudo /etc/init.d/iptables-persistent reload
+```
+
+On **Ubuntu 16.04** use the following commands instead:
+```
+sudo netfilter-persistent save
+sudo netfilter-persistent reload
+```
+
+If you are using [CentOS VPS][6] you can save the changes using the command below:
+```
+service iptables save
+```
+
+Of course, you don't have to list and delete iptables firewall rules if you use one of our [Managed VPS Hosting][7] services, in which case you can simply ask our expert Linux admins to help you list and delete iptables firewall rules on your server. They are available 24×7 and will take care of your request immediately.
+
+**PS**. If you liked this post, on how to list and delete iptables firewall rules, please share it with your friends on the social networks using the buttons on the left or simply leave a reply below. Thanks.
+
+--------------------------------------------------------------------------------
+
+via: https://www.rosehosting.com/blog/how-to-list-and-delete-iptables-firewall-rules/
+
+作者:[RoseHosting][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.rosehosting.com
+[1]:https://www.rosehosting.com/blog/wp-content/uploads/2018/01/How-To-List-and-Delete-iptables-Firewall-Rules.jpg
+[2]:https://www.rosehosting.com/blog/connect-to-your-linux-vps-via-ssh/
+[3]:https://www.rosehosting.com/blog/how-to-create-a-sudo-user-on-ubuntu/
+[4]:https://www.rosehosting.com/blog/how-to-set-up-a-firewall-with-iptables-on-ubuntu-and-centos/
+[5]:https://www.rosehosting.com/ubuntu-vps.html
+[6]:https://www.rosehosting.com/centos-vps.html
+[7]:https://www.rosehosting.com/managed-vps-hosting.html
diff --git a/sources/tech/20180118 How to Play Sound Through Two or More Output Devices in Linux.md b/sources/tech/20180118 How to Play Sound Through Two or More Output Devices in Linux.md
new file mode 100644
index 0000000000..2f35b15ac7
--- /dev/null
+++ b/sources/tech/20180118 How to Play Sound Through Two or More Output Devices in Linux.md
@@ -0,0 +1,62 @@
+translating by lujun9972
+How to Play Sound Through Two or More Output Devices in Linux
+======
+
+
+
+Handling audio in Linux can be a pain. Pulseaudio has made it both better and worse. While some things work better than they did before, other things have become more complicated. Handling audio output is one of those things.
+
+If you want to enable multiple audio outputs from your Linux PC, you can use a simple utility to enable your other sound devices on a virtual interface. It's a lot easier than it sounds.
+
+In case you're wondering why you'd want to do this, a pretty common instance is playing video from your computer on a TV and using both the PC and TV speakers.
+
+### Install Paprefs
+
+The easiest way to enable audio playback from multiple sources is to use a simple graphical utility called "paprefs." It's short for PulseAudio Preferences.
+
+It's available through the Ubuntu repositories, so just install it with Apt.
+```
+sudo apt install paprefs
+```
+
+When the install finishes, you can just launch the program.
+
+### Enable Dual Audio Playback
+
+Even though the utility is graphical, it's still probably easier to launch it by typing `paprefs` in the command line as a regular user.
+
+The window that opens has a few tabs with settings that you can tweak. The tab that you're looking for is the last one, "Simultaneous Output."
+
+![Paprefs on Ubuntu][1]
+
+There isn't a whole lot on the tab, just a checkbox to enable the setting.
+
+Next, open up the regular sound preferences. It's in different places on different distributions. On Ubuntu it'll be under the GNOME system settings.
+
+![Enable Simultaneous Audio][2]
+
+Once you have your sound preferences open, select the "Output" tab. Select the "Simultaneous output" radio button. It's now your default output.
+
+### Test It
+
+To test it, you can use anything you like, but music always works. If you are using a video, like suggested earlier, you can certainly test it with that as well.
+
+If everything is working well, you should hear audio out of all connected devices.
+
+That's all there really is to do. This works best when there are multiple devices, like the HDMI port and the standard analog output. You can certainly try it with other configurations, too. You should also keep in mind that there will only be a single volume control, so adjust the physical output devices accordingly.
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.maketecheasier.com/play-sound-through-multiple-devices-linux/
+
+作者:[Nick Congleton][a]
+译者:[lujun9972](https://github.com/lujun9972)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.maketecheasier.com/author/nickcongleton/
+[1]:https://www.maketecheasier.com/assets/uploads/2018/01/sa-paprefs.jpg (Paprefs on Ubuntu)
+[2]:https://www.maketecheasier.com/assets/uploads/2018/01/sa-enable.jpg (Enable Simultaneous Audio)
+[3]:https://depositphotos.com/89314442/stock-photo-headphones-on-speakers.html
diff --git a/sources/tech/20180118 Rediscovering make- the power behind rules.md b/sources/tech/20180118 Rediscovering make- the power behind rules.md
new file mode 100644
index 0000000000..ea500a2689
--- /dev/null
+++ b/sources/tech/20180118 Rediscovering make- the power behind rules.md
@@ -0,0 +1,102 @@
+Translating by cncuckoo
+
+Rediscovering make: the power behind rules
+======
+
+
+
+I used to think makefiles were just a convenient way to list groups of shell commands; over time I've learned how powerful, flexible, and full-featured they are. This post brings to light over some of those features related to rules.
+
+### Rules
+
+Rules are instructions that indicate `make` how and when a file called the target should be built. The target can depend on other files called prerequisites.
+
+You instruct `make` how to build the target in the recipe, which is no more than a set of shell commands to be executed, one at a time, in the order they appear. The syntax looks like this:
+```
+target_name : prerequisites
+ recipe
+```
+
+Once you have defined a rule, you can build the target from the command line by executing:
+```
+$ make target_name
+```
+
+Once the target is built, `make` is smart enough to not run the recipe ever again unless at least one of the prerequisites has changed.
+
+### More on prerequisites
+
+Prerequisites indicate two things:
+
+ * When the target should be built: if a prerequisite is newer than the target, `make` assumes that the target should be built.
+ * An order of execution: since prerequisites can, in turn, be built by another rule on the makefile, they also implicitly set an order on which rules are executed.
+
+
+
+If you want to define an order, but you don't want to rebuild the target if the prerequisite changes, you can use a special kind of prerequisite called order only, which can be placed after the normal prerequisites, separated by a pipe (`|`)
+
+### Patterns
+
+For convenience, `make` accepts patterns for targets and prerequisites. A pattern is defined by including the `%` character, a wildcard that matches any number of literal characters or an empty string. Here are some examples:
+
+ * `%`: match any file
+ * `%.md`: match all files with the `.md` extension
+ * `prefix%.go`: match all files that start with `prefix` that have the `.go` extension
+
+
+
+### Special targets
+
+There's a set of target names that have special meaning for `make` called special targets.
+
+You can find the full list of special targets in the [documentation][1]. As a rule of thumb, special targets start with a dot followed by uppercase letters.
+
+Here are a few useful ones:
+
+**.PHONY** : Indicates `make` that the prerequisites of this target are considered to be phony targets, which means that `make` will always run it's recipe regardless of whether a file with that name exists or what its last-modification time is.
+
+**.DEFAULT** : Used for any target for which no rules are found.
+
+**.IGNORE** : If you specify prerequisites for `.IGNORE`, `make` will ignore errors in execution of their recipes.
+
+### Substitutions
+
+Substitutions are useful when you need to modify the value of a variable with alterations that you specify.
+
+A substitution has the form `$(var:a=b)` and its meaning is to take the value of the variable `var`, replace every `a` at the end of a word with `b` in that value, and substitute the resulting string. For example:
+```
+foo := a.o
+bar : = $(foo:.o=.c) # sets bar to a.c
+```
+
+note: special thanks to [Luis Lavena][2] for letting me know about the existence of substitutions.
+
+### Archive Files
+
+Archive files are used to collect multiple data files together into a single file (same concept as a zip file), they are built with the `ar` Unix utility. `ar` can be used to create archives for any purpose, but has been largely replaced by `tar` for any other purposes than [static libraries][3].
+
+In `make`, you can use an individual member of an archive file as a target or prerequisite as follows:
+```
+archive(member) : prerequisite
+ recipe
+```
+
+### Final Thoughts
+
+There's a lot more to discover about make, but at least this counts as a start, I strongly encourage you to check the [documentation][4], create a dumb makefile, and just play with it.
+
+--------------------------------------------------------------------------------
+
+via: https://monades.roperzh.com/rediscovering-make-power-behind-rules/
+
+作者:[Roberto Dip][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://monades.roperzh.com
+[1]:https://www.gnu.org/software/make/manual/make.html#Special-Targets
+[2]:https://twitter.com/luislavena/
+[3]:http://tldp.org/HOWTO/Program-Library-HOWTO/static-libraries.html
+[4]:https://www.gnu.org/software/make/manual/make.html
diff --git a/sources/tech/20180118 Securing the Linux filesystem with Tripwire.md b/sources/tech/20180118 Securing the Linux filesystem with Tripwire.md
new file mode 100644
index 0000000000..a359e3a422
--- /dev/null
+++ b/sources/tech/20180118 Securing the Linux filesystem with Tripwire.md
@@ -0,0 +1,112 @@
+Securing the Linux filesystem with Tripwire
+======
+
+
+
+While Linux is considered to be the most secure operating system (ahead of Windows and MacOS), it is still vulnerable to rootkits and other variants of malware. Thus, Linux users need to know how to protect their servers or personal computers from destruction, and the first step they need to take is to protect the filesystem.
+
+In this article, we'll look at [Tripwire][1], an excellent tool for protecting Linux filesystems. Tripwire is an integrity checking tool that enables system administrators, security engineers, and others to detect alterations to system files. Although it's not the only option available ([AIDE][2] and [Samhain][3] offer similar features), Tripwire is arguably the most commonly used integrity checker for Linux system files, and it is available as open source under GPLv2.
+
+### How Tripwire works
+
+It's helpful to know how Tripwire operates in order to understand what it does once it's installed. Tripwire is made up of two major components: policy and database. Policy lists all the files and directories that the integrity checker should take a snapshot of, in addition to creating rules for identifying violations of changes to directories and files. Database consists of the snapshot taken by Tripwire.
+
+Tripwire also has a configuration file, which specifies the locations of the database, policy file, and Tripwire executable. It also provides two cryptographic keys--site key and local key--to protect important files against tampering. The site key protects the policy and configuration files, while the local key protects the database and generated reports.
+
+Tripwire works by periodically comparing the directories and files against the snapshot in the database and reporting any changes.
+
+### Installing Tripwire
+
+In order to use Tripwire, we need to download and install it first. Tripwire works on almost all Linux distributions; you can download an open source version from [Sourceforge][4] and install it as follows, depending on your version of Linux.
+
+Debian and Ubuntu users can install Tripwire directly from the repository using `apt-get`. Non-root users should type the `sudo` command to install Tripwire via `apt-get`.
+```
+
+
+sudo apt-get update
+
+sudo apt-get install tripwire
+```
+
+CentOS and other rpm-based distributions use a similar process. For the sake of best practice, update your repository before installing a new package such as Tripwire. The command `yum install epel-release` simply means we want to install extra repositories. (`epel` stands for Extra Packages for Enterprise Linux.)
+```
+
+
+yum update
+
+yum install epel-release
+
+yum install tripwire
+```
+
+This command causes the installation to run a configuration of packages that are required for Tripwire to function effectively. In addition, it will ask if you want to select passphrases during installation. You can select "Yes" to both prompts.
+
+Also, select or choose "Yes" if it's required to build the configuration file. Choose and confirm a passphrase for a site key and for a local key. (A complex passphrase such as `Il0ve0pens0urce` is recommended.)
+
+### Build and initialize Tripwire's database
+
+Next, initialize the Tripwire database as follows:
+```
+
+
+tripwire --init
+```
+
+You'll need to provide your local key passphrase to run the commands.
+
+### Basic integrity checking using Tripwire
+
+You can use the following command to instruct Tripwire to check whether your files or directories have been modified. Tripwire's ability to compare files and directories against the initial snapshot in the database is based on the rules you created in the active policy.
+```
+
+
+tripwire --check
+```
+
+You can also limit the `-check` command to specific files or directories, such as in this example:
+```
+
+
+tripwire --check /usr/tmp
+```
+
+In addition, if you need extended help on using Tripwire's `-check` command, this command allows you to consult Tripwire's manual:
+```
+
+
+tripwire --check --help
+```
+
+### Generating reports using Tripwire
+
+To easily generate a daily system integrity report, create a `crontab` with this command:
+```
+
+
+crontab -e
+```
+
+Afterward, you can edit this file (with the text editor of your choice) to introduce tasks to be run by cron. For instance, you can set up a cron job to send Tripwire reports to your email daily at 5:40 a.m. by using this command:
+```
+
+
+40 5 * * * usr/sbin/tripwire --check
+```
+
+Whether you decide to use Tripwire or another integrity checker with similar features, the key issue is making sure you have a solution to protect the security of your Linux filesystem.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/securing-linux-filesystem-tripwire
+
+作者:[Michael Kwaku Aboagye][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/revoks
+[1]:https://www.tripwire.com/
+[2]:http://aide.sourceforge.net/
+[3]:http://www.la-samhna.de/samhain/
+[4]:http://sourceforge.net/projects/tripwire
diff --git a/sources/tech/20180119 5 of the Best Linux Dark Themes that Are Easy on the Eyes.md b/sources/tech/20180119 5 of the Best Linux Dark Themes that Are Easy on the Eyes.md
new file mode 100644
index 0000000000..db70cd8732
--- /dev/null
+++ b/sources/tech/20180119 5 of the Best Linux Dark Themes that Are Easy on the Eyes.md
@@ -0,0 +1,73 @@
+5 of the Best Linux Dark Themes that Are Easy on the Eyes
+======
+
+
+
+There are several reasons people opt for dark themes on their computers. Some find them easy on the eye while others prefer them because of their medical condition. Programmers, especially, like dark themes because they reduce glare on the eyes.
+
+If you are a Linux user and a dark theme lover, you are in luck. Here are five of the best dark themes for Linux. Check them out!
+
+### 1. OSX-Arc-Shadow
+
+![OSX-Arc-Shadow Theme][1]
+
+As its name implies, this theme is inspired by OS X. It is a flat theme based on Arc. The theme supports GTK 3 and GTK 2 desktop environments, so Gnome, Cinnamon, Unity, Manjaro, Mate, and XFCE users can install and use the theme. [OSX-Arc-Shadow][2] is part of the OSX-Arc theme collection. The collection has several other themes (dark and light) included. You can download the whole collection and just use the dark variants.
+
+Debian- and Ubuntu-based distro users have the option of installing the stable release using the .deb files found on this [page][3]. The compressed source files are also on the same page. Arch Linux users, check out this [AUR link][4]. Finally, to install the theme manually, extract the zip content to the "~/.themes" folder and set it as your current theme, controls, and window borders.
+
+### 2. Kiss-Kool-Red version 2
+
+![Kiss-Kool-Red version 2 ][5]
+
+The theme is only a few days old. It has a darker look compared to OSX-Arc-Shadow and red selection outlines. It is especially appealing to those who want more contrast and less glare from the computer screen. Hence, It reduces distraction when used at night or in places with low lights. It supports GTK 3 and GTK2.
+
+Head to [gnome-looks][6] to download the theme under the "Files" menu. The installation procedure is simple: extract the theme into the "~/.themes" folder and set it as your current theme, controls, and window borders.
+
+### 3. Equilux
+
+![Equilux][7]
+
+Equilux is another simple dark theme based on Materia Theme. It has a neutral dark color tone and is not overly fancy. The contrast between the selection outlines is also minimal and not as sharp as the red color in Kiss-Kool-Red. The theme is truly made with reduction of eye strain in mind.
+
+[Download the compressed file][8] and unzip it into your "~/.themes" folder. Then, you can set it as your theme. You can check [its GitHub page][9] for the latest additions.
+
+### 4. Deepin Dark
+
+![Deepin Dark][10]
+
+Deepin Dark is a completely dark theme. For those who like a little more darkness, this theme is definitely one to consider. Moreover, it also reduces the amount of glare from the computer screen. Additionally, it supports Unity. [Download Deepin Dark here][11].
+
+### 5. Ambiance DS BlueSB12
+
+![Ambiance DS BlueSB12 ][12]
+
+Ambiance DS BlueSB12 is a simple dark theme, so it makes the important details stand out. It helps with focus as is not unnecessarily fancy. It is very similar to Deepin Dark. Especially relevant to Ubuntu users, it is compatible with Ubuntu 17.04. You can download and try it from [here][13].
+
+### Conclusion
+
+If you use a computer for a very long time, dark themes are a great way to reduce the strain on your eyes. Even if you don't, dark themes can help you in many other ways like improving your focus. Let us know which is your favorite.
+
+--------------------------------------------------------------------------------
+
+via: https://www.maketecheasier.com/best-linux-dark-themes/
+
+作者:[Bruno Edoh][a]
+译者:[译者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
+[1]:https://www.maketecheasier.com/assets/uploads/2017/12/osx-arc-shadow.png (OSX-Arc-Shadow Theme)
+[2]:https://github.com/LinxGem33/OSX-Arc-Shadow/
+[3]:https://github.com/LinxGem33/OSX-Arc-Shadow/releases
+[4]:https://aur.archlinux.org/packages/osx-arc-shadow/
+[5]:https://www.maketecheasier.com/assets/uploads/2017/12/Kiss-Kool-Red.png (Kiss-Kool-Red version 2 )
+[6]:https://www.gnome-look.org/p/1207964/
+[7]:https://www.maketecheasier.com/assets/uploads/2017/12/equilux.png (Equilux)
+[8]:https://www.gnome-look.org/p/1182169/
+[9]:https://github.com/ddnexus/equilux-theme
+[10]:https://www.maketecheasier.com/assets/uploads/2017/12/deepin-dark.png (Deepin Dark )
+[11]:https://www.gnome-look.org/p/1190867/
+[12]:https://www.maketecheasier.com/assets/uploads/2017/12/ambience.png (Ambiance DS BlueSB12 )
+[13]:https://www.gnome-look.org/p/1013664/
diff --git a/sources/tech/20180119 How to Install Tripwire IDS Intrusion Detection System on Linux.md b/sources/tech/20180119 How to Install Tripwire IDS Intrusion Detection System on Linux.md
new file mode 100644
index 0000000000..fb994b7f54
--- /dev/null
+++ b/sources/tech/20180119 How to Install Tripwire IDS Intrusion Detection System on Linux.md
@@ -0,0 +1,102 @@
+How to Install Tripwire IDS (Intrusion Detection System) on Linux
+============================================================
+
+
+Tripwire is a popular Linux Intrusion Detection System (IDS) that runs on systems in order to detect if unauthorized filesystem changes occurred over time.
+
+In CentOS and RHEL distributions, tripwire is not a part of official repositories. However, the tripwire package can be installed via [Epel repositories][1].
+
+To begin, first install Epel repositories in CentOS and RHEL system, by issuing the below command.
+
+```
+# yum install epel-release
+```
+
+After you’ve installed Epel repositories, make sure you update the system with the following command.
+
+```
+# yum update
+```
+
+After the update process finishes, install Tripwire IDS software by executing the below command.
+
+```
+# yum install tripwire
+```
+
+Fortunately, tripwire is a part of Ubuntu and Debian default repositories and can be installed with following commands.
+
+```
+$ sudo apt update
+$ sudo apt install tripwire
+```
+
+On Ubuntu and Debian, the tripwire installation will be asked to choose and confirm a site key and local key passphrase. These keys are used by tripwire to secure its configuration files.
+
+ [][2]
+
+Create Tripwire Site and Local Key
+
+On CentOS and RHEL, you need to create tripwire keys with the below command and supply a passphrase for site key and local key.
+
+```
+# tripwire-setup-keyfiles
+```
+ [][3]
+
+Create Tripwire Keys
+
+In order to validate your system, you need to initialize Tripwire database with the following command. Due to the fact that the database hasn’t been initialized yet, tripwire will display a lot of false-positive warnings.
+
+```
+# tripwire --init
+```
+ [][4]
+
+Initialize Tripwire Database
+
+Finally, generate a tripwire system report in order to check the configurations by issuing the below command. Use `--help` switch to list all tripwire check command options.
+
+```
+# tripwire --check --help
+# tripwire --check
+```
+
+After tripwire check command completes, review the report by opening the file with the extension `.twr` from /var/lib/tripwire/report/ directory with your favorite text editor command, but before that you need to convert to text file.
+
+```
+# twprint --print-report --twrfile /var/lib/tripwire/report/tecmint-20170727-235255.twr > report.txt
+# vi report.txt
+```
+ [][5]
+
+Tripwire System Report
+
+That’s It! you have successfully installed Tripwire on Linux server. I hope you can now easily configure your [Tripwire IDS][6].
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+I'am a computer addicted guy, a fan of open source and linux based system software, have about 4 years experience with Linux distributions desktop, servers and bash scripting.
+
+-------
+
+via: https://www.tecmint.com/install-tripwire-ids-intrusion-detection-system-on-linux/
+
+作者:[ Matei Cezar][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.tecmint.com/author/cezarmatei/
+[1]:https://www.tecmint.com/how-to-enable-epel-repository-for-rhel-centos-6-5/
+[2]:https://www.tecmint.com/wp-content/uploads/2018/01/Create-Site-and-Local-key.png
+[3]:https://www.tecmint.com/wp-content/uploads/2018/01/Create-Tripwire-Keys.png
+[4]:https://www.tecmint.com/wp-content/uploads/2018/01/Initialize-Tripwire-Database.png
+[5]:https://www.tecmint.com/wp-content/uploads/2018/01/Tripwire-System-Report.png
+[6]:https://www.tripwire.com/
+[7]:https://www.tecmint.com/author/cezarmatei/
+[8]:https://www.tecmint.com/10-useful-free-linux-ebooks-for-newbies-and-administrators/
+[9]:https://www.tecmint.com/free-linux-shell-scripting-books/
\ No newline at end of file
diff --git a/sources/tech/20180119 Linux mv Command Explained for Beginners (8 Examples).md b/sources/tech/20180119 Linux mv Command Explained for Beginners (8 Examples).md
new file mode 100644
index 0000000000..78cf02f4a9
--- /dev/null
+++ b/sources/tech/20180119 Linux mv Command Explained for Beginners (8 Examples).md
@@ -0,0 +1,188 @@
+translating by cncuckoo
+
+Linux mv Command Explained for Beginners (8 Examples)
+======
+
+Just like [cp][1] for copying and rm for deleting, Linux also offers an in-built command for moving and renaming files. It's called **mv**. In this article, we will discuss the basics of this command line tool using easy to understand examples. Please note that all examples used in this tutorial have been tested on Ubuntu 16.04 LTS.
+
+#### Linux mv command
+
+As already mentioned, the mv command in Linux is used to move or rename files. Following is the syntax of the command:
+
+```
+mv [OPTION]... [-T] SOURCE DEST
+mv [OPTION]... SOURCE... DIRECTORY
+mv [OPTION]... -t DIRECTORY SOURCE...
+```
+
+And here's what the man page says about it:
+```
+Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.
+```
+
+The following Q&A-styled examples will give you a better idea on how this tool works.
+
+#### Q1. How to use mv command in Linux?
+
+If you want to just rename a file, you can use the mv command in the following way:
+
+```
+mv [filename] [new_filename]
+```
+
+For example:
+
+```
+mv names.txt fullnames.txt
+```
+
+[![How to use mv command in Linux][2]][3]
+
+Similarly, if the requirement is to move a file to a new location, use the mv command in the following way:
+
+```
+mv [filename] [dest-dir]
+```
+
+For example:
+
+```
+mv fullnames.txt /home/himanshu/Downloads
+```
+
+[![Linux mv command][4]][5]
+
+#### Q2. How to make sure mv prompts before overwriting?
+
+By default, the mv command doesn't prompt when the operation involves overwriting an existing file. For example, the following screenshot shows the existing full_names.txt was overwritten by mv without any warning or notification.
+
+[![How to make sure mv prompts before overwriting][6]][7]
+
+However, if you want, you can force mv to prompt by using the **-i** command line option.
+
+```
+mv -i [file_name] [new_file_name]
+```
+
+[![the -i command option][8]][9]
+
+So the above screenshots clearly shows that **-i** leads to mv asking for user permission before overwriting an existing file. Please note that in case you want to explicitly specify that you don't want mv to prompt before overwriting, then use the **-f** command line option.
+
+#### Q3. How to make mv not overwrite an existing file?
+
+For this, you need to use the **-n** command line option.
+
+```
+mv -n [filename] [new_filename]
+```
+
+The following screenshot shows the mv operation wasn't successful as a file with name 'full_names.txt' already existed and the command had -n option in it.
+
+[![How to make mv not overwrite an existing file][10]][11]
+
+Note:
+```
+If you specify more than one of -i, -f, -n, only the final one takes effect.
+```
+
+#### Q4. How to make mv remove trailing slashes (if any) from source argument?
+
+To remove any trailing slashes from source arguments, use the **\--strip-trailing-slashes** command line option.
+
+```
+mv --strip-trailing-slashes [source] [dest]
+```
+
+Here's how the official documentation explains the usefulness of this option:
+```
+This is useful when a
+
+source
+
+ argument may have a trailing slash and specify a symbolic link to a directory. This scenario is in fact rather common because some shells can automatically append a trailing slash when performing file name completion on such symbolic links. Without this option,
+
+mv
+
+, for example, (via the system's rename function) must interpret a trailing slash as a request to dereference the symbolic link and so must rename the indirectly referenced
+
+directory
+
+ and not the symbolic link. Although it may seem surprising that such behavior be the default, it is required by POSIX and is consistent with other parts of that standard.
+```
+
+#### Q5. How to make mv treat destination as normal file?
+
+To be absolutely sure that the destination entity is treated as a normal file (and not a directory), use the **-T** command line option.
+
+```
+mv -T [source] [dest]
+```
+
+Here's why this command line option exists:
+```
+This can help avoid race conditions in programs that operate in a shared area. For example, when the command 'mv /tmp/source /tmp/dest' succeeds, there is no guarantee that /tmp/source was renamed to /tmp/dest: it could have been renamed to/tmp/dest/source instead, if some other process created /tmp/dest as a directory. However, if mv -T /tmp/source /tmp/dest succeeds, there is no question that/tmp/source was renamed to /tmp/dest.
+```
+```
+In the opposite situation, where you want the last operand to be treated as a directory and want a diagnostic otherwise, you can use the --target-directory (-t) option.
+```
+
+#### Q6. How to make mv move file only when its newer than destination file?
+
+Suppose there exists a file named fullnames.txt in Downloads directory of your system, and there's a file with same name in your home directory. Now, you want to update ~/Downloads/fullnames.txt with ~/fullnames.txt, but only when the latter is newer. Then in this case, you'll have to use the **-u** command line option.
+
+```
+mv -u ~/fullnames.txt ~/Downloads/fullnames.txt
+```
+
+This option is particularly useful in cases when you need to take such decisions from within a shell script.
+
+#### Q7. How make mv emit details of what all it is doing?
+
+If you want mv to output information explaining what exactly it's doing, then use the **-v** command line option.
+
+```
+mv -v [filename] [new_filename]
+```
+
+For example, the following screenshots shows mv emitting some helpful details of what exactly it did.
+
+[![How make mv emit details of what all it is doing][12]][13]
+
+#### Q8. How to force mv to create backup of existing destination files?
+
+This you can do using the **-b** command line option. The backup file created this way will have the same name as the destination file, but with a tilde (~) appended to it. Here's an example:
+
+[![How to force mv to create backup of existing destination files][14]][15]
+
+#### Conclusion
+
+As you'd have guessed by now, mv is as important as cp and rm for the functionality it offers - renaming/moving files around is also one of the basic operations after all. We've discussed a majority of command line options this tool offers. So you can just practice them and start using the command. To know more about mv, head to its [man page][16].
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.howtoforge.com/linux-mv-command/
+
+作者:[Himanshu Arora][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.howtoforge.com
+[1]:https://www.howtoforge.com/linux-cp-command/
+[2]:https://www.howtoforge.com/images/command-tutorial/mv-rename-ex.png
+[3]:https://www.howtoforge.com/images/command-tutorial/big/mv-rename-ex.png
+[4]:https://www.howtoforge.com/images/command-tutorial/mv-transfer-file.png
+[5]:https://www.howtoforge.com/images/command-tutorial/big/mv-transfer-file.png
+[6]:https://www.howtoforge.com/images/command-tutorial/mv-overwrite.png
+[7]:https://www.howtoforge.com/images/command-tutorial/big/mv-overwrite.png
+[8]:https://www.howtoforge.com/images/command-tutorial/mv-prompt-overwrite.png
+[9]:https://www.howtoforge.com/images/command-tutorial/big/mv-prompt-overwrite.png
+[10]:https://www.howtoforge.com/images/command-tutorial/mv-n-option.png
+[11]:https://www.howtoforge.com/images/command-tutorial/big/mv-n-option.png
+[12]:https://www.howtoforge.com/images/command-tutorial/mv-v-option.png
+[13]:https://www.howtoforge.com/images/command-tutorial/big/mv-v-option.png
+[14]:https://www.howtoforge.com/images/command-tutorial/mv-b-option.png
+[15]:https://www.howtoforge.com/images/command-tutorial/big/mv-b-option.png
+[16]:https://linux.die.net/man/1/mv
diff --git a/sources/tech/20180119 PlayOnLinux For Easier Use Of Wine.md b/sources/tech/20180119 PlayOnLinux For Easier Use Of Wine.md
new file mode 100644
index 0000000000..2af3433920
--- /dev/null
+++ b/sources/tech/20180119 PlayOnLinux For Easier Use Of Wine.md
@@ -0,0 +1,153 @@
+PlayOnLinux For Easier Use Of Wine
+======
+
+
+
+[PlayOnLinux][1] is a free program that helps to install, run, and manage Windows software on Linux. It can also manage virtual C: drives (known as Wine prefixes), and download and install certain Windows libraries for getting some software to run on Wine properly. Creating different drives using different Wine versions is also possible. It is very handy because what runs well in one version may not run as well (if at all) on a newer version. There is [PlayOnMac][2] for macOS and PlayOnBSD for FreeBSD.
+
+[Wine][3] is the compatibility layer that allows many programs developed for Windows to run under operating systems such as Linux, FreeBSD, macOS and other UNIX systems. The app database ([AppDB][4]) gives users an overview of a multitude of programs that will function on Wine, however successfully.
+
+Both programs can be obtained using your distribution’s software center or package manager for convenience.
+
+### Installing Programs Using PlayOnLinux
+
+Installing software is easy. PlayOnLinux has hundreds of scripts to aid in installing different software with which to run the setup. In the sidebar, select “Install Software”. You will find several categories to choose from.
+
+
+
+Hundreds of games can be installed this way.
+
+ [][5]
+
+Office software can be installed as well, including Microsoft Office as shown here.
+
+ [][6]
+
+Let’s install Notepad++ using the script. You can select the script to read the compatibility rating according to PlayOnLinux, and an overview of the program. To get a better idea of compatibility, refer to the WineHQ App Database and find “Browse Apps” to find a program like Notepad++.
+
+ [][7]
+
+Once you press “Install”, if you are using PlayOnLinux for the first time, you will encounter two popups: one to give you tips when installing programs with a script, and the other to not submit bug reports to WineHQ because PlayOnLinux has nothing to do with them.
+
+
+
+During the installation, I was given the choice to either download the setup executable, or select one on the computer. I downloaded the file but received a File Mismatch error; however, I continued and it was successful. It’s not perfect, but it is functional. (It is possible to submit bug reports to PlayOnLinux if the option is given.)
+
+[][8]
+
+Nevertheless, I was able to install Notepad++ successfully, run it, and update it to the latest version (at the time of writing 7.5.3) from version 7.4.2.
+
+
+
+Also during installation, it created a virtual C: drive specifically for Notepad++. As there are no other Wine versions available for PlayOnLinux to use, it defaults to using the version installed on the system. In this case, it is more than adequate for Notepad++ to run smoothly.
+
+### Installing Non-Listed Programs
+
+You can also install a program that is not on the list by pressing “Install Non-Listed Program” on the bottom-left corner of the install menu. Bear in mind that there is no script to install certain libraries to make things work properly. You will need to do this yourself. Look at the Wine AppDB for information for your program. Also, if the app isn’t listed, it doesn’t mean that it won’t work with Wine. It just means no one has given any information about it.
+
+
+
+I’ve installed Graphmatica, a graph plotting program, using this method. First I selected the option to install it on a new virtual drive.
+
+ [][9]
+
+Then I selected the option to install additional libraries after creating the drive and select a Wine version to use in doing so.
+
+ [][10]
+
+I then proceeded to select Gecko (which encountered an error for some reason), and Mono 2.10 to install.
+
+ [][11]
+
+Finally, I installed Graphmatica. It’s as simple as that.
+
+ [][12]
+
+A launcher can be created after installation. A list of executables found in the drive will appear. Search for the app executable (may not always be obvious) which may have its icon, select it and give it a display name. The icon will appear on the desktop.
+
+ [][13]
+ [][14]
+
+### Multiple “C:” Drives
+
+Now that we have easily installed a program, let’s have a look at the drive configuration. In the main window, press “Configure” in the toolbar and this window will show.
+
+ [][15]
+
+On the left are the drives that are found within PlayOnLinux. To the right, the “General” tab allows you to create shortcuts of programs installed on that virtual drive.
+
+
+
+The “Wine” tab has 8 buttons, including those to launch the Wine configuration program (winecfg), control panel, registry editor, command prompt, etc.
+
+ [][16]
+
+“Install Components” allows you to select different Windows libraries like DirectX 9, .NET Framework versions 2 – 4.5, Visual C++ runtime, etc., like [winetricks][17].
+
+ [][18]
+
+“Display” allows the user to control advanced graphics settings like GLSL support, video memory size, and more. And “Miscellaneous” is for other actions like running an executable found anywhere on the computer to be run under the selected virtual drive.
+
+### Creating Virtual Drives Without Installing Programs
+
+To create a drive without installing software, simply press “New” below the list of drives to launch the virtual drive creator. Drives are created using the same method used in installing programs not found in the install menu. Follow the prompts, select either a 32-bit or 64-bit installation (in this case we only have 32-bit versions so select 32-bit), choose the Wine version, and give the drive a name. Once completed, it will appear in the drive list.
+
+ [][19]
+
+### Managing Wine Versions
+
+Entire Wine versions can be downloaded using the manager. To access this through the menu bar, press “Tools” and select “Manage Wine versions”. Sometimes different software can behave differently between Wine versions. A Wine update can break something that made your application work in the previous version; thus rendering the application broken or completely unusable. Therefore, this feature is one of the highlights of PlayOnLinux.
+
+
+
+If you’re still on the configuration window, in the “General” tab, you can also access the version manager by pressing the “+” button next to the Wine version field.
+
+ [][20]
+
+To install a version of Wine (32-bit or 64-bit), simply select the version, and press the “>” button to download and install it. After installation, if setup executables for Mono, and/or the Gecko HTML engine have not yet been downloaded by PlayOnLinux, they will be downloaded.
+
+
+
+I went ahead and installed the 2.21-staging version of Wine afterward.
+
+ [][21]
+
+To remove a version, press the “<” button.
+
+### Conclusion
+
+This article demonstrated how to use PlayOnLinux to easily install Windows software into separate virtual C: drives, create and manage virtual drives, and manage several Wine versions. The software isn’t perfect, but it is still functional and useful. Managing different drives with different Wine versions is one of the key features of PlayOnLinux. It is a lot easier to use a front-end for Wine such as PlayOnLinux than pure Wine.
+
+
+--------------------------------------------------------------------------------
+
+via: http://www.linuxandubuntu.com/home/playonlinux-for-easier-use-of-wine
+
+作者:[LinuxAndUbuntu][a]
+译者:[译者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]:https://www.playonlinux.com/en/
+[2]:https://www.playonmac.com
+[3]:https://www.winehq.org/
+[4]:http://appdb.winehq.org/
+[5]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_orig.png
+[6]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_1_orig.png
+[7]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_2_orig.png
+[8]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_3_orig.png
+[9]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_4_orig.png
+[10]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_5_orig.png
+[11]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_6_orig.png
+[12]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_7_orig.png
+[13]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_8_orig.png
+[14]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_9_orig.png
+[15]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_10_orig.png
+[16]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_11_orig.png
+[17]:https://github.com/Winetricks/winetricks
+[18]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_12_orig.png
+[19]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_13_orig.png
+[20]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_14_orig.png
+[21]:http://www.linuxandubuntu.com/uploads/2/1/1/5/21152474/playonlinux_15_orig.png
diff --git a/sources/tech/20180119 Two great uses for the cp command Bash shortcuts.md b/sources/tech/20180119 Two great uses for the cp command Bash shortcuts.md
new file mode 100644
index 0000000000..9a45c26e7a
--- /dev/null
+++ b/sources/tech/20180119 Two great uses for the cp command Bash shortcuts.md
@@ -0,0 +1,154 @@
+Translating by cncuckoo
+
+Two great uses for the cp command: Bash shortcuts
+============================================================
+
+### Here's how to streamline the backup and synchronize functions of the cp command.
+
+
+
+>Image by : [Internet Archive Book Images][6]. Modified by Opensource.com. CC BY-SA 4.0
+
+Last July, I wrote about [two great uses for the cp command][7]: making a backup of a file, and synchronizing a secondary copy of a folder.
+
+Having discovered these great utilities, I find that they are more verbose than necessary, so I created shortcuts to them in my Bash shell startup script. I thought I’d share these shortcuts in case they are useful to others or could offer inspiration to Bash users who haven’t quite taken on aliases or shell functions.
+
+### Updating a second copy of a folder – Bash alias
+
+The general pattern for updating a second copy of a folder with cp is:
+
+```
+cp -r -u -v SOURCE-FOLDER DESTINATION-DIRECTORY
+```
+
+I can easily remember the -r option because I use it often when copying folders around. I can probably, with some more effort, remember -v, and with even more effort, -u (is it “update” or “synchronize” or…).
+
+Or I can just use the [alias capability in Bash][8] to convert the cp command and options to something more memorable, like this:
+
+```
+alias sync='cp -r -u -v'
+```
+
+```
+sync Pictures /media/me/4388-E5FE
+```
+
+Not sure if you already have a sync alias defined? You can list all your currently defined aliases by typing the word alias at the command prompt in your terminal window.
+
+Like this so much you just want to start using it right away? Open a terminal window and type:
+
+```
+echo "alias sync='cp -r -u -v'" >> ~/.bash_aliases
+```
+
+```
+me@mymachine~$ alias
+
+alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
+
+alias egrep='egrep --color=auto'
+
+alias fgrep='fgrep --color=auto'
+
+alias grep='grep --color=auto'
+
+alias gvm='sdk'
+
+alias l='ls -CF'
+
+alias la='ls -A'
+
+alias ll='ls -alF'
+
+alias ls='ls --color=auto'
+
+alias sync='cp -r -u -v'
+
+me@mymachine:~$
+```
+
+### Making versioned backups – Bash function
+
+The general pattern for making a backup of a file with cp is:
+
+```
+cp --force --backup=numbered WORKING-FILE BACKED-UP-FILE
+```
+
+Besides remembering the options to the cp command, we also need to remember to repeat the WORKING-FILE name a second time. But why repeat ourselves when [a Bash function][9] can take care of that overhead for us, like this:
+
+Again, you can save this to your .bash_aliases file in your home directory.
+
+```
+function backup {
+
+ if [ $# -ne 1 ]; then
+
+ echo "Usage: $0 filename"
+
+ elif [ -f $1 ] ; then
+
+ echo "cp --force --backup=numbered $1 $1"
+
+ cp --force --backup=numbered $1 $1
+
+ else
+
+ echo "$0: $1 is not a file"
+
+ fi
+
+}
+```
+
+The first if statement checks to make sure that only one argument is provided to the function, otherwise printing the correct usage with the echo command.
+
+The elif statement checks to make sure the argument provided is a file, and if so, it (verbosely) uses the second echo to print the cp command to be used and then executes it.
+
+If the single argument is not a file, the third echo prints an error message to that effect.
+
+In my home directory, if I execute the backup command so defined on the file checkCounts.sql, I see that backup creates a file called checkCounts.sql.~1~. If I execute it once more, I see a new file checkCounts.sql.~2~.
+
+Success! As planned, I can go on editing checkCounts.sql, but if I take a snapshot of it every so often with backup, I can return to the most recent snapshot should I run into trouble.
+
+At some point, it’s better to start using git for version control, but backup as defined above is a nice cheap tool when you need to create snapshots but you’re not ready for git.
+
+### Conclusion
+
+In my last article, I promised you that repetitive tasks can often be easily streamlined through the use of shell scripts, shell functions, and shell aliases.
+
+Here I’ve shown concrete examples of the use of shell aliases and shell functions to streamline the synchronize and backup functionality of the cp command. If you’d like to learn more about this, check out the two articles cited above: [How to save keystrokes at the command line with alias][10] and [Shell scripting: An introduction to the shift method and custom functions][11], written by my colleagues Greg and Seth, respectively.
+
+
+### About the author
+
+ [][13] Chris Hermansen
+
+
+ Engaged in computing since graduating from the University of British Columbia in 1978, I have been a full-time Linux user since 2005 and a full-time Solaris, SunOS and UNIX System V user before that. On the technical side of things, I have spent a great deal of my career doing data analysis; especially spatial data analysis. I have a substantial amount of programming experience in relation to data analysis, using awk, Python, PostgreSQL, PostGIS and lately Groovy. I have also built a few... [more about Chris Hermansen][14]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/two-great-uses-cp-command-update
+
+作者:[Chris Hermansen][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/clhermansen
+[1]:https://opensource.com/users/clhermansen
+[2]:https://opensource.com/users/clhermansen
+[3]:https://opensource.com/user/37806/feed
+[4]:https://opensource.com/article/18/1/two-great-uses-cp-command-update?rate=J_7R7wSPbukG9y8jrqZt3EqANfYtVAwZzzpopYiH3C8
+[5]:https://opensource.com/article/18/1/two-great-uses-cp-command-update#comments
+[6]:https://www.flickr.com/photos/internetarchivebookimages/14803082483/in/photolist-oy6EG4-pZR3NZ-i6r3NW-e1tJSX-boBtf7-oeYc7U-o6jFKK-9jNtc3-idt2G9-i7NG1m-ouKjXe-owqviF-92xFBg-ow9e4s-gVVXJN-i1K8Pw-4jybMo-i1rsBr-ouo58Y-ouPRzz-8cGJHK-85Evdk-cru4Ly-rcDWiP-gnaC5B-pAFsuf-hRFPcZ-odvBMz-hRCE7b-mZN3Kt-odHU5a-73dpPp-hUaaAi-owvUMK-otbp7Q-ouySkB-hYAgmJ-owo4UZ-giHgqu-giHpNc-idd9uQ-osAhcf-7vxk63-7vwN65-fQejmk-pTcLgA-otZcmj-fj1aSX-hRzHQk-oyeZfR
+[7]:https://opensource.com/article/17/7/two-great-uses-cp-command
+[8]:https://opensource.com/article/17/5/introduction-alias-command-line-tool
+[9]:https://opensource.com/article/17/1/shell-scripting-shift-method-custom-functions
+[10]:https://opensource.com/article/17/5/introduction-alias-command-line-tool
+[11]:https://opensource.com/article/17/1/shell-scripting-shift-method-custom-functions
+[12]:https://opensource.com/tags/linux
+[13]:https://opensource.com/users/clhermansen
+[14]:https://opensource.com/users/clhermansen
diff --git a/sources/tech/20180120 socat as a handler for multiple reverse shells - System Overlord.md b/sources/tech/20180120 socat as a handler for multiple reverse shells - System Overlord.md
new file mode 100644
index 0000000000..b57a1e0140
--- /dev/null
+++ b/sources/tech/20180120 socat as a handler for multiple reverse shells - System Overlord.md
@@ -0,0 +1,66 @@
+socat as a handler for multiple reverse shells · System Overlord
+======
+
+I was looking for a new way to handle multiple incoming reverse shells. My shells needed to be encrypted and I preferred not to use Metasploit in this case. Because of the way I was deploying my implants, I wasn't able to use separate incoming port numbers or other ways of directing the traffic to multiple listeners.
+
+Obviously, it's important to keep each reverse shell separated, so I couldn't just have a listener redirecting all the connections to STDIN/STDOUT. I also didn't want to wait for sessions serially - obviously I wanted to be connected to all of my implants simultaneously. (And allow them to disconnect/reconnect as needed due to loss of network connectivity.)
+
+As I was thinking about the problem, I realized that I basically wanted `tmux` for reverse shells. So I began to wonder if there was some way to connect `openssl s_server` or something similar to `tmux`. Given the limitations of `s_server`, I started looking at `socat`. Despite it's versatility, I've actually only used it once or twice before this, so I spent a fair bit of time reading the man page and the examples.
+
+I couldn't find a way to get `socat` to talk directly to `tmux` in a way that would spawn each connection as a new window (file descriptors are not passed to the newly-started process in `tmux new-window`), so I ended up with a strange workaround. I feel a little bit like Rube Goldberg inventing C2 software (and I need to get something more permanent and featureful eventually, but this was a quick and dirty PoC), but I've put together a chain of `socat` to get a working solution.
+
+My implementation works by having a single `socat` process receive the incoming connections (forking on incoming connection), and executing a script that first starts a `socat` instance within tmux, and then another `socat` process to copy from the first to the second over a UNIX domain socket.
+
+Yes, this is 3 socat processes. It's a little ridiculous, but I couldn't find a better approach. Roughly speaking, the communications flow looks a little like this:
+```
+TLS data <--> socat listener <--> script stdio <--> socat <--> unix socket <--> socat in tmux <--> terminal window
+
+```
+
+Getting it started is fairly simple. Begin by generating your SSL certificate. In this case, I'm using a self-signed certificate, but obviously you could go through a commercial CA, Let's Encrypt, etc.
+```
+openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 30 -out server.crt
+cat server.key server.crt > server.pem
+
+```
+
+Now we will create the script that is run on each incoming connection. This script needs to launch a `tmux` window running a `socat` process copying from a UNIX domain socket to `stdio` (in tmux), and then connecting another `socat` between the `stdio` coming in to the UNIX domain socket.
+```
+#!/bin/bash
+
+SOCKDIR=$(mktemp -d)
+SOCKF=${SOCKDIR}/usock
+
+# Start tmux, if needed
+tmux start
+# Create window
+tmux new-window "socat UNIX-LISTEN:${SOCKF},umask=0077 STDIO"
+# Wait for socket
+while test ! -e ${SOCKF} ; do sleep 1 ; done
+# Use socat to ship data between the unix socket and STDIO.
+exec socat STDIO UNIX-CONNECT:${SOCKF}
+```
+
+The while loop is necessary to make sure that the last `socat` process does not attempt to open the UNIX domain socket before it has been created by the new `tmux` child process.
+
+Finally, we can launch the `socat` process that will accept the incoming requests (handling all the TLS steps) and execute our per-connection script:
+```
+socat OPENSSL-LISTEN:8443,cert=server.pem,reuseaddr,verify=0,fork EXEC:./socatscript.sh
+
+```
+
+This listens on port 8443, using the certificate and private key contained in `server.pem`, performs a `fork()` on accepting each incoming connection (so they do not block each other) and disables certificate verification (since we're not expecting our clients to provide a certificate). On the other side, it launches our script, providing the data from the TLS connection via STDIO.
+
+At this point, an incoming TLS connection connects, and is passed through our processes to eventually arrive on the `STDIO` of a new window in the running `tmux` server. Each connection gets its own window, allowing us to easily see and manage the connections for our implants.
+
+--------------------------------------------------------------------------------
+
+via: https://systemoverlord.com/2018/01/20/socat-as-a-handler-for-multiple-reverse-shells.html
+
+作者:[David][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://systemoverlord.com/about
diff --git a/sources/tech/20180122 A Simple Command-line Snippet Manager.md b/sources/tech/20180122 A Simple Command-line Snippet Manager.md
new file mode 100644
index 0000000000..1c8ef14fb6
--- /dev/null
+++ b/sources/tech/20180122 A Simple Command-line Snippet Manager.md
@@ -0,0 +1,319 @@
+A Simple Command-line Snippet Manager
+======
+
+
+
+We can't remember all the commands, right? Yes. Except the frequently used commands, it is nearly impossible to remember some long commands that we rarely use. That's why we need to some external tools to help us to find the commands when we need them. In the past, we have reviewed two useful utilities named [**" Bashpast"**][1] and [**" Keep"**][2]. Using Bashpast, we can easily bookmark the Linux commands for easier repeated invocation. And, the Keep utility can be used to keep the some important and lengthy commands in your Terminal, so you can use them on demand. Today, we are going to see yet another tool in the series to help you remembering commands. Say hello to **" Pet"**, a simple command-line snippet manager written in **Go** language.
+
+Using Pet, you can;
+
+ * Register/add your important, long and complex command snippets.
+ * Search the saved command snippets interactively.
+ * Run snippets directly without having to type over and over.
+ * Edit the saved command snippets easily.
+ * Sync the snippets via Gist.
+ * Use variables in snippets.
+ * And more yet to come.
+
+
+
+#### Installing Pet CLI Snippet Manager
+
+Since it is written in Go language, make sure you have installed Go in your system.
+
+After Go language, grab the latest binaries from [**the releases page**][3].
+```
+wget https://github.com/knqyf263/pet/releases/download/v0.2.4/pet_0.2.4_linux_amd64.zip
+```
+
+For 32 bit:
+```
+wget https://github.com/knqyf263/pet/releases/download/v0.2.4/pet_0.2.4_linux_386.zip
+```
+
+Extract the downloaded archive:
+```
+unzip pet_0.2.4_linux_amd64.zip
+```
+
+32 bit:
+```
+unzip pet_0.2.4_linux_386.zip
+```
+
+Copy the pet binary file to your PATH (i.e **/usr/local/bin** or the like).
+```
+sudo cp pet /usr/local/bin/
+```
+
+Finally, make it executable:
+```
+sudo chmod +x /usr/local/bin/pet
+```
+
+If you're using Arch based systems, then you can install it from AUR using any AUR helper tools.
+
+Using [**Pacaur**][4]:
+```
+pacaur -S pet-git
+```
+
+Using [**Packer**][5]:
+```
+packer -S pet-git
+```
+
+Using [**Yaourt**][6]:
+```
+yaourt -S pet-git
+```
+
+Using [**Yay** :][7]
+```
+yay -S pet-git
+```
+
+Also, you need to install **[fzf][8]** or [**peco**][9] tools to enable interactive search. Refer the official GitHub links to know how to install these tools.
+
+#### Usage
+
+Run 'pet' without any arguments to view the list of available commands and general options.
+```
+$ pet
+pet - Simple command-line snippet manager.
+
+Usage:
+ pet [command]
+
+Available Commands:
+ configure Edit config file
+ edit Edit snippet file
+ exec Run the selected commands
+ help Help about any command
+ list Show all snippets
+ new Create a new snippet
+ search Search snippets
+ sync Sync snippets
+ version Print the version number
+
+Flags:
+ --config string config file (default is $HOME/.config/pet/config.toml)
+ --debug debug mode
+ -h, --help help for pet
+
+Use "pet [command] --help" for more information about a command.
+```
+
+To view the help section of a specific command, run:
+```
+$ pet [command] --help
+```
+
+**Configure Pet**
+
+It just works fine with default values. However, you can change the default directory to save snippets, choose the selector (fzf or peco) to use, the default text editor to edit snippets, add GIST id details etc.
+
+To configure Pet, run:
+```
+$ pet configure
+```
+
+This command will open the default configuration in the default text editor (for example **vim** in my case). Change/edit the values as per your requirements.
+```
+[General]
+ snippetfile = "/home/sk/.config/pet/snippet.toml"
+ editor = "vim"
+ column = 40
+ selectcmd = "fzf"
+
+[Gist]
+ file_name = "pet-snippet.toml"
+ access_token = ""
+ gist_id = ""
+ public = false
+~
+```
+
+**Creating Snippets**
+
+To create a new snippet, run:
+```
+$ pet new
+```
+
+Add the command and the description and hit ENTER to save it.
+```
+Command> echo 'Hell1o, Welcome1 2to OSTechNix4' | tr -d '1-9'
+Description> Remove numbers from output.
+```
+
+[![][10]][11]
+
+This is a simple command to remove all numbers from the echo command output. You can easily remember it. But, if you rarely use it, you may forgot it completely after few days. Of course we can search the history using "CTRL+r", but "Pet" is much easier. Also, Pet can help you to add any number of entries.
+
+Another cool feature is we can easily add the previous command. To do so, add the following lines in your **.bashrc** or **.zshrc** file.
+```
+function prev() {
+ PREV=$(fc -lrn | head -n 1)
+ sh -c "pet new `printf %q "$PREV"`"
+}
+```
+
+Do the following command to take effect the saved changes.
+```
+source .bashrc
+```
+
+Or,
+```
+source .zshrc
+```
+
+Now, run any command, for example:
+```
+$ cat Documents/ostechnix.txt | tr '|' '\n' | sort | tr '\n' '|' | sed "s/.$/\\n/g"
+```
+
+To add the above command, you don't have to use "pet new" command. just do:
+```
+$ prev
+```
+
+Add the description to the command snippet and hit ENTER to save.
+
+[![][10]][12]
+
+**List snippets**
+
+To view the saved snippets, run:
+```
+$ pet list
+```
+
+[![][10]][13]
+
+**Edit Snippets**
+
+If you want to edit the description or the command of a snippet, run:
+```
+$ pet edit
+```
+
+This will open all saved snippets in your default text editor. You can edit or change the snippets as you wish.
+```
+[[snippets]]
+ description = "Remove numbers from output."
+ command = "echo 'Hell1o, Welcome1 2to OSTechNix4' | tr -d '1-9'"
+ output = ""
+
+[[snippets]]
+ description = "Alphabetically sort one line of text"
+ command = "\t prev"
+ output = ""
+```
+
+**Use Tags in snippets**
+
+To use tags to a snippet, use **-t** flag like below.
+```
+$ pet new -t
+Command> echo 'Hell1o, Welcome1 2to OSTechNix4' | tr -d '1-9
+Description> Remove numbers from output.
+Tag> tr command examples
+
+```
+
+**Execute Snippets**
+
+To execute a saved snippet, run:
+```
+$ pet exec
+```
+
+Choose the snippet you want to run from the list and hit ENTER to run it.
+
+[![][10]][14]
+
+Remember you need to install fzf or peco to use this feature.
+
+**Search Snippets**
+
+If you have plenty of saved snippets, you can easily search them using a string or key word like below.
+```
+$ pet search
+```
+
+Enter the search term or keyword to narrow down the search results.
+
+[![][10]][15]
+
+**Sync Snippets**
+
+First, you need to obtain the access token. Go to this link and create access token (only need "gist" scope).
+
+Configure Pet using command:
+```
+$ pet configure
+```
+
+Set that token to **access_token** in **[Gist]** field.
+
+After setting, you can upload snippets to Gist like below.
+```
+$ pet sync -u
+Gist ID: 2dfeeeg5f17e1170bf0c5612fb31a869
+Upload success
+
+```
+
+You can also download snippets on another PC. To do so, edit configuration file and set **Gist ID** to **gist_id** in **[Gist]**.
+
+Then, download the snippets using command:
+```
+$ pet sync
+Download success
+
+```
+
+For more details, refer the help section:
+```
+pet -h
+```
+
+Or,
+```
+pet [command] -h
+```
+
+And, that's all. Hope this helps. As you can see, Pet usage is fairly simple and easy to use! If you're having hard time remembering lengthy commands, Pet utility can definitely be useful.
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/pet-simple-command-line-snippet-manager/
+
+作者:[SK][a]
+译者:[译者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/bookmark-linux-commands-easier-repeated-invocation/
+[2]:https://www.ostechnix.com/save-commands-terminal-use-demand/
+[3]:https://github.com/knqyf263/pet/releases
+[4]:https://www.ostechnix.com/install-pacaur-arch-linux/
+[5]:https://www.ostechnix.com/install-packer-arch-linux-2/
+[6]:https://www.ostechnix.com/install-yaourt-arch-linux/
+[7]:https://www.ostechnix.com/yay-found-yet-another-reliable-aur-helper/
+[8]:https://github.com/junegunn/fzf
+[9]:https://github.com/peco/peco
+[10]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[11]:http://www.ostechnix.com/wp-content/uploads/2018/01/pet-1.png ()
+[12]:http://www.ostechnix.com/wp-content/uploads/2018/01/pet-2.png ()
+[13]:http://www.ostechnix.com/wp-content/uploads/2018/01/pet-3.png ()
+[14]:http://www.ostechnix.com/wp-content/uploads/2018/01/pet-4.png ()
+[15]:http://www.ostechnix.com/wp-content/uploads/2018/01/pet-5.png ()
diff --git a/sources/tech/20180122 An overview of the Perl 5 engine.md b/sources/tech/20180122 An overview of the Perl 5 engine.md
new file mode 100644
index 0000000000..a26266a39a
--- /dev/null
+++ b/sources/tech/20180122 An overview of the Perl 5 engine.md
@@ -0,0 +1,130 @@
+An overview of the Perl 5 engine
+======
+
+
+
+As I described in "[My DeLorean runs Perl][1]," switching to Perl has vastly improved my development speed and possibilities. Here I'll dive deeper into the design of Perl 5 to discuss aspects important to systems programming.
+
+Some years ago, I wrote "OpenGL bindings for Bash" as sort of a joke. The implementation was simply an X11 program written in C that read OpenGL calls on [stdin][2] (yes, as text) and emitted user input on [stdout][3] . Then I had a littlefile that would declare all the OpenGL functions as Bash functions, which echoed the name of the function into a pipe, starting the GL interpreter process if it wasn't already running. The point of the exercise was to show that OpenGL (the 1.4 API, not the newer shader stuff) could render a lot of graphics with just a few calls per frame by using GL display lists. The OpenGL library did all the heavy lifting, and Bash just printed a few dozen lines of text per frame.
+
+In the end though, Bash is a really horrible [glue language][4], both from high overhead and limited available operations and syntax. [Perl][5], on the other hand, is a great glue language.
+
+### Syntax aside...
+
+If you're not a regular Perl user, the first thing you probably notice is the syntax.
+
+Perl 5 is built on a long legacy of awkward syntax, but more recent versions have removed the need for much of the punctuation. The remaining warts can mostly be avoided by choosing modules that give you domain-specific "syntactic sugar," which even alter the Perl syntax as it is parsed. This is in stark contrast to most other languages, where you are stuck with the syntax you're given, and infinitely more flexible than C's macros. Combined with Perl's powerful sparse-syntax operators, like `map`, `grep`, `sort`, and similar user-defined operators, I can almost always write complex algorithms more legibly and with less typing using Perl than with JavaScript, PHP, or any compiled language.
+
+So, because syntax is what you make of it, I think the underlying machine is the most important aspect of the language to consider. Perl 5 has a very capable engine, and it differs in interesting and useful ways from other languages.
+
+### A layer above C
+
+I don't recommend anyone start working with Perl by looking at the interpreter's internal API, but a quick description is useful. One of the main problems we deal with in the world of C is acquiring and releasing memory while also supporting control flow through a chain of function calls. C has a rough ability to throw exceptions using `longjmp`, but it doesn't do any cleanup for you, so it is almost useless without a framework to manage resources. The Perl interpreter is exactly this sort of framework.
+
+Perl provides a stack of variables independent from C's stack of function calls on which you can mark the logical boundaries of a Perl scope. There are also API calls you can use to allocate memory, Perl variables, etc., and tell Perl to automatically free them at the end of the Perl scope. Now you can make whatever C calls you like, "die" out of the middle of them, and let Perl clean everything up for you.
+
+Although this is a really unconventional perspective, I bring it up to emphasize that Perl sits on top of C and allows you to use as much or as little interpreted overhead as you like. Perl's internal API is certainly not as nice as C++ for general programming, but C++ doesn't give you an interpreted language on top of your work when you're done. I've lost track of the number of times that I wanted reflective capability to inspect or alter my C++ objects, and following that rabbit hole has derailed more than one of my personal projects.
+
+### Lisp-like functions
+
+Perl functions take a list of arguments. The downside is that you have to do argument count and type checking at runtime. The upside is you don't end up doing that much, because you can just let the interpreter's own runtime check catch those mistakes. You can also create the effect of C++'s overloaded functions by inspecting the arguments you were given and behaving accordingly.
+
+Because arguments are a list, and return values are a list, this encourages [Lisp-style programming][6], where you use a series of functions to filter a list of data elements. This "piping" or "streaming" effect can result in some really complicated loops turning into a single line of code.
+
+Every function is available to the language as a `coderef` that can be passed around in variables, including anonymous closure functions. Also, I find `sub {}` more convenient to type than JavaScript's `function(){}` or C++11's `[&](){}`.
+
+### Generic data structures
+
+The variables in Perl are either "scalars," references, arrays, or "hashes" ... or some other stuff that I'll skip.
+
+Scalars act as a string/integer/float hybrid and are automatically typecast as needed for the purpose you are using them. In other words, instead of determining the operation by the type of variable, the type of operator determines how the variable should be interpreted. This is less efficient than if the language knows the type in advance, but not as inefficient as, for example, shell scripting because Perl caches the type conversions.
+
+Perl scalars may contain null characters, so they are fully usable as buffers for binary data. The scalars are mutable and copied by value, but optimized with copy-on-write, and substring operations are also optimized. Strings support unicode characters but are stored efficiently as normal bytes until you append a codepoint above 255.
+
+References (which are considered scalars as well) hold a reference to any other variable; `hashrefs` and `arrayrefs` are most common, along with the `coderefs` described above.
+
+Arrays are simply a dynamic-length array of scalars (or references).
+
+Hashes (i.e., dictionaries, maps, or whatever you want to call them) are a performance-tuned hash table implementation where every key is a string and every value is a scalar (or reference). Hashes are used in Perl in the same way structs are used in C. Clearly a hash is less efficient than a struct, but it keeps things generic so tasks that require dozens of lines of code in other languages can become one-liners in Perl. For instance, you can dump the contents of a hash into a list of (key, value) pairs or reconstruct a hash from such a list as a natural part of the Perl syntax.
+
+### Object model
+
+Any reference can be "blessed" to make it into an object, granting it a multiple-inheritance method-dispatch table. The blessing is simply the name of a package (namespace), and any function in that namespace becomes an available method of the object. The inheritance tree is defined by variables in the package. As a result, you can make modifications to classes or class hierarchies or create new classes on the fly with simple data edits, rather than special keywords or built-in reflection APIs. By combining this with Perl's `local` keyword (where changes to a global are automatically undone at the end of the current scope), you can even make temporary changes to class methods or inheritance!
+
+Perl objects only have methods, so attributes are accessed via accessors like the canonical Java `get_` and `set_` methods. Perl authors usually combine them into a single method of just the attribute name and differentiate `get` from `set` by whether a parameter was given.
+
+You can also "re-bless" objects from one class to another, which enables interesting tricks not available in most other languages. Consider state machines, where each method would normally start by checking the object's current state; you can avoid that in Perl by swapping the method table to one that matches the object's state.
+
+### Visibility
+
+While other languages spend a bunch of effort on access rules between classes, Perl adopted a simple "if the name begins with underscore, don't touch it unless it's yours" convention. Although I can see how this could be a problem with an undisciplined software team, it has worked great in my experience. The only thing C++'s `private` keyword ever did for me was impair my debugging efforts, yet it felt dirty to make everything `public`. Perl removes my guilt.
+
+Likewise, an object provides methods, but you can ignore them and just access the underlying Perl data structure. This is another huge boost for debugging.
+
+### Garbage collection via reference counting
+
+Although [reference counting][7] is a rather leak-prone form of memory management (it doesn't detect cycles), it has a few upsides. It gives you deterministic destruction of your objects, like in C++, and never interrupts your program with a surprise garbage collection. It strongly encourages module authors to use a tree-of-objects pattern, which I much prefer vs. the tangle-of-objects pattern often seen in Java and JavaScript. (I've found trees to be much more easily tested with unit tests.) But, if you need a tangle of objects, Perl does offer "weak" references, which won't be considered when deciding if it's time to garbage-collect something.
+
+On the whole, the only time this ever bites me is when making heavy use of closures for event-driven callbacks. It's easy to have an object hold a reference to an event handle holding a reference to a callback that references the containing object. Again, weak references solve this, but it's an extra thing to be aware of that JavaScript or Python don't make you worry about.
+
+### Parallelism
+
+The Perl interpreter is a single thread, although modules written in C can use threads of their own internally, and Perl often includes support for multiple interpreters within the same process.
+
+Although this is a large limitation, knowing that a data structure will only ever be touched by one thread is nice, and it means you don't need locks when accessing them from C code. Even in Java, where locking is built into the syntax in convenient ways, it can be a real time sink to reason through all the ways that threads can interact (and especially annoying that they force you to deal with that in every GUI program you write).
+
+There are several event libraries available to assist in writing event-driven callback programs in the style of Node.js to avoid the need for threads.
+
+### Access to C libraries
+
+Aside from directly writing your own C extensions via Perl's [XS][8] system, there are already lots of common C libraries wrapped for you and available on Perl's [CPAN][9] repository. There is also a great module, [Inline::C][10], that takes most of the pain out of bridging between Perl and C, to the point where you just paste C code into the middle of a Perl module. (It compiles the first time you run it and caches the .so shared object file for subsequent runs.) You still need to learn some of the Perl interpreter API if you want to manipulate the Perl stack or pack/unpack Perl's variables other than your C function arguments and return value.
+
+### Memory usage
+
+Perl can use a surprising amount of memory, especially if you make use of heavyweight libraries and create thousands of objects, but with the size of today's systems it usually doesn't matter. It also isn't much worse than other interpreted systems. My personal preference is to only use lightweight libraries, which also generally improve performance.
+
+### Startup speed
+
+The Perl interpreter starts in under five milliseconds on modern hardware. If you take care to use only lightweight modules, you can use Perl for anything you might have used Bash for, like `hotplug` scripts.
+
+### Regex implementation
+
+Perl provides the mother of all regex implementations... but you probably already knew that. Regular expressions are built into Perl's syntax rather than being an object-oriented or function-based API; this helps encourage their use for any text processing you might need to do.
+
+### Ubiquity and stability
+
+Perl 5 is installed on just about every modern Unix system, and the CPAN module collection is extensive and easy to install. There's a production-quality module for almost any task, with solid test coverage and good documentation.
+
+Perl 5 has nearly complete backward compatibility across two decades of releases. The community has embraced this as well, so most of CPAN is pretty stable. There's even a crew of testers who run unit tests on all of CPAN on a regular basis to help detect breakage.
+
+The toolchain is also pretty solid. The documentation syntax (POD) is a little more verbose than I'd like, but it yields much more useful results than [doxygen][11] or [Javadoc][12]. You can run `perldoc FILENAME` to instantly see the documentation of the module you're writing. `perldoc Module::Name` shows you the specific documentation for the version of the module that you would load from your `include` path and can likewise show you the source code of that module without needing to browse deep into your filesystem.
+
+The testcase system (the `prove` command and Test Anything Protocol, or TAP) isn't specific to Perl and is extremely simple to work with (as opposed to unit testing based around language-specific object-oriented structure, or XML). Modules like `Test::More` make writing the test cases so easy that you can write a test suite in about the same time it would take to test your module once by hand. The testing effort barrier is so low that I've started using TAP and the POD documentation style for my non-Perl projects as well.
+
+### In summary
+
+Perl 5 still has a lot to offer despite the large number of newer languages competing with it. The frontend syntax hasn't stopped evolving, and you can improve it however you like with custom modules. The Perl 5 engine is capable of handling most programming problems you can throw at it, and it is even suitable for low-level work as a "glue" layer on top of C libraries. Once you get really familiar with it, it can even be an environment for developing C code.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/why-i-love-perl-5
+
+作者:[Michael Conrad][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/nerdvana
+[1]:https://opensource.com/article/17/12/my-delorean-runs-perl
+[2]:https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)
+[3]:https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout)
+[4]:https://www.techopedia.com/definition/19608/glue-language
+[5]:https://www.perl.org/
+[6]:https://en.wikipedia.org/wiki/Lisp_(programming_language)
+[7]:https://en.wikipedia.org/wiki/Reference_counting
+[8]:https://en.wikipedia.org/wiki/XS_(Perl)
+[9]:https://www.cpan.org/
+[10]:https://metacpan.org/pod/distribution/Inline-C/lib/Inline/C.pod
+[11]:http://www.stack.nl/~dimitri/doxygen/
+[12]:http://www.oracle.com/technetwork/java/javase/documentation/index-jsp-135444.html
diff --git a/sources/tech/20180122 Ick- a continuous integration system.md b/sources/tech/20180122 Ick- a continuous integration system.md
new file mode 100644
index 0000000000..4620e2c036
--- /dev/null
+++ b/sources/tech/20180122 Ick- a continuous integration system.md
@@ -0,0 +1,75 @@
+Ick: a continuous integration system
+======
+**TL;DR:** Ick is a continuous integration or CI system. See for more information.
+
+More verbose version follows.
+
+### First public version released
+
+The world may not need yet another continuous integration system (CI), but I do. I've been unsatisfied with the ones I've tried or looked at. More importantly, I am interested in a few things that are more powerful than what I've ever even heard of. So I've started writing my own.
+
+My new personal hobby project is called ick. It is a CI system, which means it can run automated steps for building and testing software. The home page is at , and the [download][1] page has links to the source code and .deb packages and an Ansible playbook for installing it.
+
+I have now made the first publicly advertised release, dubbed ALPHA-1, version number 0.23. It is of alpha quality, and that means it doesn't have all the intended features and if any of the features it does have work, you should consider yourself lucky.
+
+### Invitation to contribute
+
+Ick has so far been my personal project. I am hoping to make it more than that, and invite contributions. See the [governance][2] page for the constitution, the [getting started][3] page for tips on how to start contributing, and the [contact][4] page for how to get in touch.
+
+### Architecture
+
+Ick has an architecture consisting of several components that communicate over HTTPS using RESTful APIs and JSON for structured data. See the [architecture][5] page for details.
+
+### Manifesto
+
+Continuous integration (CI) is a powerful tool for software development. It should not be tedious, fragile, or annoying. It should be quick and simple to set up, and work quietly in the background unless there's a problem in the code being built and tested.
+
+A CI system should be simple, easy, clear, clean, scalable, fast, comprehensible, transparent, reliable, and boost your productivity to get things done. It should not be a lot of effort to set up, require a lot of hardware just for the CI, need frequent attention for it to keep working, and developers should never have to wonder why something isn't working.
+
+A CI system should be flexible to suit your build and test needs. It should support multiple types of workers, as far as CPU architecture and operating system version are concerned.
+
+Also, like all software, CI should be fully and completely free software and your instance should be under your control.
+
+(Ick is little of this yet, but it will try to become all of it. In the best possible taste.)
+
+### Dreams of the future
+
+In the long run, I would ick to have features like ones described below. It may take a while to get all of them implemented.
+
+ * A build may be triggered by a variety of events. Time is an obvious event, as is source code repository for the project changing. More powerfully, any build dependency changing, regardless of whether the dependency comes from another project built by ick, or a package from, say, Debian: ick should keep track of all the packages that get installed into the build environment of a project, and if any of their versions change, it should trigger the project build and tests again.
+
+ * Ick should support building in (or against) any reasonable target, including any Linux distribution, any free operating system, and any non-free operating system that isn't brain-dead.
+
+ * Ick should manage the build environment itself, and be able to do builds that are isolated from the build host or the network. This partially works: one can ask ick to build a container and run a build in the container. The container is implemented using systemd-nspawn. This can be improved upon, however. (If you think Docker is the only way to go, please contribute support for that.)
+
+ * Ick should support any workers that it can control over ssh or a serial port or other such neutral communication channel, without having to install an agent of any kind on them. Ick won't assume that it can have, say, a full Java run time, so that the worker can be, say, a micro controller.
+
+ * Ick should be able to effortlessly handle very large numbers of projects. I'm thinking here that it should be able to keep up with building everything in Debian, whenever a new Debian source package is uploaded. (Obviously whether that is feasible depends on whether there are enough resources to actually build things, but ick itself should not be the bottleneck.)
+
+ * Ick should optionally provision workers as needed. If all workers of a certain type are busy, and ick's been configured to allow using more resources, it should do so. This seems like it would be easy to do with virtual machines, containers, cloud providers, etc.
+
+ * Ick should be flexible in how it can notify interested parties, particularly about failures. It should allow an interested party to ask to be notified over IRC, Matrix, Mastodon, Twitter, email, SMS, or even by a phone call and speech syntethiser. "Hello, interested party. It is 04:00 and you wanted to be told when the hello package has been built for RISC-V."
+
+
+
+
+### Please give feedback
+
+If you try ick, or even if you've just read this far, please share your thoughts on it. See the [contact][4] page for where to send it. Public feedback is preferred over private, but if you prefer private, that's OK too.
+
+--------------------------------------------------------------------------------
+
+via: https://blog.liw.fi/posts/2018/01/22/ick_a_continuous_integration_system/
+
+作者:[Lars Wirzenius][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://blog.liw.fi/
+[1]:http://ick.liw.fi/download/
+[2]:http://ick.liw.fi/governance/
+[3]:http://ick.liw.fi/getting-started/
+[4]:http://ick.liw.fi/contact/
+[5]:http://ick.liw.fi/architecture/
diff --git a/sources/tech/20180122 Linux rm Command Explained for Beginners (8 Examples).md b/sources/tech/20180122 Linux rm Command Explained for Beginners (8 Examples).md
new file mode 100644
index 0000000000..4e5e002754
--- /dev/null
+++ b/sources/tech/20180122 Linux rm Command Explained for Beginners (8 Examples).md
@@ -0,0 +1,174 @@
+Translating by yizhuoyan
+
+Linux rm Command Explained for Beginners (8 Examples)
+======
+
+Deleting files is a fundamental operation, just like copying files or renaming/moving them. In Linux, there's a dedicated command - dubbed **rm** \- that lets you perform all deletion-related operations. In this tutorial, we will discuss the basics of this tool along with some easy to understand examples.
+
+But before we do that, it's worth mentioning that all examples mentioned in the article have been tested on Ubuntu 16.04 LTS.
+
+#### Linux rm command
+
+So in layman's terms, we can simply say the rm command is used for removing/deleting files and directories. Following is the syntax of the command:
+
+```
+rm [OPTION]... [FILE]...
+```
+
+And here's how the tool's man page describes it:
+```
+This manual page documents the GNU version of rm. rm removes each specified file. By default, it
+does not remove directories.
+
+If the -I or --interactive=once option is given, and there are more than three files or the -r,
+-R, or --recursive are given, then rm prompts the user for whether to proceed with the entire
+operation. If the response is not affirmative, the entire command is aborted.
+
+Otherwise, if a file is unwritable, standard input is a terminal, and the -f or --force option is
+not given, or the -i or --interactive=always option is given, rm prompts the user for whether to
+remove the file. If the response is not affirmative, the file is skipped.
+```
+
+The following Q&A-styled examples will give you a better idea on how the tool works.
+
+#### Q1. How to remove files using rm command?
+
+That's pretty easy and straightforward. All you have to do is to pass the name of the files (along with paths if they are not in the current working directory) as input to the rm command.
+
+```
+rm [filename]
+```
+
+For example:
+
+```
+rm testfile.txt
+```
+
+[![How to remove files using rm command][1]][2]
+
+#### Q2. How to remove directories using rm command?
+
+If you are trying to remove a directory, then you need to use the **-r** command line option. Otherwise, rm will throw an error saying what you are trying to delete is a directory.
+
+```
+rm -r [dir name]
+```
+
+For example:
+
+```
+rm -r testdir
+```
+
+[![How to remove directories using rm command][3]][4]
+
+#### Q3. How to make rm prompt before every removal?
+
+If you want rm to prompt before each delete action it performs, then use the **-i** command line option.
+
+```
+rm -i [file or dir]
+```
+
+For example, suppose you want to delete a directory 'testdir' and all its contents, but want rm to prompt before every deletion, then here's how you can do that:
+
+```
+rm -r -i testdir
+```
+
+[![How to make rm prompt before every removal][5]][6]
+
+#### Q4. How to force rm to ignore nonexistent files?
+
+The rm command lets you know through an error message if you try deleting a non-existent file or directory.
+
+[![Linux rm command example][7]][8]
+
+However, if you want, you can make rm suppress such error/notifications - all you have to do is to use the **-f** command line option.
+
+```
+rm -f [filename]
+```
+
+[![How to force rm to ignore nonexistent files][9]][10]
+
+#### Q5. How to make rm prompt only in some scenarios?
+
+There exists a command line option **-I** , which when used, makes sure the command only prompts once before removing more than three files, or when removing recursively.
+
+For example, the following screenshot shows this option in action - there was no prompt when two files were deleted, but the command prompted when more than three files were deleted.
+
+[![How to make rm prompt only in some scenarios][11]][12]
+
+#### Q6. How rm works when dealing with root directory?
+
+Of course, deleting root directory is the last thing a Linux user would want. That's why, the rm command doesn't let you perform a recursive delete operation on this directory by default.
+
+[![How rm works when dealing with root directory][13]][14]
+
+However, if you want to go ahead with this operation for whatever reason, then you need to tell this to rm by using the **\--no-preserve-root** option. When this option is enabled, rm doesn't treat the root directory (/) specially.
+
+In case you want to know the scenarios in which a user might want to delete the root directory of their system, head [here][15].
+
+#### Q7. How to make rm only remove empty directories?
+
+In case you want to restrict rm's directory deletion ability to only empty directories, then you can use the -d command line option.
+
+```
+rm -d [dir]
+```
+
+The following screenshot shows the -d command line option in action - only empty directory got deleted.
+
+[![How to make rm only remove empty directories][16]][17]
+
+#### Q8. How to force rm to emit details of operation it is performing?
+
+If you want rm to display detailed information of the operation being performed, then this can be done by using the **-v** command line option.
+
+```
+rm -v [file or directory name]
+```
+
+For example:
+
+[![How to force rm to emit details of operation it is performing][18]][19]
+
+#### Conclusion
+
+Given the kind of functionality it offers, rm is one of the most frequently used commands in Linux (like [cp][20] and mv). Here, in this tutorial, we have covered almost all major command line options this tool provides. rm has a bit of learning curve associated with, so you'll have to spent some time practicing its options before you start using the tool in your day to day work. For more information, head to the command's [man page][21].
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.howtoforge.com/linux-rm-command/
+
+作者:[Himanshu Arora][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.howtoforge.com
+[1]:https://www.howtoforge.com/images/command-tutorial/rm-basic-usage.png
+[2]:https://www.howtoforge.com/images/command-tutorial/big/rm-basic-usage.png
+[3]:https://www.howtoforge.com/images/command-tutorial/rm-r.png
+[4]:https://www.howtoforge.com/images/command-tutorial/big/rm-r.png
+[5]:https://www.howtoforge.com/images/command-tutorial/rm-i-option.png
+[6]:https://www.howtoforge.com/images/command-tutorial/big/rm-i-option.png
+[7]:https://www.howtoforge.com/images/command-tutorial/rm-non-ext-error.png
+[8]:https://www.howtoforge.com/images/command-tutorial/big/rm-non-ext-error.png
+[9]:https://www.howtoforge.com/images/command-tutorial/rm-f-option.png
+[10]:https://www.howtoforge.com/images/command-tutorial/big/rm-f-option.png
+[11]:https://www.howtoforge.com/images/command-tutorial/rm-I-option.png
+[12]:https://www.howtoforge.com/images/command-tutorial/big/rm-I-option.png
+[13]:https://www.howtoforge.com/images/command-tutorial/rm-root-default.png
+[14]:https://www.howtoforge.com/images/command-tutorial/big/rm-root-default.png
+[15]:https://superuser.com/questions/742334/is-there-a-scenario-where-rm-rf-no-preserve-root-is-needed
+[16]:https://www.howtoforge.com/images/command-tutorial/rm-d-option.png
+[17]:https://www.howtoforge.com/images/command-tutorial/big/rm-d-option.png
+[18]:https://www.howtoforge.com/images/command-tutorial/rm-v-option.png
+[19]:https://www.howtoforge.com/images/command-tutorial/big/rm-v-option.png
+[20]:https://www.howtoforge.com/linux-cp-command/
+[21]:https://linux.die.net/man/1/rm
diff --git a/sources/tech/20180123 Installing Awstat for analyzing Apache logs.md b/sources/tech/20180123 Installing Awstat for analyzing Apache logs.md
new file mode 100644
index 0000000000..b635417a47
--- /dev/null
+++ b/sources/tech/20180123 Installing Awstat for analyzing Apache logs.md
@@ -0,0 +1,117 @@
+Installing Awstat for analyzing Apache logs
+======
+AWSTAT is free an very powerful log analyser tool for apache log files. After analyzing logs from apache, it present them in easy to understand graphical format. Awstat is short for Advanced Web statistics & it works on command line interface or on CGI.
+
+In this tutorial, we will be installing AWSTAT on our Centos 7 machine for analyzing apache logs.
+
+( **Recommended read** :[ **Scheduling important jobs with crontab**][1])
+
+### Pre-requisites
+
+ **1-** A website hosted on apache web server, to create one read below mentioned tutorials on apache web servers,
+
+( **Recommended reads** - [**installing Apache**][2], [**Securing apache with SSL cert**][3] & **hardening tips for apache** )
+
+ **2-** Epel repository enabled on the system, as Awstat packages are not available on default repositories. To enable epel-repo , run
+
+```
+$ rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-10.noarch.rpm
+```
+
+### Installing Awstat
+
+Once the epel-repository has been enabled on the system, awstat can be installed by running,
+
+```
+ $ yum install awstat
+```
+
+When awstat is installed, it creates a file for apache at '/etc/httpd/conf.d/awstat.conf' with some configurations. These configurations are good to be used incase web server &awstat are configured on the same machine but if awstat is on different machine than the webserver, then some changes are to be made to the file.
+
+#### Configuring Apache for Awstat
+
+To configure awstat for a remote web server, open /etc/httpd/conf.d/awstat.conf, & update the parameter 'Allow from' with the IP address of the web server
+
+```
+$ vi /etc/httpd/conf.d/awstat.conf
+
+
+Options None
+AllowOverride None
+
+# Apache 2.4
+Require local
+
+
+# Apache 2.2
+Order allow,deny
+Allow from 127.0.0.1
+Allow from 192.168.1.100
+
+
+```
+
+Save the file & restart the apache services to implement the changes,
+
+```
+ $ systemctl restart httpd
+```
+
+#### Configuring AWSTAT
+
+For every website that we add to awstat, a different configuration file needs to be created with the website information . An example file is created in folder '/etc/awstats' by the name 'awstats.localhost.localdomain.conf', we can make copies of it & configure our website with this,
+
+```
+$ cd /etc/awstats
+$ cp awstats.localhost.localdomain.conf awstats.linuxtechlab.com.conf
+```
+
+Now open the file & edit the following three parameters to match your website,
+
+```
+$ vi awstats.linuxtechlab.com.conf
+
+LogFile="/var/log/httpd/access.log"
+SiteDomain="linuxtechlab.com"
+HostAliases=www.linuxtechlab.com localhost 127.0.0.1
+```
+
+Last step is to update the configuration file, which can be done executing the command below,
+
+```
+/usr/share/awstats/wwwroot/cgi-bin/awstats.pl -config=linuxtechlab.com -update
+```
+
+#### Checking the awstat page
+
+To test/check the awstat page, open web-browser & enter the following URL in the address bar,
+**https://linuxtechlab.com/awstats/awstats.pl?config=linuxtechlab.com**
+
+![awstat][5]
+
+**Note-** we can also schedule a cron job to update the awstat on regular basis. An example for the crontab
+
+```
+$ crontab -e
+0 1 * * * /usr/share/awstats/wwwroot/cgi-bin/awstats.pl -config=linuxtechlab.com–update
+```
+
+We now end our tutorial on installing Awstat for analyzing apache logs, please leave your comments/queries in the comment box below.
+
+
+--------------------------------------------------------------------------------
+
+via: http://linuxtechlab.com/installing-awstat-analyzing-apache-logs/
+
+作者:[SHUSAIN][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://linuxtechlab.com/author/shsuain/
+[1]:http://linuxtechlab.com/scheduling-important-jobs-crontab/
+[2]:http://linuxtechlab.com/beginner-guide-configure-apache/
+[3]:http://linuxtechlab.com/create-ssl-certificate-apache-server/
+[4]:https://i1.wp.com/linuxtechlab.com/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif?resize=602%2C312
+[5]:https://i0.wp.com/linuxtechlab.com/wp-content/uploads/2017/04/awstat.jpg?resize=602%2C312
diff --git a/sources/tech/20180123 Never miss a Magazine-s article, build your own RSS notification system.md b/sources/tech/20180123 Never miss a Magazine-s article, build your own RSS notification system.md
new file mode 100644
index 0000000000..8794ca611a
--- /dev/null
+++ b/sources/tech/20180123 Never miss a Magazine-s article, build your own RSS notification system.md
@@ -0,0 +1,170 @@
+Never miss a Magazine's article, build your own RSS notification system
+======
+
+
+
+Python is a great programming language to quickly build applications that make our life easier. In this article we will learn how to use Python to build a RSS notification system, the goal being to have fun learning Python using Fedora. If you are looking for a complete RSS notifier application, there are a few already packaged in Fedora.
+
+### Fedora and Python - getting started
+
+Python 3.6 is available by default in Fedora, that includes Python's extensive standard library. The standard library provides a collection of modules which make some tasks simpler for us. For example, in our case we will use the [**sqlite3**][1] module to create, add and read data from a database. In the case where a particular problem we are trying to solve is not covered by the standard library, the chance is that someone has already developed a module for everyone to use. The best place to search for such modules is the Python Package Index known as [PyPI][2]. In our example we are going to use the [**feedparser**][3] to parse an RSS feed.
+
+Since **feedparser** is not in the standard library, we have to install it in our system. Luckily for us there is an rpm package in Fedora, so the installation of **feedparser** is as simple as:
+```
+$ sudo dnf install python3-feedparser
+```
+
+We now have everything we need to start coding our application.
+
+### Storing the feed data
+
+We need to store data from the articles that have already been published so that we send a notification only for new articles. The data we want to store will give us a unique way to identify an article. Therefore we will store the **title** and the **publication date** of the article.
+
+So let's create our database using python **sqlite3** module and a simple SQL query. We are also adding the modules we are going to use later ( **feedparser** , **smtplib** and **email** ).
+
+#### Creating the Database
+```
+#!/usr/bin/python3
+import sqlite3
+import smtplib
+from email.mime.text import MIMEText
+
+import feedparser
+
+db_connection = sqlite3.connect('/var/tmp/magazine_rss.sqlite')
+db = db_connection.cursor()
+db.execute(' CREATE TABLE IF NOT EXISTS magazine (title TEXT, date TEXT)')
+
+```
+
+These few lines of code create a new sqlite database stored in a file called 'magazine_rss.sqlite', and then create a new table within the database called 'magazine'. This table has two columns - 'title' and 'date' - that can store data of the type TEXT, which means that the value of each column will be a text string.
+
+#### Checking the Database for old articles
+
+Since we only want to add new articles to our database we need a function that will check if the article we get from the RSS feed is already in our database or not. We will use it to decide if we should send an email notification (new article) or not (old article). Ok let's code this function.
+```
+def article_is_not_db(article_title, article_date):
+ """ Check if a given pair of article title and date
+ is in the database.
+ Args:
+ article_title (str): The title of an article
+ article_date (str): The publication date of an article
+ Return:
+ True if the article is not in the database
+ False if the article is already present in the database
+ """
+ db.execute("SELECT * from magazine WHERE title=? AND date=?", (article_title, article_date))
+ if not db.fetchall():
+ return True
+ else:
+ return False
+```
+
+The main part of this function is the SQL query we execute to search through the database. We are using a SELECT instruction to define which column of our magazine table we will run the query on. We are using the 0_sync_master.sh 1_add_new_article_manual.sh 1_add_new_article_newspaper.sh 2_start_translating.sh 3_continue_the_work.sh 4_finish.sh 5_pause.sh base.sh env format.test lctt.cfg parse_url_by_manual.sh parse_url_by_newspaper.py parse_url_by_newspaper.sh README.org reformat.sh symbol to select all columns ( title and date). Then we ask to select only the rows of the table WHERE the article_title and article_date string are equal to the value of the title and date column.
+
+To finish, we have a simple logic that will return True if the query did not return any results and False if the query found an article in database matching our title, date pair.
+
+#### Adding a new article to the Database
+
+Now we can code the function to add a new article to the database.
+```
+def add_article_to_db(article_title, article_date):
+ """ Add a new article title and date to the database
+ Args:
+ article_title (str): The title of an article
+ article_date (str): The publication date of an article
+ """
+ db.execute("INSERT INTO magazine VALUES (?,?)", (article_title, article_date))
+ db_connection.commit()
+```
+
+This function is straight forward, we are using a SQL query to INSERT a new row INTO the magazine table with the VALUES of the article_title and article_date. Then we commit the change to make it persistent.
+
+That's all we need from the database's point of view, let's look at the notification system and how we can use python to send emails.
+
+### Sending an email notification
+
+Let's create a function to send an email using the python standard library module **smtplib.** We are also using the **email** module from the standard library to format our email message.
+```
+def send_notification(article_title, article_url):
+ """ Add a new article title and date to the database
+
+ Args:
+ article_title (str): The title of an article
+ article_url (str): The url to access the article
+ """
+
+ smtp_server = smtplib.SMTP('smtp.gmail.com', 587)
+ smtp_server.ehlo()
+ smtp_server.starttls()
+ smtp_server.login('your_email@gmail.com', '123your_password')
+ msg = MIMEText(f'\nHi there is a new Fedora Magazine article : {article_title}. \nYou can read it here {article_url}')
+ msg['Subject'] = 'New Fedora Magazine Article Available'
+ msg['From'] = 'your_email@gmail.com'
+ msg['To'] = 'destination_email@gmail.com'
+ smtp_server.send_message(msg)
+ smtp_server.quit()
+```
+
+In this example I am using the Google mail smtp server to send an email, but this will work with any email services that provides you with a SMTP server. Most of this function is boilerplate needed to configure the access to the smtp server. You will need to update the code with your email address and credentials.
+
+If you are using 2 Factor Authentication with your gmail account you can setup a password app that will give you a unique password to use for this application. Check out this help [page][4].
+
+### Reading Fedora Magazine RSS feed
+
+We now have functions to store an article in the database and send an email notification, let's create a function that parses the Fedora Magazine RSS feed and extract the articles' data.
+```
+def read_article_feed():
+ """ Get articles from RSS feed """
+ feed = feedparser.parse('https://fedoramagazine.org/feed/')
+ for article in feed['entries']:
+ if article_is_not_db(article['title'], article['published']):
+ send_notification(article['title'], article['link'])
+ add_article_to_db(article['title'], article['published'])
+
+if __name__ == '__main__':
+ read_article_feed()
+ db_connection.close()
+```
+
+Here we are making use of the **feedparser.parse** function. The function returns a dictionary representation of the RSS feed, for the full reference of the representation you can consult **feedparser** 's [documentation][5].
+
+The RSS feed parser will return the last 10 articles as entries and then we extract the following information: the title, the link and the date the article was published. As a result, we can now use the functions we have previously defined to check if the article is not in the database, then send a notification email and finally, add the article to our database.
+
+The last if statement is used to execute our read_article_feed function and then close the database connection when we execute our script.
+
+### Running our script
+
+Finally, to run our script we need to give the correct permission to the file. Next, we make use of the **cron** utility to automatically execute our script every hour (1 minute past the hour). **cron** is a job scheduler that we can use to run a task at a fixed time.
+```
+$ chmod a+x my_rss_notifier.py
+$ sudo cp my_rss_notifier.py /etc/cron.hourly
+```
+
+To keep this tutorial simple, we are using the cron.hourly directory to execute the script every hours, I you wish to learn more about **cron** and how to configure the **crontab,** please read **cron 's** wikipedia [page][6].
+
+### Conclusion
+
+In this tutorial we have learned how to use Python to create a simple sqlite database, parse an RSS feed and send emails. I hope that this showed you how you can easily build your own application using Python and Fedora.
+
+The script is available on github [here][7].
+
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/never-miss-magazines-article-build-rss-notification-system/
+
+作者:[Clément Verna][a]
+译者:[译者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://docs.python.org/3/library/sqlite3.html
+[2]:https://pypi.python.org/pypi
+[3]:https://pypi.python.org/pypi/feedparser/5.2.1
+[4]:https://support.google.com/accounts/answer/185833?hl=en
+[5]:https://pythonhosted.org/feedparser/reference.html
+[6]:https://en.wikipedia.org/wiki/Cron
+[7]:https://github.com/cverna/rss_feed_notifier
diff --git a/sources/tech/20180125 BUILDING A FULL-TEXT SEARCH APP USING DOCKER AND ELASTICSEARCH.md b/sources/tech/20180125 BUILDING A FULL-TEXT SEARCH APP USING DOCKER AND ELASTICSEARCH.md
new file mode 100644
index 0000000000..d064544e1f
--- /dev/null
+++ b/sources/tech/20180125 BUILDING A FULL-TEXT SEARCH APP USING DOCKER AND ELASTICSEARCH.md
@@ -0,0 +1,1382 @@
+BUILDING A FULL-TEXT SEARCH APP USING DOCKER AND ELASTICSEARCH
+============================================================
+
+ _How does Wikipedia sort though 5+ million articles to find the most relevant one for your research?_
+
+ _How does Facebook find the friend who you're looking for (and whose name you've misspelled), across a userbase of 2+ billion people?_
+
+ _How does Google search the entire internet for webpages relevant to your vague, typo-filled search query?_
+
+In this tutorial, we'll walk through setting up our own full-text search application (of an admittedly lesser complexity than the systems in the questions above). Our example app will provide a UI and API to search the complete texts of 100 literary classics such as _Peter Pan_ , _Frankenstein_ , and _Treasure Island_ .
+
+You can preview a completed version of the tutorial app here - [https://search.patricktriest.com][6]
+
+
+
+The source code for the application is 100% open-source and can be found at the GitHub repository here - [https://github.com/triestpa/guttenberg-search][7]
+
+Adding fast, flexible full-text search to apps can be a challenge. Most mainstream databases, such as [PostgreSQL][8] and [MongoDB][9], offer very basic text searching capabilities due to limitations on their existing query and index structures. In order to implement high quality full-text search, a separate datastore is often the best option. [Elasticsearch][10] is a leading open-source datastore that is optimized to perform incredibly flexible and fast full-text search.
+
+We'll be using [Docker][11] to setup our project environment and dependencies. Docker is a containerization engine used by the likes of [Uber][12], [Spotify][13], [ADP][14], and [Paypal][15]. A major advantage of building a containerized app is that the project setup is virtually the same on Windows, macOS, and Linux - which makes writing this tutorial quite a bit simpler for me. Don't worry if you've never used Docker, we'll go through the full project configuration further down.
+
+We'll also be using [Node.js][16] (with the [Koa][17] framework), and [Vue.js][18] to build our search API and frontend web app respectively.
+
+### 1 - WHAT IS ELASTICSEARCH?
+
+Full-text search is a heavily requested feature in modern applications. Search can also be one of the most difficult features to implement competently - many popular websites have subpar search functionality that returns results slowly and has trouble finding non-exact matches. Often, this is due to limitations in the underlying database: most standard relational databases are limited to basic `CONTAINS` or `LIKE`SQL queries, which provide only the most basic string matching functionality.
+
+We'd like our search app to be :
+
+1. **Fast** - Search results should be returned almost instantly, in order to provide a responsive user experience.
+
+2. **Flexible** - We'll want to be able to modify how the search is performed, in order to optimize for different datasets and use cases.
+
+3. **Forgiving** - If a search contains a typo, we'd still like to return relevant results for what the user might have been trying to search for.
+
+4. **Full-Text** - We don't want to limit our search to specific matching keywords or tags - we want to search _everything_ in our datastore (including large text fields) for a match.
+
+
+
+In order to build a super-powered search feature, it’s often most ideal to use a datastore that is optimized for the task of full-text search. This is where [Elasticsearch][19]comes into play; Elasticsearch is an open-source in-memory datastore written in Java and originally built on the [Apache Lucene][20] library.
+
+Here are some examples of real-world Elasticsearch use cases from the official [Elastic website][21].
+
+* Wikipedia uses Elasticsearch to provide full-text search with highlighted search snippets, and search-as-you-type and did-you-mean suggestions.
+
+* The Guardian uses Elasticsearch to combine visitor logs with social -network data to provide real-time feedback to its editors about the public’s response to new articles.
+
+* Stack Overflow combines full-text search with geolocation queries and uses more-like-this to find related questions and answers.
+
+* GitHub uses Elasticsearch to query 130 billion lines of code.
+
+### What makes Elasticsearch different from a "normal" database?
+
+At its core, Elasticsearch is able to provide fast and flexible full-text search through the use of _inverted indices_ .
+
+An "index" is a data structure to allow for ultra-fast data query and retrieval operations in databases. Databases generally index entries by storing an association of fields with the matching table rows. By storing the index in a searchable data structure (often a [B-Tree][22]), databases can achieve sub-linear time on optimized queries (such as “Find the row with ID = 5”).
+
+
+
+We can think of a database index like an old-school library card catalog - it tells you precisely where the entry that you're searching for is located, as long as you already know the title and author of the book. Database tables generally have multiple indices in order to speed up queries on specific fields (i.e. an index on the `name`column would greatly speed up queries for rows with a specific name).
+
+Inverted indexes work in a substantially different manner. The content of each row (or document) is split up, and each individual entry (in this case each word) points back to any documents that it was found within.
+
+
+
+This inverted-index data structure allows us to very quickly find, say, all of the documents where “football” was mentioned. Through the use of a heavily optimized in-memory inverted index, Elasticsearch enables us to perform some very powerful and customizable full-text searches on our stored data.
+
+### 2 - PROJECT SETUP
+
+### 2.0 - Docker
+
+We'll be using [Docker][23] to manage the environments and dependencies for this project. Docker is a containerization engine that allows applications to be run in isolated environments, unaffected by the host operating system and local development environment. Many web-scale companies run a majority of their server infrastructure in containers now, due to the increased flexibility and composability of containerized application components.
+
+
+
+The advantage of using Docker for me, as the friendly author of this tutorial, is that the local environment setup is minimal and consistent across Windows, macOS, and Linux systems. Instead of going through divergent installation instructions for Node.js, Elasticsearch, and Nginx, we can instead just define these dependencies in Docker configuration files, and then run our app anywhere using this configuration. Furthermore, since each application component will run in it's own isolated container, there is much less potential for existing junk on our local machines to interfere, so "But it works on my machine!" types of scenarios will be much more rare when debugging issues.
+
+### 2.1 - Install Docker & Docker-Compose
+
+The only dependencies for this project are [Docker][24] and [docker-compose][25], the later of which is an officially supported tool for defining multiple container configurations to _compose_ into a single application stack.
+
+Install Docker - [https://docs.docker.com/engine/installation/][26]
+Install Docker Compose - [https://docs.docker.com/compose/install/][27]
+
+### 2.2 - Setup Project Directories
+
+Create a base directory (say `guttenberg_search`) for the project. To organize our project we'll work within two main subdirectories.
+
+* `/public` - Store files for the frontend Vue.js webapp.
+
+* `/server` - Server-side Node.js source code
+
+### 2.3 - Add Docker-Compose Config
+
+Next, we'll create a `docker-compose.yml` file to define each container in our application stack.
+
+1. `gs-api` - The Node.js container for the backend application logic.
+
+2. `gs-frontend` - An Ngnix container for serving the frontend webapp files.
+
+3. `gs-search` - An Elasticsearch container for storing and searching data.
+
+```
+version: '3'
+
+services:
+ api: # Node.js App
+ container_name: gs-api
+ build: .
+ ports:
+ - "3000:3000" # Expose API port
+ - "9229:9229" # Expose Node process debug port (disable in production)
+ environment: # Set ENV vars
+ - NODE_ENV=local
+ - ES_HOST=elasticsearch
+ - PORT=3000
+ volumes: # Attach local book data directory
+ - ./books:/usr/src/app/books
+
+ frontend: # Nginx Server For Frontend App
+ container_name: gs-frontend
+ image: nginx
+ volumes: # Serve local "public" dir
+ - ./public:/usr/share/nginx/html
+ ports:
+ - "8080:80" # Forward site to localhost:8080
+
+ elasticsearch: # Elasticsearch Instance
+ container_name: gs-search
+ image: docker.elastic.co/elasticsearch/elasticsearch:6.1.1
+ volumes: # Persist ES data in seperate "esdata" volume
+ - esdata:/usr/share/elasticsearch/data
+ environment:
+ - bootstrap.memory_lock=true
+ - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
+ - discovery.type=single-node
+ ports: # Expose Elasticsearch ports
+ - "9300:9300"
+ - "9200:9200"
+
+volumes: # Define seperate volume for Elasticsearch data
+ esdata:
+
+```
+
+This file defines our entire application stack - no need to install Elasticsearch, Node, or Nginx on your local system. Each container is forwarding ports to the host system (`localhost`), in order for us to access and debug the Node API, Elasticsearch instance, and fronted web app from our host machine.
+
+### 2.4 - Add Dockerfile
+
+We are using official prebuilt images for Nginx and Elasticsearch, but we'll need to build our own image for the Node.js app.
+
+Define a simple `Dockerfile` configuration in the application root directory.
+
+```
+# Use Node v8.9.0 LTS
+FROM node:carbon
+
+# Setup app working directory
+WORKDIR /usr/src/app
+
+# Copy package.json and package-lock.json
+COPY package*.json ./
+
+# Install app dependencies
+RUN npm install
+
+# Copy sourcecode
+COPY . .
+
+# Start app
+CMD [ "npm", "start" ]
+
+```
+
+This Docker configuration extends the official Node.js image, copies our application source code, and installs the NPM dependencies within the container.
+
+We'll also add a `.dockerignore` file to avoid copying unneeded files into the container.
+
+```
+node_modules/
+npm-debug.log
+books/
+public/
+
+```
+
+> Note that we're not copying the `node_modules` directory into our container - this is because we'll be running `npm install` from within the container build process. Attempting to copy the `node_modules` from the host system into a container can cause errors since some packages need to be specifically built for certain operating systems. For instance, installing the `bcrypt` package on macOS and attempting to copy that module directly to an Ubuntu container will not work because `bcyrpt`relies on a binary that needs to be built specifically for each operating system.
+
+### 2.5 - Add Base Files
+
+In order to test out the configuration, we'll need to add some placeholder files to the app directories.
+
+Add this base HTML file at `public/index.html`
+
+```
+Hello World From The Frontend Container
+
+```
+
+Next, add the placeholder Node.js app file at `server/app.js`.
+
+```
+const Koa = require('koa')
+const app = new Koa()
+
+app.use(async (ctx, next) => {
+ ctx.body = 'Hello World From the Backend Container'
+})
+
+const port = process.env.PORT || 3000
+
+app.listen(port, err => {
+ if (err) console.error(err)
+ console.log(`App Listening on Port ${port}`)
+})
+
+```
+
+Finally, add our `package.json` Node app configuration.
+
+```
+{
+ "name": "guttenberg-search",
+ "version": "0.0.1",
+ "description": "Source code for Elasticsearch tutorial using 100 classic open source books.",
+ "scripts": {
+ "start": "node --inspect=0.0.0.0:9229 server/app.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/triestpa/guttenberg-search.git"
+ },
+ "author": "patrick.triest@gmail.com",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/triestpa/guttenberg-search/issues"
+ },
+ "homepage": "https://github.com/triestpa/guttenberg-search#readme",
+ "dependencies": {
+ "elasticsearch": "13.3.1",
+ "joi": "13.0.1",
+ "koa": "2.4.1",
+ "koa-joi-validate": "0.5.1",
+ "koa-router": "7.2.1"
+ }
+}
+
+```
+
+This file defines the application start command and the Node.js package dependencies.
+
+> Note - You don't have to run `npm install` - the dependencies will be installed inside the container when it is built.
+
+### 2.6 - Try it Out
+
+Everything is in place now to test out each component of the app. From the base directory, run `docker-compose build`, which will build our Node.js application container.
+
+
+
+Next, run `docker-compose up` to launch our entire application stack.
+
+
+
+> This step might take a few minutes since Docker has to download the base images for each container. In subsequent runs, starting the app should be nearly instantaneous, since the required images will have already been downloaded.
+
+Try visiting `localhost:8080` in your browser - you should see a simple "Hello World" webpage.
+
+
+
+Visit `localhost:3000` to verify that our Node server returns it's own "Hello World" message.
+
+
+
+Finally, visit `localhost:9200` to check that Elasticsearch is running. It should return information similar to this.
+
+```
+{
+ "name" : "SLTcfpI",
+ "cluster_name" : "docker-cluster",
+ "cluster_uuid" : "iId8e0ZeS_mgh9ALlWQ7-w",
+ "version" : {
+ "number" : "6.1.1",
+ "build_hash" : "bd92e7f",
+ "build_date" : "2017-12-17T20:23:25.338Z",
+ "build_snapshot" : false,
+ "lucene_version" : "7.1.0",
+ "minimum_wire_compatibility_version" : "5.6.0",
+ "minimum_index_compatibility_version" : "5.0.0"
+ },
+ "tagline" : "You Know, for Search"
+}
+
+```
+
+If all three URLs display data successfully, congrats! The entire containerized stack is running, so now we can move on to the fun part.
+
+### 3 - CONNECT TO ELASTICSEARCH
+
+The first thing that we'll need to do in our app is connect to our local Elasticsearch instance.
+
+### 3.0 - Add ES Connection Module
+
+Add the following Elasticsearch initialization code to a new file `server/connection.js`.
+
+```
+const elasticsearch = require('elasticsearch')
+
+// Core ES variables for this project
+const index = 'library'
+const type = 'novel'
+const port = 9200
+const host = process.env.ES_HOST || 'localhost'
+const client = new elasticsearch.Client({ host: { host, port } })
+
+/** Check the ES connection status */
+async function checkConnection () {
+ let isConnected = false
+ while (!isConnected) {
+ console.log('Connecting to ES')
+ try {
+ const health = await client.cluster.health({})
+ console.log(health)
+ isConnected = true
+ } catch (err) {
+ console.log('Connection Failed, Retrying...', err)
+ }
+ }
+}
+
+checkConnection()
+
+```
+
+Let's rebuild our Node app now that we've made changes, using `docker-compose build`. Next, run `docker-compose up -d` to start the application stack as a background daemon process.
+
+With the app started, run `docker exec gs-api "node" "server/connection.js"` on the command line in order to run our script within the container. You should see some system output similar to the following.
+
+```
+{ cluster_name: 'docker-cluster',
+ status: 'yellow',
+ timed_out: false,
+ number_of_nodes: 1,
+ number_of_data_nodes: 1,
+ active_primary_shards: 1,
+ active_shards: 1,
+ relocating_shards: 0,
+ initializing_shards: 0,
+ unassigned_shards: 1,
+ delayed_unassigned_shards: 0,
+ number_of_pending_tasks: 0,
+ number_of_in_flight_fetch: 0,
+ task_max_waiting_in_queue_millis: 0,
+ active_shards_percent_as_number: 50 }
+
+```
+
+Go ahead and remove the `checkConnection()` call at the bottom before moving on, since in our final app we'll be making that call from outside the connection module.
+
+### 3.1 - Add Helper Function To Reset Index
+
+In `server/connection.js` add the following function below `checkConnection`, in order to provide an easy way to reset our Elasticsearch index.
+
+```
+/** Clear the index, recreate it, and add mappings */
+async function resetIndex (index) {
+ if (await client.indices.exists({ index })) {
+ await client.indices.delete({ index })
+ }
+
+ await client.indices.create({ index })
+ await putBookMapping()
+}
+
+```
+
+### 3.2 - Add Book Schema
+
+Next, we'll want to add a "mapping" for the book data schema. Add the following function below `resetIndex` in `server/connection.js`.
+
+```
+/** Add book section schema mapping to ES */
+async function putBookMapping () {
+ const schema = {
+ title: { type: 'keyword' },
+ author: { type: 'keyword' },
+ location: { type: 'integer' },
+ text: { type: 'text' }
+ }
+
+ return client.indices.putMapping({ index, type, body: { properties: schema } })
+}
+
+```
+
+Here we are defining a mapping for the `book` index. An Elasticsearch `index` is roughly analogous to a SQL `table` or a MongoDB `collection`. Adding a mapping allows us to specify each field and datatype for the stored documents. Elasticsearch is schema-less, so we don't technically need to add a mapping, but doing so will give us more control over how the data is handled.
+
+For instance - we're assigning the `keyword` type to the "title" and "author" fields, and the `text` type to the "text" field. Doing so will cause the search engine to treat these string fields differently - During a search, the engine will search _within_ the `text` field for potential matches, whereas `keyword` fields will be matched based on their full content. This might seem like a minor distinction, but it can have a huge impact on the behavior and speed of different searches.
+
+Export the exposed properties and functions at the bottom of the file, so that they can be accessed by other modules in our app.
+
+```
+module.exports = {
+ client, index, type, checkConnection, resetIndex
+}
+
+```
+
+### 4 - LOAD THE RAW DATA
+
+We'll be using data from [Project Gutenberg][28] - an online effort dedicated to providing free, digital copies of books within the public domain. For this project, we'll be populating our library with 100 classic books, including texts such as _The Adventures of Sherlock Holmes_ , _Treasure Island_ , _The Count of Monte Cristo_ , _Around the World in 80 Days_ , _Romeo and Juliet_ , and _The Odyssey_ .
+
+
+
+### 4.1 - Download Book Files
+
+I've zipped the 100 books into a file that you can download here -
+[https://cdn.patricktriest.com/data/books.zip][29]
+
+Extract this file into a `books/` directory in your project.
+
+If you want, you can do this by using the following commands (requires [wget][30] and ["The Unarchiver" CLI][31]).
+
+```
+wget https://cdn.patricktriest.com/data/books.zip
+unar books.zip
+
+```
+
+### 4.2 - Preview A Book
+
+Try opening one of the book files, say `219-0.txt`. You'll notice that it starts with an open access license, followed by some lines identifying the book title, author, release dates, language and character encoding.
+
+```
+Title: Heart of Darkness
+
+Author: Joseph Conrad
+
+Release Date: February 1995 [EBook #219]
+Last Updated: September 7, 2016
+
+Language: English
+
+Character set encoding: UTF-8
+
+```
+
+After these lines comes `*** START OF THIS PROJECT GUTENBERG EBOOK HEART OF DARKNESS ***`, after which the book content actually starts.
+
+If you scroll to the end of the book you'll see the matching message `*** END OF THIS PROJECT GUTENBERG EBOOK HEART OF DARKNESS ***`, which is followed by a much more detailed version of the book's license.
+
+In the next steps, we'll programmatically parse the book metadata from this header and extract the book content from between the `*** START OF` and `***END OF` place markers.
+
+### 4.3 - Read Data Dir
+
+Let's write a script to read the content of each book and to add that data to Elasticsearch. We'll define a new Javascript file `server/load_data.js` in order to perform these operations.
+
+First, we'll obtain a list of every file within the `books/` data directory.
+
+Add the following content to `server/load_data.js`.
+
+```
+const fs = require('fs')
+const path = require('path')
+const esConnection = require('./connection')
+
+/** Clear ES index, parse and index all files from the books directory */
+async function readAndInsertBooks () {
+ try {
+ // Clear previous ES index
+ await esConnection.resetIndex()
+
+ // Read books directory
+ let files = fs.readdirSync('./books').filter(file => file.slice(-4) === '.txt')
+ console.log(`Found ${files.length} Files`)
+
+ // Read each book file, and index each paragraph in elasticsearch
+ for (let file of files) {
+ console.log(`Reading File - ${file}`)
+ const filePath = path.join('./books', file)
+ const { title, author, paragraphs } = parseBookFile(filePath)
+ await insertBookData(title, author, paragraphs)
+ }
+ } catch (err) {
+ console.error(err)
+ }
+}
+
+readAndInsertBooks()
+
+```
+
+We'll use a shortcut command to rebuild our Node.js app and update the running container.
+
+Run `docker-compose up -d --build` to update the application. This is a shortcut for running `docker-compose build` and `docker-compose up -d`.
+
+
+
+Run`docker exec gs-api "node" "server/load_data.js"` in order to run our `load_data` script within the container. You should see the Elasticsearch status output, followed by `Found 100 Books`.
+
+After this, the script will exit due to an error because we're calling a helper function (`parseBookFile`) that we have not yet defined.
+
+
+
+### 4.4 - Read Data File
+
+Next, we'll read the metadata and content for each book.
+
+Define a new function in `server/load_data.js`.
+
+```
+/** Read an individual book text file, and extract the title, author, and paragraphs */
+function parseBookFile (filePath) {
+ // Read text file
+ const book = fs.readFileSync(filePath, 'utf8')
+
+ // Find book title and author
+ const title = book.match(/^Title:\s(.+)$/m)[1]
+ const authorMatch = book.match(/^Author:\s(.+)$/m)
+ const author = (!authorMatch || authorMatch[1].trim() === '') ? 'Unknown Author' : authorMatch[1]
+
+ console.log(`Reading Book - ${title} By ${author}`)
+
+ // Find Guttenberg metadata header and footer
+ const startOfBookMatch = book.match(/^\*{3}\s*START OF (THIS|THE) PROJECT GUTENBERG EBOOK.+\*{3}$/m)
+ const startOfBookIndex = startOfBookMatch.index + startOfBookMatch[0].length
+ const endOfBookIndex = book.match(/^\*{3}\s*END OF (THIS|THE) PROJECT GUTENBERG EBOOK.+\*{3}$/m).index
+
+ // Clean book text and split into array of paragraphs
+ const paragraphs = book
+ .slice(startOfBookIndex, endOfBookIndex) // Remove Guttenberg header and footer
+ .split(/\n\s+\n/g) // Split each paragraph into it's own array entry
+ .map(line => line.replace(/\r\n/g, ' ').trim()) // Remove paragraph line breaks and whitespace
+ .map(line => line.replace(/_/g, '')) // Guttenberg uses "_" to signify italics. We'll remove it, since it makes the raw text look messy.
+ .filter((line) => (line && line.length !== '')) // Remove empty lines
+
+ console.log(`Parsed ${paragraphs.length} Paragraphs\n`)
+ return { title, author, paragraphs }
+}
+
+```
+
+This function performs a few important tasks.
+
+1. Read book text from the file system.
+
+2. Use regular expressions (check out [this post][1] for a primer on using regex) to parse the book title and author.
+
+3. Identify the start and end of the book content, by matching on the all-caps "Project Guttenberg" header and footer.
+
+4. Extract the book text content.
+
+5. Split each paragraph into its own array.
+
+6. Clean up the text and remove blank lines.
+
+As a return value, we'll form an object containing the book's title, author, and an array of paragraphs within the book.
+
+Run `docker-compose up -d --build` and `docker exec gs-api "node" "server/load_data.js"` again, and you should see the same output as before, this time with three extra lines at the end of the output.
+
+
+
+Success! Our script successfully parsed the title and author from the text file. The script will again end with an error since we still have to define one more helper function.
+
+### 4.5 - Index Datafile in ES
+
+As a final step, we'll bulk-upload each array of paragraphs into the Elasticsearch index.
+
+Add a new `insertBookData` function to `load_data.js`.
+
+```
+/** Bulk index the book data in Elasticsearch */
+async function insertBookData (title, author, paragraphs) {
+ let bulkOps = [] // Array to store bulk operations
+
+ // Add an index operation for each section in the book
+ for (let i = 0; i < paragraphs.length; i++) {
+ // Describe action
+ bulkOps.push({ index: { _index: esConnection.index, _type: esConnection.type } })
+
+ // Add document
+ bulkOps.push({
+ author,
+ title,
+ location: i,
+ text: paragraphs[i]
+ })
+
+ if (i > 0 && i % 500 === 0) { // Do bulk insert in 500 paragraph batches
+ await esConnection.client.bulk({ body: bulkOps })
+ bulkOps = []
+ console.log(`Indexed Paragraphs ${i - 499} - ${i}`)
+ }
+ }
+
+ // Insert remainder of bulk ops array
+ await esConnection.client.bulk({ body: bulkOps })
+ console.log(`Indexed Paragraphs ${paragraphs.length - (bulkOps.length / 2)} - ${paragraphs.length}\n\n\n`)
+}
+
+```
+
+This function will index each paragraph of the book, with author, title, and paragraph location metadata attached. We are inserting the paragraphs using a bulk operation, which is much faster than indexing each paragraph individually.
+
+> We're bulk indexing the paragraphs in batches, instead of inserting all of them at once. This was a last minute optimization which I added in order for the app to run on the low-ish memory (1.7 GB) host machine that serves `search.patricktriest.com`. If you have a reasonable amount of RAM (4+ GB), you probably don't need to worry about batching each bulk upload,
+
+Run `docker-compose up -d --build` and `docker exec gs-api "node" "server/load_data.js"` one more time - you should now see a full output of 100 books being parsed and inserted in Elasticsearch. This might take a minute or so.
+
+
+
+### 5 - SEARCH
+
+Now that Elasticsearch has been populated with one hundred books (amounting to roughly 230,000 paragraphs), let's try out some search queries.
+
+### 5.0 - Simple HTTP Query
+
+First, let's just query Elasticsearch directly using it's HTTP API.
+
+Visit this URL in your browser - `http://localhost:9200/library/_search?q=text:Java&pretty`
+
+Here, we are performing a bare-bones full-text search to find the word "Java" within our library of books.
+
+You should see a JSON response similar to the following.
+
+```
+{
+ "took" : 11,
+ "timed_out" : false,
+ "_shards" : {
+ "total" : 5,
+ "successful" : 5,
+ "skipped" : 0,
+ "failed" : 0
+ },
+ "hits" : {
+ "total" : 13,
+ "max_score" : 14.259304,
+ "hits" : [
+ {
+ "_index" : "library",
+ "_type" : "novel",
+ "_id" : "p_GwFWEBaZvLlaAUdQgV",
+ "_score" : 14.259304,
+ "_source" : {
+ "author" : "Charles Darwin",
+ "title" : "On the Origin of Species",
+ "location" : 1080,
+ "text" : "Java, plants of, 375."
+ }
+ },
+ {
+ "_index" : "library",
+ "_type" : "novel",
+ "_id" : "wfKwFWEBaZvLlaAUkjfk",
+ "_score" : 10.186235,
+ "_source" : {
+ "author" : "Edgar Allan Poe",
+ "title" : "The Works of Edgar Allan Poe",
+ "location" : 827,
+ "text" : "After many years spent in foreign travel, I sailed in the year 18-- , from the port of Batavia, in the rich and populous island of Java, on a voyage to the Archipelago of the Sunda islands. I went as passenger--having no other inducement than a kind of nervous restlessness which haunted me as a fiend."
+ }
+ },
+ ...
+ ]
+ }
+}
+
+```
+
+The Elasticseach HTTP interface is useful for testing that our data is inserted successfully, but exposing this API directly to the web app would be a huge security risk. The API exposes administrative functionality (such as directly adding and deleting documents), and should ideally not ever be exposed publicly. Instead, we'll write a simple Node.js API to receive requests from the client, and make the appropriate query (within our private local network) to Elasticsearch.
+
+### 5.1 - Query Script
+
+Let's now try querying Elasticsearch from our Node.js application.
+
+Create a new file, `server/search.js`.
+
+```
+const { client, index, type } = require('./connection')
+
+module.exports = {
+ /** Query ES index for the provided term */
+ queryTerm (term, offset = 0) {
+ const body = {
+ from: offset,
+ query: { match: {
+ text: {
+ query: term,
+ operator: 'and',
+ fuzziness: 'auto'
+ } } },
+ highlight: { fields: { text: {} } }
+ }
+
+ return client.search({ index, type, body })
+ }
+}
+
+```
+
+Our search module defines a simple `search` function, which will perform a `match`query using the input term.
+
+Here are query fields broken down -
+
+* `from` - Allows us to paginate the results. Each query returns 10 results by default, so specifying `from: 10` would allow us to retrieve results 10-20.
+
+* `query` - Where we specify the actual term that we are searching for.
+
+* `operator` - We can modify the search behavior; in this case, we're using the "and" operator to prioritize results that contain all of the tokens (words) in the query.
+
+* `fuzziness` - Adjusts tolerance for spelling mistakes, `auto` defaults to `fuzziness: 2`. A higher fuzziness will allow for more corrections in result hits. For instance, `fuzziness: 1` would allow `Patricc` to return `Patrick` as a match.
+
+* `highlights` - Returns an extra field with the result, containing HTML to display the exact text subset and terms that were matched with the query.
+
+Feel free to play around with these parameters, and to customize the search query further by exploring the [Elastic Full-Text Query DSL][32].
+
+### 6 - API
+
+Let's write a quick HTTP API in order to access our search functionality from a frontend app.
+
+### 6.0 - API Server
+
+Replace our existing `server/app.js` file with the following contents.
+
+```
+const Koa = require('koa')
+const Router = require('koa-router')
+const joi = require('joi')
+const validate = require('koa-joi-validate')
+const search = require('./search')
+
+const app = new Koa()
+const router = new Router()
+
+// Log each request to the console
+app.use(async (ctx, next) => {
+ const start = Date.now()
+ await next()
+ const ms = Date.now() - start
+ console.log(`${ctx.method} ${ctx.url} - ${ms}`)
+})
+
+// Log percolated errors to the console
+app.on('error', err => {
+ console.error('Server Error', err)
+})
+
+// Set permissive CORS header
+app.use(async (ctx, next) => {
+ ctx.set('Access-Control-Allow-Origin', '*')
+ return next()
+})
+
+// ADD ENDPOINTS HERE
+
+const port = process.env.PORT || 3000
+
+app
+ .use(router.routes())
+ .use(router.allowedMethods())
+ .listen(port, err => {
+ if (err) throw err
+ console.log(`App Listening on Port ${port}`)
+ })
+
+```
+
+This code will import our server dependencies and set up simple logging and error handling for a [Koa.js][33] Node API server.
+
+### 6.1 - Link endpoint with queries
+
+Next, we'll add an endpoint to our server in order to expose our Elasticsearch query function.
+
+Insert the following code below the `// ADD ENDPOINTS HERE` comment in `server/app.js`.
+
+```
+/**
+ * GET /search
+ * Search for a term in the library
+ */
+router.get('/search', async (ctx, next) => {
+ const { term, offset } = ctx.request.query
+ ctx.body = await search.queryTerm(term, offset)
+ }
+)
+
+```
+
+Restart the app using `docker-compose up -d --build`. In your browser, try calling the search endpoint. For example, this request would search the entire library for passages mentioning "Java" - `http://localhost:3000/search?term=java`
+
+The result will look quite similar to the response from earlier when we called the Elasticsearch HTTP interface directly.
+
+```
+{
+ "took": 242,
+ "timed_out": false,
+ "_shards": {
+ "total": 5,
+ "successful": 5,
+ "skipped": 0,
+ "failed": 0
+ },
+ "hits": {
+ "total": 93,
+ "max_score": 13.356944,
+ "hits": [{
+ "_index": "library",
+ "_type": "novel",
+ "_id": "eHYHJmEBpQg9B4622421",
+ "_score": 13.356944,
+ "_source": {
+ "author": "Charles Darwin",
+ "title": "On the Origin of Species",
+ "location": 1080,
+ "text": "Java, plants of, 375."
+ },
+ "highlight": {
+ "text": ["Java, plants of, 375."]
+ }
+ }, {
+ "_index": "library",
+ "_type": "novel",
+ "_id": "2HUHJmEBpQg9B462xdNg",
+ "_score": 9.030668,
+ "_source": {
+ "author": "Unknown Author",
+ "title": "The King James Bible",
+ "location": 186,
+ "text": "10:4 And the sons of Javan; Elishah, and Tarshish, Kittim, and Dodanim."
+ },
+ "highlight": {
+ "text": ["10:4 And the sons of Javan; Elishah, and Tarshish, Kittim, and Dodanim."]
+ }
+ }
+ ...
+ ]
+ }
+}
+
+```
+
+### 6.2 - Input validation
+
+This endpoint is still brittle - we are not doing any checks on the request parameters, so invalid or missing values would result in a server error.
+
+We'll add some middleware to the endpoint in order to validate input parameters using [Joi][34] and the [Koa-Joi-Validate][35] library.
+
+```
+/**
+ * GET /search
+ * Search for a term in the library
+ * Query Params -
+ * term: string under 60 characters
+ * offset: positive integer
+ */
+router.get('/search',
+ validate({
+ query: {
+ term: joi.string().max(60).required(),
+ offset: joi.number().integer().min(0).default(0)
+ }
+ }),
+ async (ctx, next) => {
+ const { term, offset } = ctx.request.query
+ ctx.body = await search.queryTerm(term, offset)
+ }
+)
+
+```
+
+Now, if you restart the server and make a request with a missing term(`http://localhost:3000/search`), you will get back an HTTP 400 error with a relevant message, such as `Invalid URL Query - child "term" fails because ["term" is required]`.
+
+To view live logs from the Node app, you can run `docker-compose logs -f api`.
+
+### 7 - FRONT-END APPLICATION
+
+Now that our `/search` endpoint is in place, let's wire up a simple web app to test out the API.
+
+### 7.0 - Vue.js App
+
+We'll be using Vue.js to coordinate our frontend.
+
+Add a new file, `/public/app.js`, to hold our Vue.js application code.
+
+```
+const vm = new Vue ({
+ el: '#vue-instance',
+ data () {
+ return {
+ baseUrl: 'http://localhost:3000', // API url
+ searchTerm: 'Hello World', // Default search term
+ searchDebounce: null, // Timeout for search bar debounce
+ searchResults: [], // Displayed search results
+ numHits: null, // Total search results found
+ searchOffset: 0, // Search result pagination offset
+
+ selectedParagraph: null, // Selected paragraph object
+ bookOffset: 0, // Offset for book paragraphs being displayed
+ paragraphs: [] // Paragraphs being displayed in book preview window
+ }
+ },
+ async created () {
+ this.searchResults = await this.search() // Search for default term
+ },
+ methods: {
+ /** Debounce search input by 100 ms */
+ onSearchInput () {
+ clearTimeout(this.searchDebounce)
+ this.searchDebounce = setTimeout(async () => {
+ this.searchOffset = 0
+ this.searchResults = await this.search()
+ }, 100)
+ },
+ /** Call API to search for inputted term */
+ async search () {
+ const response = await axios.get(`${this.baseUrl}/search`, { params: { term: this.searchTerm, offset: this.searchOffset } })
+ this.numHits = response.data.hits.total
+ return response.data.hits.hits
+ },
+ /** Get next page of search results */
+ async nextResultsPage () {
+ if (this.numHits > 10) {
+ this.searchOffset += 10
+ if (this.searchOffset + 10 > this.numHits) { this.searchOffset = this.numHits - 10}
+ this.searchResults = await this.search()
+ document.documentElement.scrollTop = 0
+ }
+ },
+ /** Get previous page of search results */
+ async prevResultsPage () {
+ this.searchOffset -= 10
+ if (this.searchOffset < 0) { this.searchOffset = 0 }
+ this.searchResults = await this.search()
+ document.documentElement.scrollTop = 0
+ }
+ }
+})
+
+```
+
+The app is pretty simple - we're just defining some shared data properties, and adding methods to retrieve and paginate through search results. The search input is debounced by 100ms, to prevent the API from being called with every keystroke.
+
+Explaining how Vue.js works is outside the scope of this tutorial, but this probably won't look too crazy if you've used Angular or React. If you're completely unfamiliar with Vue, and if you want something quick to get started with, I would recommend the official quick-start guide - [https://vuejs.org/v2/guide/][36]
+
+### 7.1 - HTML
+
+Replace our placeholder `/public/index.html` file with the following contents, in order to load our Vue.js app and to layout a basic search interface.
+
+```
+
+
+
+
+ Elastic Library
+
+
+
+
+
+
+
+
+
+
+```
+
+Restart the app server (`docker-compose up -d --build`) again and open up `localhost:8080`. When you click on a search result, you are now able to view the surrounding paragraphs. You can now even read the rest of the book to completion if you're entertained by what you find.
+
+
+
+Congrats, you've completed the tutorial application!
+
+Feel free to compare your local result against the completed sample hosted here - [https://search.patricktriest.com/][37]
+
+### 9 - DISADVANTAGES OF ELASTICSEARCH
+
+### 9.0 - Resource Hog
+
+Elasticsearch is computationally demanding. The [official recommendation][38] is to run ES on a machine with 64 GB of RAM, and they strongly discourage running it on anything with under 8 GB of RAM. Elasticsearch is an _in-memory_ datastore, which allows it to return results extremely quickly, but also results in a very significant system memory footprint. In production, [it is strongly recommended to run multiple Elasticsearch nodes in a cluster][39] to allow for high server availability, automatic sharding, and data redundancy in case of a node failure.
+
+I've got our tutorial application running on a $15/month GCP compute instance (at [search.patricktriest.com][40]) with 1.7 GB of RAM, and it _just barely_ is able to run the Elasticsearch node; sometimes the entire machine freezes up during the initial data-loading step. Elasticsearch is, in my experience, much more of a resource hog than more traditional databases such as PostgreSQL and MongoDB, and can be significantly more expensive to host as a result.
+
+### 9.1 - Syncing with Databases
+
+In most applications, storing all of the data in Elasticsearch is not an ideal option. It is possible to use ES as the primary transactional database for an app, but this is generally not recommended due to the lack of ACID compliance in Elasticsearch, which can lead to lost write operations when ingesting data at scale. In many cases, ES serves a more specialized role, such as powering the text searching features of the app. This specialized use requires that some of the data from the primary database is replicated to the Elasticsearch instance.
+
+For instance, let's imagine that we're storing our users in a PostgreSQL table, but using Elasticsearch to power our user-search functionality. If a user, "Albert", decides to change his name to "Al", we'll need this change to be reflected in both our primary PostgreSQL database and in our auxiliary Elasticsearch cluster.
+
+This can be a tricky integration to get right, and the best answer will depend on your existing stack. There are a multitude of open-source options available, from [a process to watch a MongoDB operation log][41] and automatically sync detected changes to ES, to a [PostgresSQL plugin][42] to create a custom PSQL-based index that communicates automatically with Elasticsearch.
+
+If none of the available pre-built options work, you could always just add some hooks into your server code to update the Elasticsearch index manually based on database changes. I would consider this final option to be a last resort, since keeping ES in sync using custom business logic can be complex, and is likely to introduce numerous bugs to the application.
+
+The need to sync Elasticsearch with a primary database is more of an architectural complexity than it is a specific weakness of ES, but it's certainly worth keeping in mind when considering the tradeoffs of adding a dedicated search engine to your app.
+
+### CONCLUSION
+
+Full-text search is one of the most important features in many modern applications - and is one of the most difficult to implement well. Elasticsearch is a fantastic option for adding fast and customizable text search to your application, but there are alternatives. [Apache Solr][43] is a similar open source search platform that is built on Apache Lucene - the same library at the core of Elasticsearch. [Algolia][44] is a search-as-a-service web platform which is growing quickly in popularity and is likely to be easier to get started with for beginners (but as a tradeoff is less customizable and can get quite expensive).
+
+"Search-bar" style features are far from the only use-case for Elasticsearch. ES is also a very common tool for log storage and analysis, commonly used in an ELK (Elasticsearch, Logstash, Kibana) stack configuration. The flexible full-text search allowed by Elasticsearch can also be very useful for a wide variety of data science tasks - such as correcting/standardizing the spellings of entities within a dataset or searching a large text dataset for similar phrases.
+
+Here are some ideas for your own projects.
+
+* Add more of your favorite books to our tutorial app and create your own private library search engine.
+
+* Create an academic plagiarism detection engine by indexing papers from [Google Scholar][2].
+
+* Build a spell checking application by indexing every word in the dictionary to Elasticsearch.
+
+* Build your own Google-competitor internet search engine by loading the [Common Crawl Corpus][3] into Elasticsearch (caution - with over 5 billion pages, this can be a very expensive dataset play with).
+
+* Use Elasticsearch for journalism: search for specific names and terms in recent large-scale document leaks such as the [Panama Papers][4] and [Paradise Papers][5].
+
+The source code for this tutorial application is 100% open-source and can be found at the GitHub repository here - [https://github.com/triestpa/guttenberg-search][45]
+
+I hope you enjoyed the tutorial! Please feel free to post any thoughts, questions, or criticisms in the comments below.
+
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Full-stack engineer, data enthusiast, insatiable learner, obsessive builder. You can find me wandering on a mountain trail, pretending not to be lost.
+
+-------------
+
+
+via: https://blog.patricktriest.com/text-search-docker-elasticsearch/
+
+作者:[Patrick Triest][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://blog.patricktriest.com/author/patrick/
+[1]:https://blog.patricktriest.com/you-should-learn-regex/
+[2]:https://scholar.google.com/
+[3]:https://aws.amazon.com/public-datasets/common-crawl/
+[4]:https://en.wikipedia.org/wiki/Panama_Papers
+[5]:https://en.wikipedia.org/wiki/Paradise_Papers
+[6]:https://search.patricktriest.com/
+[7]:https://github.com/triestpa/guttenberg-search
+[8]:https://www.postgresql.org/
+[9]:https://www.mongodb.com/
+[10]:https://www.elastic.co/
+[11]:https://www.docker.com/
+[12]:https://www.uber.com/
+[13]:https://www.spotify.com/us/
+[14]:https://www.adp.com/
+[15]:https://www.paypal.com/us/home
+[16]:https://nodejs.org/en/
+[17]:http://koajs.com/
+[18]:https://vuejs.org/
+[19]:https://www.elastic.co/
+[20]:https://lucene.apache.org/core/
+[21]:https://www.elastic.co/guide/en/elasticsearch/guide/2.x/getting-started.html
+[22]:https://en.wikipedia.org/wiki/B-tree
+[23]:https://www.docker.com/
+[24]:https://www.docker.com/
+[25]:https://docs.docker.com/compose/
+[26]:https://docs.docker.com/engine/installation/
+[27]:https://docs.docker.com/compose/install/
+[28]:https://www.gutenberg.org/
+[29]:https://cdn.patricktriest.com/data/books.zip
+[30]:https://www.gnu.org/software/wget/
+[31]:https://theunarchiver.com/command-line
+[32]:https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html
+[33]:http://koajs.com/
+[34]:https://github.com/hapijs/joi
+[35]:https://github.com/triestpa/koa-joi-validate
+[36]:https://vuejs.org/v2/guide/
+[37]:https://search.patricktriest.com/
+[38]:https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html
+[39]:https://www.elastic.co/guide/en/elasticsearch/guide/2.x/distributed-cluster.html
+[40]:https://search.patricktriest.com/
+[41]:https://github.com/mongodb-labs/mongo-connector
+[42]:https://github.com/zombodb/zombodb
+[43]:https://lucene.apache.org/solr/
+[44]:https://www.algolia.com/
+[45]:https://github.com/triestpa/guttenberg-search
+[46]:https://blog.patricktriest.com/tag/guides/
+[47]:https://blog.patricktriest.com/tag/javascript/
+[48]:https://blog.patricktriest.com/tag/nodejs/
+[49]:https://blog.patricktriest.com/tag/web-development/
+[50]:https://blog.patricktriest.com/tag/devops/
\ No newline at end of file
diff --git a/sources/tech/20180125 Building a Linux-based HPC system on the Raspberry.md b/sources/tech/20180125 Building a Linux-based HPC system on the Raspberry.md
new file mode 100644
index 0000000000..eab5ac90b3
--- /dev/null
+++ b/sources/tech/20180125 Building a Linux-based HPC system on the Raspberry.md
@@ -0,0 +1,153 @@
+Building a Linux-based HPC system on the Raspberry Pi with Ansible
+============================================================
+
+### Create a high-performance computing cluster with low-cost hardware and open source software.
+
+
+Image by : opensource.com
+
+In my [previous article for Opensource.com][14], I introduced the [OpenHPC][15] project, which aims to accelerate innovation in high-performance computing (HPC). This article goes a step further by using OpenHPC's capabilities to build a small HPC system. To call it an _HPC system_ might sound bigger than it is, so maybe it is better to say this is a system based on the [Cluster Building Recipes][16] published by the OpenHPC project.
+
+The resulting cluster consists of two Raspberry Pi 3 systems acting as compute nodes and one virtual machine acting as the master node:
+
+
+
+
+My master node is running CentOS on x86_64 and my compute nodes are running a slightly modified CentOS on aarch64.
+
+This is what the setup looks in real life:
+
+
+
+
+To set up my system like an HPC system, I followed some of the steps from OpenHPC's Cluster Building Recipes [install guide for CentOS 7.4/aarch64 + Warewulf + Slurm][17] (PDF). This recipe includes provisioning instructions using [Warewulf][18]; because I manually installed my three systems, I skipped the Warewulf parts and created an [Ansible playbook][19] for the steps I took.
+
+
+Once my cluster was set up by the [Ansible][26] playbooks, I could start to submit jobs to my resource manager. The resource manager, [Slurm][27] in my case, is the instance in the cluster that decides where and when my jobs are executed. One possibility to start a simple job on the cluster is:
+```
+[ohpc@centos01 ~]$ srun hostname
+calvin
+```
+
+If I need more resources, I can tell Slurm that I want to run my command on eight CPUs:
+
+```
+[ohpc@centos01 ~]$ srun -n 8 hostname
+hobbes
+hobbes
+hobbes
+hobbes
+calvin
+calvin
+calvin
+calvin
+```
+
+In the first example, Slurm ran the specified command (`hostname`) on a single CPU, and in the second example Slurm ran the command on eight CPUs. One of my compute nodes is named `calvin` and the other is named `hobbes`; that can be seen in the output of the above commands. Each of the compute nodes is a Raspberry Pi 3 with four CPU cores.
+
+Another way to submit jobs to my cluster is the command `sbatch`, which can be used to execute scripts with the output written to a file instead of my terminal.
+
+```
+[ohpc@centos01 ~]$ cat script1.sh
+#!/bin/sh
+date
+hostname
+sleep 10
+date
+[ohpc@centos01 ~]$ sbatch script1.sh
+Submitted batch job 101
+```
+
+This will create an output file called `slurm-101.out` with the following content:
+
+```
+Mon 11 Dec 16:42:31 UTC 2017
+calvin
+Mon 11 Dec 16:42:41 UTC 2017
+```
+
+To demonstrate the basic functionality of the resource manager, simple and serial command line tools are suitable—but a bit boring after doing all the work to set up an HPC-like system.
+
+A more interesting application is running an [Open MPI][20] parallelized job on all available CPUs on the cluster. I'm using an application based on [Game of Life][21], which was used in a [video][22] called "Running Game of Life across multiple architectures with Red Hat Enterprise Linux." In addition to the previously used MPI-based Game of Life implementation, the version now running on my cluster colors the cells for each involved host differently. The following script starts the application interactively with a graphical output:
+
+```
+$ cat life.mpi
+#!/bin/bash
+
+module load gnu6 openmpi3
+
+if [[ "$SLURM_PROCID" != "0" ]]; then
+ exit
+fi
+
+mpirun ./mpi_life -a -p -b
+```
+
+I start the job with the following command, which tells Slurm to allocate eight CPUs for the job:
+
+```
+$ srun -n 8 --x11 life.mpi
+```
+
+For demonstration purposes, the job has a graphical interface that shows the current result of the calculation:
+
+
+
+
+The position of the red cells is calculated on one of the compute nodes, and the green cells are calculated on the other compute node. I can also tell the Game of Life program to color the cell for each used CPU (there are four per compute node) differently, which leads to the following output:
+
+
+
+
+Thanks to the installation recipes and the software packages provided by OpenHPC, I was able to set up two compute nodes and a master node in an HPC-type configuration. I can submit jobs to my resource manager, and I can use the software provided by OpenHPC to start MPI applications utilizing all my Raspberry Pis' CPUs.
+
+* * *
+
+ _To learn more about using OpenHPC to build a Raspberry Pi cluster, please attend Adrian Reber's talks at [DevConf.cz 2018][10], January 26-28, in Brno, Czech Republic, and at the [CentOS Dojo 2018][11], on February 2, in Brussels._
+
+### About the author
+
+ [][23] Adrian Reber - Adrian is a Senior Software Engineer at Red Hat and is migrating processes at least since 2010\. He started to migrate processes in a high performance computing environment and at some point he migrated so many processes that he got a PhD for that and since he joined Red Hat he started to migrate containers. Occasionally he still migrates single processes and is still interested in high performance computing topics.[More about me][12]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/how-build-hpc-system-raspberry-pi-and-openhpc
+
+作者:[Adrian Reber ][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/adrianreber
+[1]:https://opensource.com/resources/what-are-linux-containers?utm_campaign=containers&intcmp=70160000000h1s6AAA
+[2]:https://opensource.com/resources/what-docker?utm_campaign=containers&intcmp=70160000000h1s6AAA
+[3]:https://opensource.com/resources/what-is-kubernetes?utm_campaign=containers&intcmp=70160000000h1s6AAA
+[4]:https://developers.redhat.com/blog/2016/01/13/a-practical-introduction-to-docker-container-terminology/?utm_campaign=containers&intcmp=70160000000h1s6AAA
+[5]:https://opensource.com/file/384031
+[6]:https://opensource.com/file/384016
+[7]:https://opensource.com/file/384021
+[8]:https://opensource.com/file/384026
+[9]:https://opensource.com/article/18/1/how-build-hpc-system-raspberry-pi-and-openhpc?rate=l9n6B6qRcR20LJyXEoUoWEZ4mb2nDc9sFZ1YSPc60vE
+[10]:https://devconfcz2018.sched.com/event/DJYi/openhpc-introduction
+[11]:https://wiki.centos.org/Events/Dojo/Brussels2018
+[12]:https://opensource.com/users/adrianreber
+[13]:https://opensource.com/user/188446/feed
+[14]:https://opensource.com/article/17/11/openhpc
+[15]:https://openhpc.community/
+[16]:https://openhpc.community/downloads/
+[17]:https://github.com/openhpc/ohpc/releases/download/v1.3.3.GA/Install_guide-CentOS7-Warewulf-SLURM-1.3.3-aarch64.pdf
+[18]:https://en.wikipedia.org/wiki/Warewulf
+[19]:http://people.redhat.com/areber/openhpc/ansible/
+[20]:https://www.open-mpi.org/
+[21]:https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
+[22]:https://www.youtube.com/watch?v=n8DvxMcOMXk
+[23]:https://opensource.com/users/adrianreber
+[24]:https://opensource.com/users/adrianreber
+[25]:https://opensource.com/users/adrianreber
+[26]:https://www.ansible.com/
+[27]:https://slurm.schedmd.com/
+[28]:https://opensource.com/tags/raspberry-pi
+[29]:https://opensource.com/tags/programming
+[30]:https://opensource.com/tags/linux
+[31]:https://opensource.com/tags/ansible
\ No newline at end of file
diff --git a/sources/tech/20180125 Keep Accurate Time on Linux with NTP.md b/sources/tech/20180125 Keep Accurate Time on Linux with NTP.md
new file mode 100644
index 0000000000..817931c2a4
--- /dev/null
+++ b/sources/tech/20180125 Keep Accurate Time on Linux with NTP.md
@@ -0,0 +1,146 @@
+Keep Accurate Time on Linux with NTP
+======
+
+
+
+How to keep the correct time and keep your computers synchronized without abusing time servers, using NTP and systemd.
+
+### What Time is It?
+
+Linux is funky when it comes to telling the time. You might think that the `time` tells the time, but it doesn't because it is a timer that measures how long a process runs. To get the time, you run the `date` command, and to view more than one date, you use `cal`. Timestamps on files are also a source of confusion as they are typically displayed in two different ways, depending on your distro defaults. This example is from Ubuntu 16.04 LTS:
+```
+$ ls -l
+drwxrwxr-x 5 carla carla 4096 Mar 27 2017 stuff
+drwxrwxr-x 2 carla carla 4096 Dec 8 11:32 things
+-rw-rw-r-- 1 carla carla 626052 Nov 21 12:07 fatpdf.pdf
+-rw-rw-r-- 1 carla carla 2781 Apr 18 2017 oddlots.txt
+
+```
+
+Some display the year, some display the time, which makes ordering your files rather a mess. The GNU default is files dated within the last six months display the time instead of the year. I suppose there is a reason for this. If your Linux does this, try `ls -l --time-style=long-iso` to display the timestamps all the same way, sorted alphabetically. See [How to Change the Linux Date and Time: Simple Commands][1] to learn all manner of fascinating ways to manage the time on Linux.
+
+### Check Current Settings
+
+NTP, the network time protocol, is the old-fashioned way of keeping correct time on computers. `ntpd`, the NTP daemon, periodically queries a public time server and adjusts your system time as needed. It's a simple lightweight protocol that is easy to set up for basic use. Systemd has barged into NTP territory with the `systemd-timesyncd.service`, which acts as a client to `ntpd`.
+
+Before messing with NTP, let's take a minute to check that current time settings are correct.
+
+There are (at least) two timekeepers on your system: system time, which is managed by the Linux kernel, and the hardware clock on your motherboard, which is also called the real-time clock (RTC). When you enter your system BIOS, you see the hardware clock time and you can change its settings. When you install a new Linux, and in some graphical time managers, you are asked if you want your RTC set to the UTC (Coordinated Universal Time) zone. It should be set to UTC, because all time zone and daylight savings time calculations are based on UTC. Use the `hwclock` command to check:
+```
+$ sudo hwclock --debug
+hwclock from util-linux 2.27.1
+Using the /dev interface to the clock.
+Hardware clock is on UTC time
+Assuming hardware clock is kept in UTC time.
+Waiting for clock tick...
+...got clock tick
+Time read from Hardware Clock: 2018/01/22 22:14:31
+Hw clock time : 2018/01/22 22:14:31 = 1516659271 seconds since 1969
+Time since last adjustment is 1516659271 seconds
+Calculated Hardware Clock drift is 0.000000 seconds
+Mon 22 Jan 2018 02:14:30 PM PST .202760 seconds
+
+```
+
+"Hardware clock is kept in UTC time" confirms that your RTC is on UTC, even though it translates the time to your local time. If it were set to local time it would report "Hardware clock is kept in local time."
+
+You should have a `/etc/adjtime` file. If you don't, sync your RTC to system time:
+```
+$ sudo hwclock -w
+
+```
+
+This should generate the file, and the contents should look like this example:
+```
+$ cat /etc/adjtime
+0.000000 1516661953 0.000000
+1516661953
+UTC
+
+```
+
+The new-fangled systemd way is to run `timedatectl`, which does not need root permissions:
+```
+$ timedatectl
+ Local time: Mon 2018-01-22 14:17:51 PST
+ Universal time: Mon 2018-01-22 22:17:51 UTC
+ RTC time: Mon 2018-01-22 22:17:51
+ Time zone: America/Los_Angeles (PST, -0800)
+ Network time on: yes
+NTP synchronized: yes
+ RTC in local TZ: no
+
+```
+
+"RTC in local TZ: no" confirms that it is on UTC time. What if it is on local time? There are, as always, multiple ways to change it. The easy way is with a nice graphical configuration tool, like YaST in openSUSE. You can use `timedatectl`:
+```
+$ timedatectl set-local-rtc 0
+```
+
+Or edit `/etc/adjtime`, replacing UTC with LOCAL.
+
+### systemd-timesyncd Client
+
+Now I'm tired, and we've just gotten to the good part. Who knew timekeeping was so complex? We haven't even scratched the surface; read `man 8 hwclock` to get an idea of how time is kept on computers.
+
+Systemd provides the `systemd-timesyncd.service` client, which queries remote time servers and adjusts your system time. Configure your servers in `/etc/systemd/timesyncd.conf`. Most Linux distributions provide a default configuration that points to time servers that they maintain, like Fedora:
+```
+[Time]
+#NTP=
+#FallbackNTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org
+
+```
+
+You may enter any other servers you desire, such as your own local NTP server, on the `NTP=` line in a space-delimited list. (Remember to uncomment this line.) Anything you put on the `NTP=` line overrides the fallback.
+
+What if you are not using systemd? Then you need only NTP.
+
+### Setting up NTP Server and Client
+
+It is a good practice to set up your own LAN NTP server, so that you are not pummeling public NTP servers from all of your computers. On most Linuxes NTP comes in the `ntp` package, and most of them provide `/etc/ntp.conf` to configure the service. Consult [NTP Pool Time Servers][2] to find the NTP server pool that is appropriate for your region. Then enter 4-5 servers in your `/etc/ntp.conf` file, with each server on its own line:
+```
+driftfile /var/ntp.drift
+logfile /var/log/ntp.log
+server 0.europe.pool.ntp.org
+server 1.europe.pool.ntp.org
+server 2.europe.pool.ntp.org
+server 3.europe.pool.ntp.org
+
+```
+
+The `driftfile` tells `ntpd` where to store the information it needs to quickly synchronize your system clock with the time servers at startup, and your logs should have their own home instead of getting dumped into the syslog. Use your Linux distribution defaults for these files if it provides them.
+
+Now start the daemon; on most Linuxes this is `sudo systemctl start ntpd`. Let it run for a few minutes, then check its status:
+```
+$ ntpq -p
+ remote refid st t when poll reach delay offset jitter
+==============================================================
++dev.smatwebdesi 192.168.194.89 3 u 25 64 37 92.456 -6.395 18.530
+*chl.la 127.67.113.92 2 u 23 64 37 75.175 8.820 8.230
++four0.fairy.mat 35.73.197.144 2 u 22 64 37 116.272 -10.033 40.151
+-195.21.152.161 195.66.241.2 2 u 27 64 37 107.559 1.822 27.346
+
+```
+
+I have no idea what any of that means, other than your daemon is talking to the remote time servers, and that is what you want. To permanently enable it, run `sudo systemctl enable ntpd`. If your Linux doesn't use systemd then it is your homework to figure out how to run `ntpd`.
+
+Now you can set up `systemd-timesyncd` on your other LAN hosts to use your local NTP server, or install NTP on them and enter your local server in their `/etc/ntp.conf` files.
+
+NTP servers take a beating, and demand continually increases. You can help by running your own public NTP server. Come back next week to learn how.
+
+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/1/keep-accurate-time-linux-ntp
+
+作者:[CARLA SCHRODER][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/cschroder
+[1]:https://www.linux.com/learn/how-change-linux-date-and-time-simple-commands
+[2]:http://support.ntp.org/bin/view/Servers/NTPPoolServers
+[3]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180126 An introduction to the Web Simple Perl module a minimalist web framework.md b/sources/tech/20180126 An introduction to the Web Simple Perl module a minimalist web framework.md
new file mode 100644
index 0000000000..ab8c29b2b6
--- /dev/null
+++ b/sources/tech/20180126 An introduction to the Web Simple Perl module a minimalist web framework.md
@@ -0,0 +1,106 @@
+An introduction to the Web::Simple Perl module, a minimalist web framework
+============================================================
+
+### Perl module Web::Simple is easy to learn and packs a big enough punch for a variety of one-offs and smaller services.
+
+
+
+Image credits : [You as a Machine][10]. Modified by Rikki Endsley. [CC BY-SA 2.0][11].
+
+One of the more-prominent members of the Perl community is [Matt Trout][12], technical director at [Shadowcat Systems][13]. He's been building core tools for Perl applications for years, including being a co-maintaner of the [Catalyst][14] MVC (Model, View, Controller) web framework, creator of the [DBIx::Class][15] object-management system, and much more. In person, he's energetic, interesting, brilliant, and sometimes hard to keep up with. When Matt writes code…well, think of a runaway chainsaw, with the trigger taped down and the safety features disabled. He's off and running, and you never quite know what will come out. Two things are almost certain: the module will precisely fit the purpose Matt has in mind, and it will show up on CPAN for others to use.
+
+
+One of Matt's special-purpose modules is [Web::Simple][23]. Touted as "a quick and easy way to build simple web applications," it is a stripped-down, minimalist web framework, with an easy to learn interface. Web::Simple is not at all designed for a large-scale application; however, it may be ideal for a small tool that does one or two things in a lower-traffic environment. I can also envision it being used for rapid prototyping if you wanted to create quick wireframes of a new application for demonstrations.
+
+### Installation, and a quick "Howdy!"
+
+You can install the module using `cpan` or `cpanm`. Once you've got it installed, you're ready to write simple web apps without having to hassle with managing the connections or any of that—just your functionality. Here's a quick example:
+
+```
+#!/usr/bin/perl
+package HelloReader;
+use Web::Simple;
+
+sub dispatch_request {
+ GET => sub {
+ [ 200, [ 'Content-type', 'text/plain' ], [ 'Howdy, Opensource.com reader!' ] ]
+ },
+ '' => sub {
+ [ 405, [ 'Content-type', 'text/plain' ], [ 'You cannot do that, friend. Sorry.' ] ]
+ }
+}
+
+HelloReader->run_if_script;
+```
+
+There are a couple of things to notice right off. For one, I didn't `use strict` and `use warnings` like I usually would. Web::Simple imports those for you, so you don't have to. It also imports [Moo][16], a minimalist OO framework, so if you know Moo and want to use it here, you can! The heart of the system lies in the `dispatch_request`method, which you must define in your application. Each entry in the method is a match string, followed by a subroutine to respond if that string matches. The subroutine must return an array reference containing status, headers, and content of the reply to the request.
+
+### Matching
+
+The matching system in Web::Simple is powerful, allowing for complicated matches, passing parameters in a URL, query parameters, and extension matches, in pretty much any combination you want. As you can see in the example above, starting with a capital letter will match on the request method, and you can combine that with a path match easily:
+
+```
+'GET + /person/*' => sub {
+ my ($self, $person) = @_;
+ # write some code to retrieve and display a person
+ },
+'POST + /person/* + %*' => sub {
+ my ($self, $person, $params) = @_;
+ # write some code to modify a person, perhaps
+ }
+```
+
+In the latter case, the third part of the match indicates that we should pick up all the POST parameters and put them in a hashref called `$params` for use by the subroutine. Using `?` instead of `%` in that part of the match would pick up query parameters, as normally used in a GET request. There's also a useful exported subroutine called `redispatch_to`. This tool lets you redirect, without using a 3xx redirect; it's handled internally, invisible to the user. So:
+
+```
+'GET + /some/url' => sub {
+ redispatch_to '/some/other/url';
+}
+```
+
+A GET request to `/some/url` would get handled as if it was sent to `/some/other/url`, without a redirect, and the user won't see a redirect in their browser.
+
+I've just scratched the surface with this module. If you're looking for something production-ready for larger projects, you'll be better off with [Dancer][17] or [Catalyst][18]. But with its light weight and built-in Moo integration, Web::Simple packs a big enough punch for a variety of one-offs and smaller services.
+
+### About the author
+
+ [][19] Ruth Holloway - Ruth Holloway has been a system administrator and software developer for a long, long time, getting her professional start on a VAX 11/780, way back when. She spent a lot of her career (so far) serving the technology needs of libraries, and has been a contributor since 2008 to the Koha open source library automation suite.Ruth is currently a Perl Developer at cPanel in Houston, and also serves as chief of staff for an obnoxious cat. In her copious free time, she occasionally reviews old romance... [more about Ruth Holloway][7][More about me][8]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/introduction-websimple-perl-module-minimalist-web-framework
+
+作者:[Ruth Holloway ][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/druthb
+[1]:https://opensource.com/tags/python?src=programming_resource_menu1
+[2]:https://opensource.com/tags/javascript?src=programming_resource_menu2
+[3]:https://opensource.com/tags/perl?src=programming_resource_menu3
+[4]:https://developers.redhat.com/?intcmp=7016000000127cYAAQ&src=programming_resource_menu4
+[5]:http://perldoc.perl.org/functions/package.html
+[6]:https://opensource.com/article/18/1/introduction-websimple-perl-module-minimalist-web-framework?rate=ICN35y076ElpInDKoMqp-sN6f4UVF-n2Qt6dL6lb3kM
+[7]:https://opensource.com/users/druthb
+[8]:https://opensource.com/users/druthb
+[9]:https://opensource.com/user/36051/feed
+[10]:https://www.flickr.com/photos/youasamachine/8025582590/in/photolist-decd6C-7pkccp-aBfN9m-8NEffu-3JDbWb-aqf5Tx-7Z9MTZ-rnYTRu-3MeuPx-3yYwA9-6bSLvd-irmvxW-5Asr4h-hdkfCA-gkjaSQ-azcgct-gdV5i4-8yWxCA-9G1qDn-5tousu-71V8U2-73D4PA-iWcrTB-dDrya8-7GPuxe-5pNb1C-qmnLwy-oTxwDW-3bFhjL-f5Zn5u-8Fjrua-bxcdE4-ddug5N-d78G4W-gsYrFA-ocrBbw-pbJJ5d-682rVJ-7q8CbF-7n7gDU-pdfgkJ-92QMx2-aAmM2y-9bAGK1-dcakkn-8rfyTz-aKuYvX-hqWSNP-9FKMkg-dyRPkY
+[11]:https://creativecommons.org/licenses/by/2.0/
+[12]:https://shadow.cat/resources/bios/matt_short/
+[13]:https://shadow.cat/
+[14]:https://metacpan.org/pod/Catalyst
+[15]:https://metacpan.org/pod/DBIx::Class
+[16]:https://metacpan.org/pod/Moo
+[17]:http://perldancer.org/
+[18]:http://www.catalystframework.org/
+[19]:https://opensource.com/users/druthb
+[20]:https://opensource.com/users/druthb
+[21]:https://opensource.com/users/druthb
+[22]:https://opensource.com/article/18/1/introduction-websimple-perl-module-minimalist-web-framework#comments
+[23]:https://metacpan.org/pod/Web::Simple
+[24]:https://opensource.com/tags/perl
+[25]:https://opensource.com/tags/programming
+[26]:https://opensource.com/tags/perl-column
+[27]:https://opensource.com/tags/web-development
\ No newline at end of file
diff --git a/sources/tech/20180126 Creating an Adventure Game in the Terminal with ncurses.md b/sources/tech/20180126 Creating an Adventure Game in the Terminal with ncurses.md
new file mode 100644
index 0000000000..221c53a4ed
--- /dev/null
+++ b/sources/tech/20180126 Creating an Adventure Game in the Terminal with ncurses.md
@@ -0,0 +1,324 @@
+Creating an Adventure Game in the Terminal with ncurses
+======
+How to use curses functions to read the keyboard and manipulate the screen.
+
+My [previous article][1] introduced the ncurses library and provided a simple program that demonstrated a few curses functions to put text on the screen. In this follow-up article, I illustrate how to use a few other curses functions.
+
+### An Adventure
+
+When I was growing up, my family had an Apple II computer. It was on this machine that my brother and I taught ourselves how to write programs in AppleSoft BASIC. After writing a few math puzzles, I moved on to creating games. Having grown up in the 1980s, I already was a fan of the Dungeons and Dragons tabletop games, where you role-played as a fighter or wizard on some quest to defeat monsters and plunder loot in strange lands. So it shouldn't be surprising that I also created a rudimentary adventure game.
+
+The AppleSoft BASIC programming environment supported a neat feature: in standard resolution graphics mode (GR mode), you could probe the color of a particular pixel on the screen. This allowed a shortcut to create an adventure game. Rather than create and update an in-memory map that was transferred to the screen periodically, I could rely on GR mode to maintain the map for me, and my program could query the screen as the player's character moved around the screen. Using this method, I let the computer do most of the hard work. Thus, my top-down adventure game used blocky GR mode graphics to represent my game map.
+
+My adventure game used a simple map that represented a large field with a mountain range running down the middle and a large lake on the upper-left side. I might crudely draw this map for a tabletop gaming campaign to include a narrow path through the mountains, allowing the player to pass to the far side.
+
+
+
+Figure 1. A simple Tabletop Game Map with a Lake and Mountains
+
+You can draw this map in cursesusing characters to represent grass, mountains and water. Next, I describe how to do just that using curses functions and how to create and play a similar adventure game in the Linux terminal.
+
+### Constructing the Program
+
+In my last article, I mentioned that most curses programs start with the same set of instructions to determine the terminal type and set up the curses environment:
+
+```
+initscr();
+cbreak();
+noecho();
+
+```
+
+For this program, I add another statement:
+
+```
+keypad(stdscr, TRUE);
+
+```
+
+The TRUE flag allows curses to read the keypad and function keys from the user's terminal. If you want to use the up, down, left and right arrow keys in your program, you need to use keypad(stdscr, TRUE) here.
+
+Having done that, you now can start drawing to the terminal screen. The curses functions include several ways to draw text on the screen. In my previous article, I demonstrated the addch() and addstr() functions and their associated mvaddch() and mvaddstr() counterparts that first moved to a specific location on the screen before adding text. To create the adventure game map on the terminal, you can use another set of functions: vline() and hline(), and their partner functions mvvline() and mvhline(). These mv functions accept screen coordinates, a character to draw and how many times to repeat that character. For example, mvhline(1, 2, '-', 20) will draw a line of 20 dashes starting at line 1, column 2.
+
+To draw the map to the terminal screen programmatically, let's define this draw_map() function:
+
+```
+#define GRASS ' '
+#define EMPTY '.'
+#define WATER '~'
+#define MOUNTAIN '^'
+#define PLAYER '*'
+
+void draw_map(void)
+{
+ int y, x;
+
+ /* draw the quest map */
+
+ /* background */
+
+ for (y = 0; y < LINES; y++) {
+ mvhline(y, 0, GRASS, COLS);
+ }
+
+ /* mountains, and mountain path */
+
+ for (x = COLS / 2; x < COLS * 3 / 4; x++) {
+ mvvline(0, x, MOUNTAIN, LINES);
+ }
+
+ mvhline(LINES / 4, 0, GRASS, COLS);
+
+ /* lake */
+
+ for (y = 1; y < LINES / 2; y++) {
+ mvhline(y, 1, WATER, COLS / 3);
+ }
+}
+
+```
+
+In drawing this map, note the use of mvvline() and mvhline() to fill large chunks of characters on the screen. I created the fields of grass by drawing horizontal lines (mvhline) of characters starting at column 0, for the entire height and width of the screen. I added the mountains on top of that by drawing vertical lines (mvvline), starting at row 0, and a mountain path by drawing a single horizontal line (mvhline). And, I created the lake by drawing a series of short horizontal lines (mvhline). It may seem inefficient to draw overlapping rectangles in this way, but remember that curses doesn't actually update the screen until I call the refresh() function later.
+
+Having drawn the map, all that remains to create the game is to enter a loop where the program waits for the user to press one of the up, down, left or right direction keys and then moves a player icon appropriately. If the space the player wants to move into is unoccupied, it allows the player to go there.
+
+You can use curses as a shortcut. Rather than having to instantiate a version of the map in the program and replicate this map to the screen, you can let the screen keep track of everything for you. The inch() function, and associated mvinch() function, allow you to probe the contents of the screen. This allows you to query curses to find out whether the space the player wants to move into is already filled with water or blocked by mountains. To do this, you'll need a helper function that you'll use later:
+
+```
+int is_move_okay(int y, int x)
+{
+ int testch;
+
+ /* return true if the space is okay to move into */
+
+ testch = mvinch(y, x);
+ return ((testch == GRASS) || (testch == EMPTY));
+}
+
+```
+
+As you can see, this function probes the location at column y, row x and returns true if the space is suitably unoccupied, or false if not.
+
+That makes it really easy to write a navigation loop: get a key from the keyboard and move the user's character around depending on the up, down, left and right arrow keys. Here's a simplified version of that loop:
+
+```
+
+ do {
+ ch = getch();
+
+ /* test inputted key and determine direction */
+
+ switch (ch) {
+ case KEY_UP:
+ if ((y > 0) && is_move_okay(y - 1, x)) {
+ y = y - 1;
+ }
+ break;
+ case KEY_DOWN:
+ if ((y < LINES - 1) && is_move_okay(y + 1, x)) {
+ y = y + 1;
+ }
+ break;
+ case KEY_LEFT:
+ if ((x > 0) && is_move_okay(y, x - 1)) {
+ x = x - 1;
+ }
+ break;
+ case KEY_RIGHT
+ if ((x < COLS - 1) && is_move_okay(y, x + 1)) {
+ x = x + 1;
+ }
+ break;
+ }
+ }
+ while (1);
+
+```
+
+To use this in a game, you'll need to add some code inside the loop to allow other keys (for example, the traditional WASD movement keys), provide a method for the user to quit the game and move the player's character around the screen. Here's the program in full:
+
+```
+
+/* quest.c */
+
+#include
+#include
+
+#define GRASS ' '
+#define EMPTY '.'
+#define WATER '~'
+#define MOUNTAIN '^'
+#define PLAYER '*'
+
+int is_move_okay(int y, int x);
+void draw_map(void);
+
+int main(void)
+{
+ int y, x;
+ int ch;
+
+ /* initialize curses */
+
+ initscr();
+ keypad(stdscr, TRUE);
+ cbreak();
+ noecho();
+
+ clear();
+
+ /* initialize the quest map */
+
+ draw_map();
+
+ /* start player at lower-left */
+
+ y = LINES - 1;
+ x = 0;
+
+ do {
+ /* by default, you get a blinking cursor - use it to indicate player */
+
+ mvaddch(y, x, PLAYER);
+ move(y, x);
+ refresh();
+
+ ch = getch();
+
+ /* test inputted key and determine direction */
+
+ switch (ch) {
+ case KEY_UP:
+ case 'w':
+ case 'W':
+ if ((y > 0) && is_move_okay(y - 1, x)) {
+ mvaddch(y, x, EMPTY);
+ y = y - 1;
+ }
+ break;
+ case KEY_DOWN:
+ case 's':
+ case 'S':
+ if ((y < LINES - 1) && is_move_okay(y + 1, x)) {
+ mvaddch(y, x, EMPTY);
+ y = y + 1;
+ }
+ break;
+ case KEY_LEFT:
+ case 'a':
+ case 'A':
+ if ((x > 0) && is_move_okay(y, x - 1)) {
+ mvaddch(y, x, EMPTY);
+ x = x - 1;
+ }
+ break;
+ case KEY_RIGHT:
+ case 'd':
+ case 'D':
+ if ((x < COLS - 1) && is_move_okay(y, x + 1)) {
+ mvaddch(y, x, EMPTY);
+ x = x + 1;
+ }
+ break;
+ }
+ }
+ while ((ch != 'q') && (ch != 'Q'));
+
+ endwin();
+
+ exit(0);
+}
+
+int is_move_okay(int y, int x)
+{
+ int testch;
+
+ /* return true if the space is okay to move into */
+
+ testch = mvinch(y, x);
+ return ((testch == GRASS) || (testch == EMPTY));
+}
+
+void draw_map(void)
+{
+ int y, x;
+
+ /* draw the quest map */
+
+ /* background */
+
+ for (y = 0; y < LINES; y++) {
+ mvhline(y, 0, GRASS, COLS);
+ }
+
+ /* mountains, and mountain path */
+
+ for (x = COLS / 2; x < COLS * 3 / 4; x++) {
+ mvvline(0, x, MOUNTAIN, LINES);
+ }
+
+ mvhline(LINES / 4, 0, GRASS, COLS);
+
+ /* lake */
+
+ for (y = 1; y < LINES / 2; y++) {
+ mvhline(y, 1, WATER, COLS / 3);
+ }
+}
+
+```
+
+In the full program listing, you can see the complete arrangement of curses functions to create the game:
+
+1) Initialize the curses environment.
+
+2) Draw the map.
+
+3) Initialize the player coordinates (lower-left).
+
+4) Loop:
+
+* Draw the player's character.
+
+* Get a key from the keyboard.
+
+* Adjust the player's coordinates up, down, left or right, accordingly.
+
+* Repeat.
+
+5) When done, close the curses environment and exit.
+
+### Let's Play
+
+When you run the game, the player's character starts in the lower-left corner. As the player moves around the play area, the program creates a "trail" of dots. This helps show where the player has been before, so the player can avoid crossing the path unnecessarily.
+
+
+
+Figure 2\. The player starts the game in the lower-left corner.
+
+
+
+Figure 3\. The player can move around the play area, such as around the lake and through the mountain pass.
+
+To create a complete adventure game on top of this, you might add random encounters with various monsters as the player navigates his or her character around the play area. You also could include special items the player could discover or loot after defeating enemies, which would enhance the player's abilities further.
+
+But to start, this is a good program for demonstrating how to use the curses functions to read the keyboard and manipulate the screen.
+
+### Next Steps
+
+This program is a simple example of how to use the curses functions to update and read the screen and keyboard. You can do so much more with curses, depending on what you need your program to do. In a follow up article, I plan to show how to update this sample program to use colors. In the meantime, if you are interested in learning more about curses, I encourage you to read Pradeep Padala's [NCURSES Programming HOWTO][2] at the Linux Documentation Project.
+
+
+--------------------------------------------------------------------------------
+
+via: http://www.linuxjournal.com/content/creating-adventure-game-terminal-ncurses
+
+作者:[Jim Hall][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://www.linuxjournal.com/users/jim-hall
+[1]:http://www.linuxjournal.com/content/getting-started-ncurses
+[2]:http://tldp.org/HOWTO/NCURSES-Programming-HOWTO
diff --git a/sources/tech/20180126 How To Manage NodeJS Packages Using Npm.md b/sources/tech/20180126 How To Manage NodeJS Packages Using Npm.md
new file mode 100644
index 0000000000..ac27816a7b
--- /dev/null
+++ b/sources/tech/20180126 How To Manage NodeJS Packages Using Npm.md
@@ -0,0 +1,372 @@
+How To Manage NodeJS Packages Using Npm
+======
+
+
+
+A while ago, we have published a guide to [**manage Python packages using PIP**][1]. Today, we are going to discuss how to manage NodeJS packages using Npm. NPM is the largest software registry that contains over 600,000 packages. Everyday, developers across the world shares and downloads packages through npm. In this guide, I will explain the the basics of working with npm, such as installing packages(locally and globally), installing certain version of a package, updating, removing and managing NodeJS packages and so on.
+
+### Manage NodeJS Packages Using Npm
+
+##### Installing NPM
+
+Since npm is written in NodeJS, we need to install NodeJS in order to use npm. To install NodeJS on different Linux distributions, refer the following link.
+
+Once installed, ensure that NodeJS and NPM have been properly installed. There are couple ways to do this.
+
+To check where node has been installed:
+```
+$ which node
+/home/sk/.nvm/versions/node/v9.4.0/bin/node
+```
+
+Check its version:
+```
+$ node -v
+v9.4.0
+```
+
+Log in to Node REPL session:
+```
+$ node
+> .help
+.break Sometimes you get stuck, this gets you out
+.clear Alias for .break
+.editor Enter editor mode
+.exit Exit the repl
+.help Print this help message
+.load Load JS from a file into the REPL session
+.save Save all evaluated commands in this REPL session to a file
+> .exit
+```
+
+Check where npm installed:
+```
+$ which npm
+/home/sk/.nvm/versions/node/v9.4.0/bin/npm
+```
+
+And the version:
+```
+$ npm -v
+5.6.0
+```
+
+Great! Node and NPM have been installed and are working! As you may have noticed, I have installed NodeJS and NPM in my $HOME directory to avoid permission issues while installing modules globally. This is the recommended method by NodeJS team.
+
+Well, let us go ahead to see managing NodeJS modules (or packages) using npm.
+
+##### Installing NodeJS modules
+
+NodeJS modules can either be installed locally or globally(system wide). Now I am going to show how to install a package locally.
+
+**Install packages locally**
+
+To manage packages locally, we normally use **package.json** file.
+
+First, let us create our project directory.
+```
+$ mkdir demo
+```
+```
+$ cd demo
+```
+
+Create a package.json file inside your project's directory. To do so, run:
+```
+$ npm init
+```
+
+Enter the details of your package such as name, version, author, github page etc., or just hit ENTER key to accept the default values and type **YES** to confirm.
+```
+This utility will walk you through creating a package.json file.
+It only covers the most common items, and tries to guess sensible defaults.
+
+See `npm help json` for definitive documentation on these fields
+and exactly what they do.
+
+Use `npm install ` afterwards to install a package and
+save it as a dependency in the package.json file.
+
+Press ^C at any time to quit.
+package name: (demo)
+version: (1.0.0)
+description: demo nodejs app
+entry point: (index.js)
+test command:
+git repository:
+keywords:
+author:
+license: (ISC)
+About to write to /home/sk/demo/package.json:
+
+{
+ "name": "demo",
+ "version": "1.0.0",
+ "description": "demo nodejs app",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC"
+}
+
+Is this ok? (yes) yes
+```
+
+The above command initializes your project and create package.json file.
+
+You can also do this non-interactively using command:
+```
+npm init --y
+```
+
+This will create a package.json file quickly with default values without the user interaction.
+
+Now let us install package named [**commander**][2].
+```
+$ npm install commander
+```
+
+Sample output:
+```
+npm notice created a lockfile as package-lock.json. You should commit this file.
+npm WARN demo@1.0.0 No repository field.
+
++ commander@2.13.0
+added 1 package in 2.519s
+```
+
+This will create a directory named **" node_modules"** (if it doesn't exist already) in the project's root directory and download the packages in it.
+
+Let us check the package.json file.
+```
+$ cat package.json
+{
+ "name": "demo",
+ "version": "1.0.0",
+ "description": "demo nodejs app",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC",
+ **"dependencies": {**
+**"commander": "^2.13.0"**
+ }
+}
+```
+
+You will see the dependencies have been added. The caret ( **^** ) at the front of the version number indicates that when installing, npm will pull the highest version of the package it can find.
+```
+$ ls node_modules/
+commander
+```
+
+The advantage of package.json file is if you had the package.json file in your project's directory, you can just type "npm install", then npm will look into the dependencies that listed in the file and download all of them. You can even share it with other developers or push into your GitHub repository, so when they type "npm install", they will get all the same packages that you have.
+
+You may also noticed another json file named **package-lock.json**. This file ensures that the dependencies remain the same on all systems the project is installed on.
+
+To use the installed package in your program, create a file **index.js** (or any name of you choice) in the project's directory with the actual code, and then run it using command:
+```
+$ node index.js
+```
+
+**Install packages globally**
+
+If you want to use a package as a command line tool, then it is better to install it globally. This way, it works no matter which directory is your current directory.
+```
+$ npm install async -g
++ async@2.6.0
+added 2 packages in 4.695s
+```
+
+Or,
+```
+$ npm install async --global
+```
+
+To install a specific version of a package, we do:
+```
+$ npm install async@2.6.0 --global
+```
+
+##### Updating NodeJS modules
+
+To update the local packages, go the the project's directory where the package.json is located and run:
+```
+$ npm update
+```
+
+Then, run the following command to ensure all packages were updated.
+```
+$ npm outdated
+```
+
+If there is no update, then it returns nothing.
+
+To find out which global packages need to be updated, run:
+```
+$ npm outdated -g --depth=0
+```
+
+If there is no output, then all packages are updated.
+
+To update the a single global package, run:
+```
+$ npm update -g
+```
+
+To update all global packages, run:
+```
+$ npm update -g
+```
+
+##### Listing NodeJS modules
+
+To list the local packages, go the project's directory and run:
+```
+$ npm list
+demo@1.0.0 /home/sk/demo
+└── commander@2.13.0
+```
+
+As you see, I have installed "commander" package in local mode.
+
+To list global packages, run this command from any location:
+```
+$ npm list -g
+```
+
+Sample output:
+```
+/home/sk/.nvm/versions/node/v9.4.0/lib
+├─┬ async@2.6.0
+│ └── lodash@4.17.4
+└─┬ npm@5.6.0
+ ├── abbrev@1.1.1
+ ├── ansi-regex@3.0.0
+ ├── ansicolors@0.3.2
+ ├── ansistyles@0.1.3
+ ├── aproba@1.2.0
+ ├── archy@1.0.0
+[...]
+```
+
+This command will list all modules and their dependencies.
+
+To list only the top level modules, use -depth=0 option:
+```
+$ npm list -g --depth=0
+/home/sk/.nvm/versions/node/v9.4.0/lib
+├── async@2.6.0
+└── npm@5.6.0
+```
+
+##### Searching NodeJS modules
+
+To search for a module, use "npm search" command:
+```
+npm search
+```
+
+Example:
+```
+$ npm search request
+```
+
+This command will display all modules that contains the search string "request".
+
+##### Removing NodeJS modules
+
+To remove a local package, go to the project's directory and run following command to remove the package from your **node_modules** directory:
+```
+$ npm uninstall
+```
+
+To remove it from the dependencies in **package.json** file, use the **save** flag like below:
+```
+$ npm uninstall --save
+
+```
+
+To remove the globally installed packages, run:
+```
+$ npm uninstall -g
+```
+
+##### Cleaning NPM cache
+
+By default, NPM keeps the copy of a installed package in the cache folder named npm in your $HOME directory when installing it. So, you can install it next time without having to download again.
+
+To view the cached modules:
+```
+$ ls ~/.npm
+```
+
+The cache folder gets flooded with all old packages over time. It is better to clean the cache from time to time.
+
+As of npm@5, the npm cache self-heals from corruption issues and data extracted from the cache is guaranteed to be valid. If you want to make sure everything is consistent, run:
+```
+$ npm cache verify
+```
+
+To clear the entire cache, run:
+```
+$ npm cache clean --force
+```
+
+##### Viewing NPM configuration
+
+To view the npm configuration, type:
+```
+$ npm config list
+```
+
+Or,
+```
+$ npm config ls
+```
+
+Sample output:
+```
+; cli configs
+metrics-registry = "https://registry.npmjs.org/"
+scope = ""
+user-agent = "npm/5.6.0 node/v9.4.0 linux x64"
+
+; node bin location = /home/sk/.nvm/versions/node/v9.4.0/bin/node
+; cwd = /home/sk
+; HOME = /home/sk
+; "npm config ls -l" to show all defaults.
+```
+
+To display the current global location:
+```
+$ npm config get prefix
+/home/sk/.nvm/versions/node/v9.4.0
+```
+
+And, that's all for now. What we have just covered here is just the basics. NPM is a vast topic. For more details, head over to the the [**NPM Getting Started**][3] guide.
+
+Hope this was useful. More good stuffs to come. Stay tuned!
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/manage-nodejs-packages-using-npm/
+
+作者:[SK][a]
+译者:[译者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.npmjs.com/package/commander
+[3]:https://docs.npmjs.com/getting-started/
diff --git a/sources/tech/20180126 How to Make a Minecraft Server - ThisHosting.Rocks.md b/sources/tech/20180126 How to Make a Minecraft Server - ThisHosting.Rocks.md
new file mode 100644
index 0000000000..30c6ccc54e
--- /dev/null
+++ b/sources/tech/20180126 How to Make a Minecraft Server - ThisHosting.Rocks.md
@@ -0,0 +1,418 @@
+translating by heart4lor
+
+How to Make a Minecraft Server – ThisHosting.Rocks
+======
+We’ll show you how to make a Minecraft server with beginner-friendly step-by-step instructions. It will be a persistent multiplayer server that you can play on with your friends from all around the world. You don’t have to be in a LAN.
+
+### How to Make a Minecraft Server – Quick Guide
+
+This is our “Table of contents” if you’re in a hurry and want to go straight to the point. We recommend reading everything though.
+
+* [Learn stuff][1] (optional)
+
+* [Learn more stuff][2] (optional)
+
+* [Requirements][3] (required)
+
+* [Install and start the Minecraft server][4] (required)
+
+* [Run the server even after you log out of your VPS][5] (optional)
+
+* [Make the server automatically start at boot][6] (optional)
+
+* [Configure your Minecraft server][7] (required)
+
+* [FAQs][8] (optional)
+
+Before going into the actual instructions, a few things you should know:
+
+#### Reasons why you would NOT use a specialized Minecraft server hosting provider
+
+Since you’re here, you’re obviously interested in hosting your own Minecraft server. There are more reasons why you would not use a specialized Minecraft hosting provider, but here are a few:
+
+* They’re slow most of the time. This is because you actually share the resources with multiple users. It becomes overloaded at some point. Most of them oversell their servers too.
+
+* You don’t have full control over the Minecraft server or the actual server. You cannot customize anything you want to.
+
+* You’re limited. Those kinds of hosting plans are always limited in one way or another.
+
+Of course, there are positives to using a Minecraft hosting provider. The best upside is that you don’t actually have to do all the stuff we’ll write about below. But where’s the fun in that?
+
+
+#### Why you should NOT use your personal computer to make a Minecraft server
+
+We noticed lots of tutorials showing you how to host a server on your own computer. There are downsides to doing that, like:
+
+* Your home internet is not secured enough to handle DDoS attacks. Game servers are often prone to DDoS attacks, and your home network setup is most probably not secured enough to handle them. It’s most likely not powerful enough to handle a small attack.
+
+* You’ll need to handle port forwarding. If you’ve tried making a Minecraft server on your home network, you’ve surely stumbled upon port forwarding and had issues with it.
+
+* You’ll need to keep your computer on at all times. Your electricity bill will sky-rocket and you’ll add unnecessary load to your hardware. The hardware most servers use is enterprise-grade and designed to handle loads, with improved stability and longevity.
+
+* Your home internet is not fast enough. Home networks are not designed to handle multiplayer games. You’ll need a much larger internet plan to even consider making a small server. Luckily, data centers have multiple high-speed, enterprise-grade internet connections making sure they have (or strive to have) 100% uptime.
+
+* Your hardware is most likely not good enough. Again, servers use enterprise-grade hardware, latest and fastest CPUs, SSDs, and much more. Your personal computer most likely does not.
+
+* You probably use Windows/MacOS on your personal computer. Though this is debatable, we believe that Linux is much better for game hosting. Don’t worry, you don’t really need to know everything about Linux to make a Minecraft server (though it’s recommended). We’ll show you everything you need to know.
+
+Our tip is not to use your personal computer, though technically you can. It’s not expensive to buy a cloud server. We’ll show you how to make a Minecraft server on cloud hosting below. It’s easy if you carefully follow the steps.
+
+### Making a Minecraft Server – Requirements
+
+There are a few requirements. You should have and know all of this before continuing to the tutorial:
+
+* You’ll need a [Linux cloud server][9]. We recommend [Vultr][10]. Their prices are cheap, services are high-quality, customer support is great, all server hardware is high-end. Check the [Minecraft server requirements][11] to find out what kind of server you should get (resources like RAM and Disk space). We recommend getting the $20 per month server. They support hourly pricing so if you only need the server temporary for playing with friends, you’ll pay less. Choose the Ubuntu 16.04 distro during signup. Choose the closest server location to where your players live during the signup process. Keep in mind that you’ll be responsible for your server. So you’ll have to secure it and manage it. If you don’t want to do that, you can get a [managed server][12], in which case the hosting provider will likely make a Minecraft server for you.
+
+* You’ll need an SSH client to connect to the Linux cloud server. [PuTTy][13] is often recommended for beginners, but we also recommend [MobaXTerm][14]. There are many other SSH clients to choose from, so pick your favorite.
+
+* You’ll need to setup your server (basic security setup at least). Google it and you’ll find many tutorials. You can use [Linode’s Security Guide][15] and follow the exact steps on your [Vultr][16] server.
+
+* We’ll handle the software requirements like Java below.
+
+And finally, onto our actual tutorial:
+
+### How to Make a Minecraft Server on Ubuntu (Linux)
+
+These instructions are written for and tested on an Ubuntu 16.04 server from [Vultr][17]. Though they’ll also work on Ubuntu 14.04, [Ubuntu 18.04][18], and any other Ubuntu-based distro, and any other server provider.
+
+We’re using the default Vanilla server from Minecraft. You can use alternatives like CraftBukkit or Spigot that allow more customizations and plugins. Though if you use too many plugins you’ll essentially ruin the server. There are pros and cons to each one. Nevertheless, the instructions below are for the default Vanilla server to keep things simple and beginner-friendly. We may publish a tutorial for CraftBukkit soon if there’s an interest.
+
+#### 1. Login to your server
+
+We’ll use the root user. If you use a limited-user, you’ll have to execute most commands with ‘sudo’. You’ll get a warning if you’re doing something you don’t have enough permissions for.
+
+You can login to your server via your SSH client. Use your server IP and your port (most likely 22).
+
+After you log in, make sure you [secure your server][19].
+
+#### 2. Update Ubuntu
+
+You should always first update your Ubuntu before you do anything else. You can update it with the following commands:
+
+```
+apt-get update && apt-get upgrade
+```
+
+Hit “enter” and/or “y” when prompted.
+
+#### 3. Install necessary tools
+
+You’ll need a few packages and tools for various things in this tutorial like text editing, making your server persistent etc. Install them with the following command:
+
+```
+apt-get install nano wget screen bash default-jdk ufw
+```
+
+Some of them may already be installed.
+
+#### 4. Download Minecraft Server
+
+First, create a directory where you’ll store your Minecraft server and all other files:
+
+```
+mkdir /opt/minecraft
+```
+
+And navigate to the new directory:
+
+```
+cd /opt/minecraft
+```
+
+Now you can download the Minecraft Server file. Go to the [download page][20] and get the link there. Download the file with wget:
+
+```
+wget https://s3.amazonaws.com/Minecraft.Download/versions/1.12.2/minecraft_server.1.12.2.jar
+```
+
+#### 5. Install the Minecraft server
+
+Once you’ve downloaded the server .jar file, you need to run it once and it will generate some files, including an eula.txt license file. The first time you run it, it will return an error and exit. That’s supposed to happen. Run in with the following command:
+
+```
+java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.2.jar nogui
+```
+
+“-Xms2048M” is the minimum RAM that your Minecraft server can use and “-Xmx3472M” is the maximum. [Adjust][21] this based on your server’s resources. If you got the 4GB RAM server from [Vultr][22] you can leave them as-is, if you don’t use the server for anything else other than Minecraft.
+
+After that command ends and returns an error, a new eula.txt file will be generated. You need to accept the license in that file. You can do that by adding “eula=true” to the file with the following command:
+
+```
+sed -i.orig 's/eula=false/eula=true/g' eula.txt
+```
+
+You can now start the server again and access the Minecraft server console with that same java command from before:
+
+```
+java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.2.jar nogui
+```
+
+Make sure you’re in the /opt/minecraft directory, or the directory where you installed your MC server.
+
+You’re free to stop here if you’re just testing this and need it for the short-term. If you’re having trouble loggin into the server, you’ll need to [configure your firewall][23].
+
+The first time you successfully start the server it will take a bit longer to generate
+
+We’ll show you how to create a script so you can start the server with it.
+
+#### 6. Start the Minecraft server with a script, make it persistent, and enable it at boot
+
+To make things easier, we’ll create a bash script that will start the server automatically.
+
+So first, create a bash script with nano:
+
+```
+nano /opt/minecraft/startminecraft.sh
+```
+
+A new (blank) file will open. Paste the following:
+
+```
+#!/bin/bash
+cd /opt/minecraft/ && java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.2.jar nogui
+```
+
+If you’re new to nano – you can save and close the file with “CTRL + X”, then “Y”, and hitting enter. This script navigates to your Minecraft server directory you created previously and runs the java command for starting the server. You need to make it executable with the following command:
+
+```
+chmod +x startminecraft.sh
+```
+
+Then, you can start the server anytime with the following command:
+
+```
+/opt/minecraft/startminecraft.sh
+```
+
+But, if/when you log out of the SSH session the server will turn off. To keep the server up without being logged in all the time, you can use a screen session. A screen session basically means that it will keep running until the actual server reboots or turns off.
+
+Start a screen session with this command:
+
+```
+screen -S minecraft
+```
+
+Once you’re in the screen session (looks like you would start a new ssh session), you can use the bash script from earlier to start the server:
+
+```
+/opt/minecraft/startminecraft.sh
+```
+
+To get out of the screen session, you should press CTRL + A-D. Even after you get out of the screen session (detach), the server will keep running. You can safely log off your Ubuntu server now, and the Minecraft server you created will keep running.
+
+But, if the Ubuntu server reboots or shuts off, the screen session won’t work anymore. So **to do everything we did before automatically at boot** , do the following:
+
+Open the /etc/rc.local file:
+
+```
+nano /etc/rc.local
+```
+
+and add the following line above the “exit 0” line:
+
+```
+screen -dm -S minecraft /opt/minecraft/startminecraft.sh
+exit 0
+```
+
+Save and close the file.
+
+To access the Minecraft server console, just run the following command to attach to the screen session:
+
+```
+screen -r minecraft
+```
+
+That’s it for now. Congrats and have fun! You can now connect to your Minecraft server or configure/modify it.
+
+### Configure your Ubuntu Server
+
+You’ll, of course, need to set up your Ubuntu server and secure it if you haven’t already done so. Follow the [guide we mentioned earlier][24] and google it for more info. The configurations you need to do for your Minecraft server on your Ubuntu server are:
+
+#### Enable and configure the firewall
+
+First, if it’s not already enabled, you should enable UFW that you previously installed:
+
+```
+ufw enable
+```
+
+You should allow the default Minecraft server port:
+
+```
+ufw allow 25565/tcp
+```
+
+You should allow and deny other rules depending on how you use your server. You should deny ports like 80 and 443 if you don’t use the server for hosting websites. Google a UFW/Firewall guide for Ubuntu and you’ll get recommendations. Be careful when setting up your firewall, you may lock yourself out of your server if you block the SSH port.
+
+Since this is the default port, it often gets automatically scanned and attacked. You can prevent attacks by blocking access to anyone that’s not of your whitelist.
+
+First, you need to enable the whitelist mode in your [server.properties][25] file. To do that, open the file:
+
+```
+nano /opt/minecraft/server.properties
+```
+
+And change “white-list” line to “true”:
+
+```
+white-list=true
+```
+
+Save and close the file.
+
+Then restart your server (either by restarting your Ubuntu server or by running the start bash script again):
+
+```
+/opt/minecraft/startminecraft.sh
+```
+
+Access the Minecraft server console:
+
+```
+screen -r minecraft
+```
+
+And if you want someone to be able to join your server, you need to add them to the whitelist with the following command:
+
+```
+whitelist add PlayerUsername
+```
+
+To remove them from the whitelist, use:
+
+```
+whitelist remove PlayerUsername
+```
+
+Exit the screen session (server console) with CTRL + A-D. It’s worth noting that this will deny access to everyone but the whitelisted usernames.
+
+ [][26]
+
+### How to Make a Minecraft Server – FAQs
+
+We’ll answer some frequently asked questions about Minecraft Servers and our guide.
+
+#### How do I restart the Minecraft server?
+
+If you followed every step from our tutorial, including enabling the server to start on boot, you can just reboot your Ubuntu server. If you didn’t set it up to start at boot, you can just run the start script again which will restart the Minecraft server:
+
+```
+/opt/minecraft/startminecraft.sh
+```
+
+#### How do I configure my Minecraft server?
+
+You can configure your server using the [server.properties][27] file. Check the Minecraft Wiki for more info, though you can leave everything as-is and it will work perfectly fine.
+
+If you want to change the game mode, difficulty and stuff like that, you can use the server console. Access the server console by running:
+
+```
+screen -r minecraft
+```
+
+And execute [commands][28] there. Commands like:
+
+```
+difficulty hard
+```
+
+```
+gamemode survival @a
+```
+
+You may need to restart the server depending on what command you used. There are many more commands you can use, check the [wiki][29] for more.
+
+#### How do I upgrade my Minecraft server?
+
+If there’s a new release, you need to do this:
+
+Navigate to the minecraft directory:
+
+```
+cd /opt/minecraft
+```
+
+Download the latest version, example 1.12.3 with wget:
+
+```
+wget https://s3.amazonaws.com/Minecraft.Download/versions/1.12.3/minecraft_server.1.12.3.jar
+```
+
+Next, run and build the new server:
+
+```
+java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.3.jar nogui
+```
+
+Finally, update your start script:
+
+```
+nano /opt/minecraft/startminecraft.sh
+```
+
+And update the version number accordingly:
+
+```
+#!/bin/bash
+cd /opt/minecraft/ && java -Xms2048M -Xmx3472M -jar minecraft_server.1.12.3.jar nogui
+```
+
+Now you can restart the server and everything should go well.
+
+#### Why is your Minecraft server tutorial so long, and yet others are only 2 lines long?!
+
+We tried to make this beginner-friendly and be as detailed as possible. We also showed you how to make the Minecraft server persistent and start it automatically at boot, we showed you how to configure your server and everything. I mean, sure, you can start a Minecraft server with a couple of lines, but it would definitely suck, for more than one reason.
+
+#### I don’t know Linux or anything you wrote about here, how do I make a Minecraft server?
+
+Just read all of our article and copy and paste the commands. If you really don’t know how to do it all, [we can do it for you][30], or just get a [managed][31] server [provider][32] and let them do it for you.
+
+#### How do I install mods on my server? How do I install plugins?
+
+Our article is intended to be a starting guide. You should check the [Minecraft wiki][33] for more info, or just google it. There are plenty of tutorials online
+
+--------------------------------------------------------------------------------
+
+via: https://thishosting.rocks/how-to-make-a-minecraft-server/
+
+作者:[ThisHosting.Rocks][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://thishosting.rocks
+[1]:https://thishosting.rocks/how-to-make-a-minecraft-server/#reasons
+[2]:https://thishosting.rocks/how-to-make-a-minecraft-server/#not-pc
+[3]:https://thishosting.rocks/how-to-make-a-minecraft-server/#requirements
+[4]:https://thishosting.rocks/how-to-make-a-minecraft-server/#make-minecraft-server
+[5]:https://thishosting.rocks/how-to-make-a-minecraft-server/#persistent
+[6]:https://thishosting.rocks/how-to-make-a-minecraft-server/#boot
+[7]:https://thishosting.rocks/how-to-make-a-minecraft-server/#configure-minecraft-server
+[8]:https://thishosting.rocks/how-to-make-a-minecraft-server/#faqs
+[9]:https://thishosting.rocks/cheap-cloud-hosting-providers-comparison/
+[10]:https://thishosting.rocks/go/vultr/
+[11]:https://minecraft.gamepedia.com/Server/Requirements/Dedicated
+[12]:https://thishosting.rocks/best-cheap-managed-vps/
+[13]:https://www.chiark.greenend.org.uk/~sgtatham/putty/
+[14]:https://mobaxterm.mobatek.net/
+[15]:https://www.linode.com/docs/security/securing-your-server/
+[16]:https://thishosting.rocks/go/vultr/
+[17]:https://thishosting.rocks/go/vultr/
+[18]:https://thishosting.rocks/ubuntu-18-04-new-features-release-date/
+[19]:https://www.linode.com/docs/security/securing-your-server/
+[20]:https://minecraft.net/en-us/download/server
+[21]:https://minecraft.gamepedia.com/Commands
+[22]:https://thishosting.rocks/go/vultr/
+[23]:https://thishosting.rocks/how-to-make-a-minecraft-server/#configure-minecraft-server
+[24]:https://www.linode.com/docs/security/securing-your-server/
+[25]:https://minecraft.gamepedia.com/Server.properties
+[26]:https://thishosting.rocks/wp-content/uploads/2018/01/create-a-minecraft-server.jpg
+[27]:https://minecraft.gamepedia.com/Server.properties
+[28]:https://minecraft.gamepedia.com/Commands
+[29]:https://minecraft.gamepedia.com/Commands
+[30]:https://thishosting.rocks/support/
+[31]:https://thishosting.rocks/best-cheap-managed-vps/
+[32]:https://thishosting.rocks/best-cheap-managed-vps/
+[33]:https://minecraft.gamepedia.com/Minecraft_Wiki
diff --git a/sources/tech/20180126 Linux kill Command Tutorial for Beginners (5 Examples).md b/sources/tech/20180126 Linux kill Command Tutorial for Beginners (5 Examples).md
new file mode 100644
index 0000000000..8fcdedef0e
--- /dev/null
+++ b/sources/tech/20180126 Linux kill Command Tutorial for Beginners (5 Examples).md
@@ -0,0 +1,113 @@
+Linux kill Command Tutorial for Beginners (5 Examples)
+======
+
+Sometimes, while working on a Linux machine, you'll see that an application or a command line process gets stuck (becomes unresponsive). Then in those cases, terminating it is the only way out. Linux command line offers a utility that you can use in these scenarios. It's called **kill**.
+
+In this tutorial, we will discuss the basics of kill using some easy to understand examples. But before we do that, it's worth mentioning that all examples in the article have been tested on an Ubuntu 16.04 machine.
+
+#### Linux kill command
+
+The kill command is usually used to kill a process. Internally it sends a signal, and depending on what you want to do, there are different signals that you can send using this tool. Following is the command's syntax:
+
+```
+kill [options] [...]
+```
+
+And here's how the tool's man page describes it:
+```
+The default signal for kill is TERM. Use -l or -L to list available signals. Particularly useful
+signals include HUP, INT, KILL, STOP, CONT, and 0. Alternate signals may be specified in three ways:
+-9, -SIGKILL or -KILL. Negative PID values may be used to choose whole process groups; see the PGID
+column in ps command output. A PID of -1 is special; it indicates all processes except the kill
+process itself and init.
+```
+
+The following Q&A-styled examples should give you a better idea of how the kill command works.
+
+#### Q1. How to terminate a process using kill command?
+
+This is very easy - all you need to do is to get the pid of the process you want to kill, and then pass it to the kill command.
+
+```
+kill [pid]
+```
+
+For example, I wanted to kill the 'gthumb' process on my system. So i first used the ps command to fetch the application's pid, and then passed it to the kill command to terminate it. Here's the screenshot showing all this:
+
+[![How to terminate a process using kill command][1]][2]
+
+#### Q2. How to send a custom signal?
+
+As already mentioned in the introduction section, TERM is the default signal that kill sends to the application/process in question. However, if you want, you can send any other signal that kill supports using the **-s** command line option.
+
+```
+kill -s [signal] [pid]
+```
+
+For example, if a process isn't responding to the TERM signal (which allows the process to do final cleanup before quitting), you can go for the KILL signal (which doesn't let process do any cleanup). Following is the command you need to run in that case.
+
+```
+kill -s KILL [pid]
+```
+
+#### Q3. What all signals you can send using kill?
+
+Of course, the next logical question that'll come to your mind is how to know which all signals you can send using kill. Well, thankfully, there exists a command line option **-l** that lists all supported signals.
+
+```
+kill -l
+```
+
+Following is the output the above command produced on our system:
+
+[![What all signals you can send using kill][3]][4]
+
+#### Q4. What are the other ways in which signal can be sent?
+
+In one of the previous examples, we told you if you want to send the KILL signal, you can do it in the following way:
+
+```
+kill -s KILL [pid]
+```
+
+However, there are a couple of other alternatives as well:
+
+```
+kill -s SIGKILL [pid]
+
+kill -s 9 [pid]
+```
+
+The corresponding number can be known using the -l option we've already discussed in the previous example.
+
+#### Q5. How to kill all running process in one go?
+
+In case a user wants to kill all processes that they can (this depends on their privilege level), then instead of specifying a large number of process IDs, they can simply pass the -1 option to kill.
+
+For example:
+
+```
+kill -s KILL -1
+```
+
+#### Conclusion
+
+The kill command is pretty straightforward to understand and use. There's a slight learning curve in terms of the list of signal options it offers, but as we explained in here, there's an option to take a quick look at that list as well. Just practice whatever we've discussed and you should be good to go. For more information, head to the tool's [man page][5].
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.howtoforge.com/linux-kill-command/
+
+作者:[Himanshu Arora][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.howtoforge.com
+[1]:https://www.howtoforge.com/images/usage_of_pfsense_to_block_dos_attack_/kill-default.png
+[2]:https://www.howtoforge.com/images/usage_of_pfsense_to_block_dos_attack_/big/kill-default.png
+[3]:https://www.howtoforge.com/images/usage_of_pfsense_to_block_dos_attack_/kill-l-option.png
+[4]:https://www.howtoforge.com/images/usage_of_pfsense_to_block_dos_attack_/big/kill-l-option.png
+[5]:https://linux.die.net/man/1/kill
diff --git a/sources/tech/20180126 Running a Python application on Kubernetes.md b/sources/tech/20180126 Running a Python application on Kubernetes.md
new file mode 100644
index 0000000000..4ce9f38726
--- /dev/null
+++ b/sources/tech/20180126 Running a Python application on Kubernetes.md
@@ -0,0 +1,280 @@
+Running a Python application on Kubernetes
+============================================================
+
+### This step-by-step tutorial takes you through the process of deploying a simple Python application on Kubernetes.
+
+
+Image by : opensource.com
+
+Kubernetes is an open source platform that offers deployment, maintenance, and scaling features. It simplifies management of containerized Python applications while providing portability, extensibility, and self-healing capabilities.
+
+Whether your Python applications are simple or more complex, Kubernetes lets you efficiently deploy and scale them, seamlessly rolling out new features while limiting resources to only those required.
+
+In this article, I will describe the process of deploying a simple Python application to Kubernetes, including:
+
+* Creating Python container images
+
+* Publishing the container images to an image registry
+
+* Working with persistent volume
+
+* Deploying the Python application to Kubernetes
+
+### Requirements
+
+You will need Docker, kubectl, and this [source code][10].
+
+Docker is an open platform to build and ship distributed applications. To install Docker, follow the [official documentation][11]. To verify that Docker runs your system:
+
+```
+$ docker info
+Containers: 0
+Images: 289
+Storage Driver: aufs
+ Root Dir: /var/lib/docker/aufs
+ Dirs: 289
+Execution Driver: native-0.2
+Kernel Version: 3.16.0-4-amd64
+Operating System: Debian GNU/Linux 8 (jessie)
+WARNING: No memory limit support
+WARNING: No swap limit support
+```
+
+kubectl is a command-line interface for executing commands against a Kubernetes cluster. Run the shell script below to install kubectl:
+
+```
+curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
+```
+
+Deploying to Kubernetes requires a containerized application. Let's review containerizing Python applications.
+
+### Containerization at a glance
+
+Containerization involves enclosing an application in a container with its own operating system. This full machine virtualization option has the advantage of being able to run an application on any machine without concerns about dependencies.
+
+Roman Gaponov's [article][12] serves as a reference. Let's start by creating a container image for our Python code.
+
+### Create a Python container image
+
+To create these images, we will use Docker, which enables us to deploy applications inside isolated Linux software containers. Docker is able to automatically build images using instructions from a Docker file.
+
+This is a Docker file for our Python application:
+
+```
+FROM python:3.6
+MAINTAINER XenonStack
+
+# Creating Application Source Code Directory
+RUN mkdir -p /k8s_python_sample_code/src
+
+# Setting Home Directory for containers
+WORKDIR /k8s_python_sample_code/src
+
+# Installing python dependencies
+COPY requirements.txt /k8s_python_sample_code/src
+RUN pip install --no-cache-dir -r requirements.txt
+
+# Copying src code to Container
+COPY . /k8s_python_sample_code/src/app
+
+# Application Environment variables
+ENV APP_ENV development
+
+# Exposing Ports
+EXPOSE 5035
+
+# Setting Persistent data
+VOLUME ["/app-data"]
+
+# Running Python Application
+CMD ["python", "app.py"]
+```
+
+This Docker file contains instructions to run our sample Python code. It uses the Python 3.5 development environment.
+
+### Build a Python Docker image
+
+We can now build the Docker image from these instructions using this command:
+
+```
+docker build -t k8s_python_sample_code .
+```
+
+This command creates a Docker image for our Python application.
+
+### Publish the container images
+
+We can publish our Python container image to different private/public cloud repositories, like Docker Hub, AWS ECR, Google Container Registry, etc. For this tutorial, we'll use Docker Hub.
+
+Before publishing the image, we need to tag it to a version:
+
+```
+docker tag k8s_python_sample_code:latest k8s_python_sample_code:0.1
+```
+
+### Push the image to a cloud repository
+
+Using a Docker registry other than Docker Hub to store images requires you to add that container registry to the local Docker daemon and Kubernetes Docker daemons. You can look up this information for the different cloud registries. We'll use Docker Hub in this example.
+
+Execute this Docker command to push the image:
+
+```
+docker push k8s_python_sample_code
+```
+
+### Working with CephFS persistent storage
+
+Kubernetes supports many persistent storage providers, including AWS EBS, CephFS, GlusterFS, Azure Disk, NFS, etc. I will cover Kubernetes persistence storage with CephFS.
+
+To use CephFS for persistent data to Kubernetes containers, we will create two files:
+
+persistent-volume.yml
+
+```
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: app-disk1
+ namespace: k8s_python_sample_code
+spec:
+ capacity:
+ storage: 50Gi
+ accessModes:
+ - ReadWriteMany
+ cephfs:
+ monitors:
+ - "172.17.0.1:6789"
+ user: admin
+ secretRef:
+ name: ceph-secret
+ readOnly: false
+```
+
+persistent_volume_claim.yaml
+
+```
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: appclaim1
+ namespace: k8s_python_sample_code
+spec:
+ accessModes:
+ - ReadWriteMany
+ resources:
+ requests:
+ storage: 10Gi
+```
+
+We can now use kubectl to add the persistent volume and claim to the Kubernetes cluster:
+
+```
+$ kubectl create -f persistent-volume.yml
+$ kubectl create -f persistent-volume-claim.yml
+```
+
+We are now ready to deploy to Kubernetes.
+
+### Deploy the application to Kubernetes
+
+To manage the last mile of deploying the application to Kubernetes, we will create two important files: a service file and a deployment file.
+
+Create a file and name it `k8s_python_sample_code.service.yml` with the following content:
+
+```
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ k8s-app: k8s_python_sample_code
+ name: k8s_python_sample_code
+ namespace: k8s_python_sample_code
+spec:
+ type: NodePort
+ ports:
+ - port: 5035
+ selector:
+ k8s-app: k8s_python_sample_code
+```
+
+Create a file and name it `k8s_python_sample_code.deployment.yml` with the following content:
+
+```
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: k8s_python_sample_code
+ namespace: k8s_python_sample_code
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ k8s-app: k8s_python_sample_code
+ spec:
+ containers:
+ - name: k8s_python_sample_code
+ image: k8s_python_sample_code:0.1
+ imagePullPolicy: "IfNotPresent"
+ ports:
+ - containerPort: 5035
+ volumeMounts:
+ - mountPath: /app-data
+ name: k8s_python_sample_code
+ volumes:
+ - name:
+ persistentVolumeClaim:
+ claimName: appclaim1
+```
+
+Finally, use kubectl to deploy the application to Kubernetes:
+
+```
+$ kubectl create -f k8s_python_sample_code.deployment.yml $ kubectl create -f k8s_python_sample_code.service.yml
+```
+
+Your application was successfully deployed to Kubernetes.
+
+You can verify whether your application is running by inspecting the running services:
+
+```
+kubectl get services
+```
+
+May Kubernetes free you from future deployment hassles!
+
+ _Want to learn more about Python? Nanjekye's book, [Python 2 and 3 Compatibility][7]offers clean ways to write code that will run on both Python 2 and 3, including detailed examples of how to convert existing Python 2-compatible code to code that will run reliably on both Python 2 and 3._
+
+
+### About the author
+
+ [][13] Joannah Nanjekye - Straight Outta 256 , I choose Results over Reasons, Passionate Aviator, Show me the code.[More about me][8]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/running-python-application-kubernetes
+
+作者:[Joannah Nanjekye ][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/nanjekyejoannah
+[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://opensource.com/article/18/1/running-python-application-kubernetes?rate=D9iKksKbd9q9vOVb92Mg-v0Iyqn0QVO5fbIERTbSHz4
+[7]:https://www.apress.com/gp/book/9781484229545
+[8]:https://opensource.com/users/nanjekyejoannah
+[9]:https://opensource.com/user/196386/feed
+[10]:https://github.com/jnanjekye/k8s_python_sample_code/tree/master
+[11]:https://docs.docker.com/engine/installation/
+[12]:https://hackernoon.com/docker-tutorial-getting-started-with-python-redis-and-nginx-81a9d740d091
+[13]:https://opensource.com/users/nanjekyejoannah
+[14]:https://opensource.com/users/nanjekyejoannah
+[15]:https://opensource.com/users/nanjekyejoannah
+[16]:https://opensource.com/tags/python
+[17]:https://opensource.com/tags/kubernetes
\ No newline at end of file
diff --git a/sources/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md b/sources/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md
new file mode 100644
index 0000000000..6dce30d6dc
--- /dev/null
+++ b/sources/tech/20180127 How to install KVM on CentOS 7 - RHEL 7 Headless Server.md
@@ -0,0 +1,342 @@
+How to install KVM on CentOS 7 / RHEL 7 Headless Server
+======
+
+
+How do I install and configure KVM (Kernel-based Virtual Machine) on a CentOS 7 or RHEL (Red Hat Enterprise Linux) 7 server? How can I setup KMV on a CentOS 7 and use cloud images/cloud-init for installing guest VM?
+
+
+Kernel-based Virtual Machine (KVM) is virtualization software for CentOS or RHEL 7. KVM turn your server into a hypervisor. This page shows how to setup and manage a virtualized environment with KVM in CentOS 7 or RHEL 7. It also described how to install and administer Virtual Machines (VMs) on a physical server using the CLI. Make sure that **Virtualization Technology (VT)** is enabled in your server 's BIOS. You can also run the following command [to test if CPU Support Intel VT and AMD-V Virtualization tech][1]
+```
+$ lscpu | grep Virtualization
+Virtualization: VT-x
+```
+
+
+
+### Follow installation steps of KVM on CentOS 7/RHEL 7 headless sever
+
+#### Step 1: Install kvm
+
+Type the following [yum command][2]:
+`# yum install qemu-kvm libvirt libvirt-python libguestfs-tools virt-install`
+[![How to install KVM on CentOS 7 RHEL 7 Headless Server][3]][3]
+Start the libvirtd service:
+```
+# systemctl enable libvirtd
+# systemctl start libvirtd
+```
+
+#### Step 2: Verify kvm installation
+
+Make sure KVM module loaded using lsmod command and [grep command][4]:
+`# lsmod | grep -i kvm`
+
+#### Step 3: Configure bridged networking
+
+By default dhcpd based network bridge configured by libvirtd. You can verify that with the following commands:
+```
+# brctl show
+# virsh net-list
+```
+[![KVM default networking][5]][5]
+All VMs (guest machine) only have network access to other VMs on the same server. A private network 192.168.122.0/24 created for you. Verify it:
+`# virsh net-dumpxml default`
+If you want your VMs avilable to other servers on your LAN, setup a a network bridge on the server that connected to the your LAN. Update your nic config file such as ifcfg-enp3s0 or em1:
+`# vi /etc/sysconfig/network-scripts/enp3s0 `
+Add line:
+```
+BRIDGE=br0
+```
+
+[Save and close the file in vi][6]. Edit /etc/sysconfig/network-scripts/ifcfg-br0 and add:
+`# vi /etc/sysconfig/network-scripts/ifcfg-br0`
+Append the following:
+```
+DEVICE="br0"
+# I am getting ip from DHCP server #
+BOOTPROTO="dhcp"
+IPV6INIT="yes"
+IPV6_AUTOCONF="yes"
+ONBOOT="yes"
+TYPE="Bridge"
+DELAY="0"
+```
+
+Restart the networking service (warning ssh command will disconnect, it is better to reboot the box):
+`# systemctl restart NetworkManager`
+Verify it with brctl command:
+`# brctl show`
+
+#### Step 4: Create your first virtual machine
+
+I am going to create a CentOS 7.x VM. First, grab CentOS 7.x latest ISO image using the wget command:
+```
+# cd /var/lib/libvirt/boot/
+# wget https://mirrors.kernel.org/centos/7.4.1708/isos/x86_64/CentOS-7-x86_64-Minimal-1708.iso
+```
+Verify ISO images:
+```
+# wget https://mirrors.kernel.org/centos/7.4.1708/isos/x86_64/sha256sum.txt
+# sha256sum -c sha256sum.txt
+```
+
+##### Create CentOS 7.x VM
+
+In this example, I'm creating CentOS 7.x VM with 2GB RAM, 2 CPU core, 1 nics and 40GB disk space, enter:
+```
+# virt-install \
+--virt-type=kvm \
+--name centos7 \
+--ram 2048 \
+--vcpus=1 \
+--os-variant=centos7.0 \
+--cdrom=/var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-1708.iso \
+--network=bridge=br0,model=virtio \
+--graphics vnc \
+--disk path=/var/lib/libvirt/images/centos7.qcow2,size=40,bus=virtio,format=qcow2
+```
+To configure vnc login from another terminal over ssh and type:
+```
+# virsh dumpxml centos7 | grep vnc
+
+```
+Please note down the port value (i.e. 5901). You need to use an SSH client to setup tunnel and a VNC client to access the remote vnc server. Type the following SSH port forwarding command from your client/desktop/macbook pro system:
+`$ ssh vivek@server1.cyberciti.biz -L 5901:127.0.0.1:5901`
+Once you have ssh tunnel established, you can point your VNC client at your own 127.0.0.1 (localhost) address and port 5901 as follows:
+[![][7]][7]
+You should see CentOS Linux 7 guest installation screen as follows:
+[![][8]][8]
+Now just follow on screen instructions and install CentOS 7. Once installed, go ahead and click the reboot button. The remote server closed the connection to our VNC client. You can reconnect via KVM client to configure the rest of the server including SSH based session or firewall.
+
+#### Step 5: Using cloud images
+
+The above installation method is okay for learning purpose or a single VM. Do you need to deploy lots of VMs? Try cloud images. You can modify pre built cloud images as per your needs. For example, add users, ssh keys, setup time zone, and more using [Cloud-init][9] which is the defacto multi-distribution package that handles early initialization of a cloud instance. Let us see how to create CentOS 7 vm with 1024MB ram, 20GB disk space, and 1 vCPU.
+
+##### Grab CentOS 7 cloud image
+
+```
+# cd /var/lib/libvirt/boot
+# wget http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2
+```
+
+##### Create required directories
+
+```
+# D=/var/lib/libvirt/images
+# VM=centos7-vm1 ## vm name ##
+# mkdir -vp $D/$VM
+mkdir: created directory '/var/lib/libvirt/images/centos7-vm1'
+```
+
+##### Create meta-data file
+
+```
+# cd $D/$VM
+# vi meta-data
+```
+Append the following:
+```
+instance-id: centos7-vm1
+local-hostname: centos7-vm1
+```
+
+##### Crete user-data file
+
+I am going to login into VM using ssh keys. So make sure you have ssh-keys in place:
+`# ssh-keygen -t ed25519 -C "VM Login ssh key"`
+[![ssh-keygen command][10]][11]
+See "[How To Setup SSH Keys on a Linux / Unix System][12]" for more info. Edit user-data as follows:
+```
+# cd $D/$VM
+# vi user-data
+```
+Add as follows (replace hostname, users, ssh-authorized-keys as per your setup):
+```
+#cloud-config
+
+# Hostname management
+preserve_hostname: False
+hostname: centos7-vm1
+fqdn: centos7-vm1.nixcraft.com
+
+# Users
+users:
+ - default
+ - name: vivek
+ groups: ['wheel']
+ shell: /bin/bash
+ sudo: ALL=(ALL) NOPASSWD:ALL
+ ssh-authorized-keys:
+ - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMP3MOF2ot8MOdNXCpHem0e2Wemg4nNmL2Tio4Ik1JY VM Login ssh key
+
+# Configure where output will go
+output:
+ all: ">> /var/log/cloud-init.log"
+
+# configure interaction with ssh server
+ssh_genkeytypes: ['ed25519', 'rsa']
+
+# Install my public ssh key to the first user-defined user configured
+# in cloud.cfg in the template (which is centos for CentOS cloud images)
+ssh_authorized_keys:
+ - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIMP3MOF2ot8MOdNXCpHem0e2Wemg4nNmL2Tio4Ik1JY VM Login ssh key
+
+# set timezone for VM
+timezone: Asia/Kolkata
+
+# Remove cloud-init
+runcmd:
+ - systemctl stop network && systemctl start network
+ - yum -y remove cloud-init
+```
+
+##### Copy cloud image
+
+```
+# cd $D/$VM
+# cp /var/lib/libvirt/boot/CentOS-7-x86_64-GenericCloud.qcow2 $VM.qcow2
+```
+
+##### Create 20GB disk image
+
+```
+# cd $D/$VM
+# export LIBGUESTFS_BACKEND=direct
+# qemu-img create -f qcow2 -o preallocation=metadata $VM.new.image 20G
+# virt-resize --quiet --expand /dev/sda1 $VM.qcow2 $VM.new.image
+```
+[![Set VM image disk size][13]][13]
+Overwrite it resized image:
+```
+# cd $D/$VM
+# mv $VM.new.image $VM.qcow2
+```
+
+##### Creating a cloud-init ISO
+
+`# mkisofs -o $VM-cidata.iso -V cidata -J -r user-data meta-data`
+[![Creating a cloud-init ISO][14]][14]
+
+##### Creating a pool
+
+```
+# virsh pool-create-as --name $VM --type dir --target $D/$VM
+Pool centos7-vm1 created
+```
+
+##### Installing a CentOS 7 VM
+
+```
+# cd $D/$VM
+# virt-install --import --name $VM \
+--memory 1024 --vcpus 1 --cpu host \
+--disk $VM.qcow2,format=qcow2,bus=virtio \
+--disk $VM-cidata.iso,device=cdrom \
+--network bridge=virbr0,model=virtio \
+--os-type=linux \
+--os-variant=centos7.0 \
+--graphics spice \
+--noautoconsole
+```
+Delete unwanted files:
+```
+# cd $D/$VM
+# virsh change-media $VM hda --eject --config
+# rm meta-data user-data centos7-vm1-cidata.iso
+```
+
+##### Find out IP address of VM
+
+`# virsh net-dhcp-leases default`
+[![CentOS7-VM1- Created][15]][15]
+
+##### Log in to your VM
+
+Use ssh command:
+`# ssh vivek@192.168.122.85`
+[![Sample VM session][16]][16]
+
+### Useful commands
+
+Let us see some useful commands for managing VMs.
+
+#### List all VMs
+
+`# virsh list --all`
+
+#### Get VM info
+
+```
+# virsh dominfo vmName
+# virsh dominfo centos7-vm1
+```
+
+#### Stop/shutdown a VM
+
+`# virsh shutdown centos7-vm1`
+
+#### Start VM
+
+`# virsh start centos7-vm1`
+
+#### Mark VM for autostart at boot time
+
+`# virsh autostart centos7-vm1`
+
+#### Reboot (soft & safe reboot) VM
+
+`# virsh reboot centos7-vm1`
+Reset (hard reset/not safe) VM
+`# virsh reset centos7-vm1`
+
+#### Delete VM
+
+```
+# virsh shutdown centos7-vm1
+# virsh undefine centos7-vm1
+# virsh pool-destroy centos7-vm1
+# D=/var/lib/libvirt/images
+# VM=centos7-vm1
+# rm -ri $D/$VM
+```
+To see a complete list of virsh command type
+```
+# virsh help | less
+# virsh help | grep reboot
+```
+
+
+### About the author
+
+The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on [Twitter][17], [Facebook][18], [Google+][19].
+
+--------------------------------------------------------------------------------
+
+via: https://www.cyberciti.biz/faq/how-to-install-kvm-on-centos-7-rhel-7-headless-server/
+
+作者:[Vivek Gite][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.cyberciti.biz
+[1]:https://www.cyberciti.biz/faq/linux-xen-vmware-kvm-intel-vt-amd-v-support/
+[2]:https://www.cyberciti.biz/faq/rhel-centos-fedora-linux-yum-command-howto/ (See Linux/Unix yum command examples for more info)
+[3]:https://www.cyberciti.biz/media/new/faq/2018/01/How-to-install-KVM-on-CentOS-7-RHEL-7-Headless-Server.jpg
+[4]:https://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/ (See Linux/Unix grep command examples for more info)
+[5]:https://www.cyberciti.biz/media/new/faq/2018/01/KVM-default-networking.jpg
+[6]:https://www.cyberciti.biz/faq/linux-unix-vim-save-and-quit-command/
+[7]:https://www.cyberciti.biz/media/new/faq/2016/01/vnc-client.jpg
+[8]:https://www.cyberciti.biz/media/new/faq/2016/01/centos7-guest-vnc.jpg
+[9]:https://cloudinit.readthedocs.io/en/latest/index.html
+[10]:https://www.cyberciti.biz/media/new/faq/2018/01/ssh-keygen-pub-key.jpg
+[11]:https://www.cyberciti.biz/faq/linux-unix-generating-ssh-keys/
+[12]:https://www.cyberciti.biz/faq/how-to-set-up-ssh-keys-on-linux-unix/
+[13]:https://www.cyberciti.biz/media/new/faq/2018/01/Set-VM-image-disk-size.jpg
+[14]:https://www.cyberciti.biz/media/new/faq/2018/01/Creating-a-cloud-init-ISO.jpg
+[15]:https://www.cyberciti.biz/media/new/faq/2018/01/CentOS7-VM1-Created.jpg
+[16]:https://www.cyberciti.biz/media/new/faq/2018/01/Sample-VM-session.jpg
+[17]:https://twitter.com/nixcraft
+[18]:https://facebook.com/nixcraft
+[19]:https://plus.google.com/+CybercitiBiz
diff --git a/sources/tech/20180127 Your instant Kubernetes cluster.md b/sources/tech/20180127 Your instant Kubernetes cluster.md
new file mode 100644
index 0000000000..b17619762a
--- /dev/null
+++ b/sources/tech/20180127 Your instant Kubernetes cluster.md
@@ -0,0 +1,171 @@
+Your instant Kubernetes cluster
+============================================================
+
+
+This is a condensed and updated version of my previous tutorial [Kubernetes in 10 minutes][10]. I've removed just about everything I can so this guide still makes sense. Use it when you want to create a cluster on the cloud or on-premises as fast as possible.
+
+### 1.0 Pick a host
+
+We will be using Ubuntu 16.04 for this guide so that you can copy/paste all the instructions. Here are several environments where I've tested this guide. Just pick where you want to run your hosts.
+
+* [DigitalOcean][1] - developer cloud
+
+* [Civo][2] - UK developer cloud
+
+* [Packet][3] - bare metal cloud
+
+* 2x Dell Intel i7 boxes - at home
+
+> Civo is a relatively new developer cloud and one thing that I really liked was how quickly they can bring up hosts - in about 25 seconds. I'm based in the UK so I also get very low latency.
+
+### 1.1 Provision the machines
+
+You can get away with a single host for testing but I'd recommend at least three so we have a single master and two worker nodes.
+
+Here are some other guidelines:
+
+* Pick dual-core hosts with ideally at least 2GB RAM
+
+* If you can pick a custom username when provisioning the host then do that rather than root. For example Civo offers an option of `ubuntu`, `civo` or `root`.
+
+Now run through the following steps on each machine. It should take you less than 5-10 minutes. If that's too slow for you then you can use my utility script [kept in a Gist][11]:
+
+```
+$ curl -sL https://gist.githubusercontent.com/alexellis/e8bbec45c75ea38da5547746c0ca4b0c/raw/23fc4cd13910eac646b13c4f8812bab3eeebab4c/configure.sh | sh
+
+```
+
+### 1.2 Login and install Docker
+
+Install Docker from the Ubuntu apt repository. This will be an older version of Docker but as Kubernetes is tested with old versions of Docker it will work in our favour.
+
+```
+$ sudo apt-get update \
+ && sudo apt-get install -qy docker.io
+
+```
+
+### 1.3 Disable the swap file
+
+This is now a mandatory step for Kubernetes. The easiest way to do this is to edit `/etc/fstab` and to comment out the line referring to swap.
+
+To save a reboot then type in `sudo swapoff -a`.
+
+> Disabling swap memory may appear like a strange requirement at first. If you are curious about this step then [read more here][4].
+
+### 1.4 Install Kubernetes packages
+
+```
+$ sudo apt-get update \
+ && sudo apt-get install -y apt-transport-https \
+ && curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
+
+$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" \
+ | sudo tee -a /etc/apt/sources.list.d/kubernetes.list \
+ && sudo apt-get update
+
+$ sudo apt-get update \
+ && sudo apt-get install -y \
+ kubelet \
+ kubeadm \
+ kubernetes-cni
+
+```
+
+### 1.5 Create the cluster
+
+At this point we create the cluster by initiating the master with `kubeadm`. Only do this on the master node.
+
+> Despite any warnings I have been assured by [Weaveworks][5] and Lucas (the maintainer) that `kubeadm` is suitable for production use.
+
+```
+$ sudo kubeadm init
+
+```
+
+If you missed a step or there's a problem then `kubeadm` will let you know at this point.
+
+Take a copy of the Kube config:
+
+```
+mkdir -p $HOME/.kube
+sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
+sudo chown $(id -u):$(id -g) $HOME/.kube/config
+
+```
+
+Make sure you note down the join token command i.e.
+
+```
+$ sudo kubeadm join --token c30633.d178035db2b4bb9a 10.0.0.5:6443 --discovery-token-ca-cert-hash sha256:
+
+```
+
+### 2.0 Install networking
+
+Many networking providers are available for Kubernetes, but none are included by default, so let's use Weave Net from [Weaveworks][12] which is one of the most popular options in the Kubernetes community. It tends to work out of the box without additional configuration.
+
+```
+$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
+
+```
+
+If you have private networking enabled on your host then you may need to alter the private subnet that Weavenet uses for allocating IP addresses to Pods (containers). Here's an example of how to do that:
+
+```
+$ curl -SL "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.IPALLOC_RANGE=172.16.6.64/27" \
+| kubectl apply -f -
+
+```
+
+> Weave also have a very cool visualisation tool called Weave Cloud. It's free and will show you the path traffic is taking between your Pods. [See here for an example with the OpenFaaS project][6].
+
+### 2.2 Join the worker nodes to the cluster
+
+Now you can switch to each of your workers and use the `kubeadm join` command from 1.5\. Once you run that log out of the workers.
+
+### 3.0 Profit
+
+That's it - we're done. You have a cluster up and running and can deploy your applications. If you need to setup a dashboard UI then consult the [Kubernetes documentation][13].
+
+```
+$ kubectl get nodes
+NAME STATUS ROLES AGE VERSION
+openfaas1 Ready master 20m v1.9.2
+openfaas2 Ready 19m v1.9.2
+openfaas3 Ready 19m v1.9.2
+
+```
+
+If you want to see my running through creating a cluster step-by-step and showing you how `kubectl` works then checkout my video below and make sure you subscribe
+
+
+You can also get an "instant" Kubernetes cluster on your Mac for development using Minikube or Docker for Mac Edge edition. [Read my review and first impressions here][14].
+
+
+--------------------------------------------------------------------------------
+
+via: https://blog.alexellis.io/your-instant-kubernetes-cluster/
+
+作者:[Alex Ellis ][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://blog.alexellis.io/author/alex/
+[1]:https://www.digitalocean.com/
+[2]:https://www.civo.com/
+[3]:https://packet.net/
+[4]:https://github.com/kubernetes/kubernetes/issues/53533
+[5]:https://weave.works/
+[6]:https://www.weave.works/blog/openfaas-gke
+[7]:https://blog.alexellis.io/tag/kubernetes/
+[8]:https://blog.alexellis.io/tag/k8s/
+[9]:https://blog.alexellis.io/tag/cloud-native/
+[10]:https://www.youtube.com/watch?v=6xJwQgDnMFE
+[11]:https://gist.github.com/alexellis/e8bbec45c75ea38da5547746c0ca4b0c
+[12]:https://weave.works/
+[13]:https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
+[14]:https://blog.alexellis.io/docker-for-mac-with-kubernetes/
+[15]:https://blog.alexellis.io/your-instant-kubernetes-cluster/#
\ No newline at end of file
diff --git a/sources/tech/20180128 Getting Linux Jobs.md b/sources/tech/20180128 Getting Linux Jobs.md
new file mode 100644
index 0000000000..a7f1a075a5
--- /dev/null
+++ b/sources/tech/20180128 Getting Linux Jobs.md
@@ -0,0 +1,98 @@
+Getting Linux Jobs
+======
+
+In a qualitative review of job posting websites, even highly skilled Linux administrators would be hamstrung to succeed in getting to the stage of an interview.
+
+All of this results in hundreds of decent and skilled people being snubbed without cause simply because today's job market requires a few extra tools to increase the odds.
+
+I have two colleagues and a cousin who have all received certifications with RedHat, managed quite extensive server rooms, and received earnest recommendations from former employers.
+
+All of these skills, certifications and experience come to naught as they apply to employer ads that are crudely constructed by someone hurriedly cutting and pasting snippets of "skill words" from a list of technical terms.
+
+Not surprisingly, today's politeness has gone the way of the bird, and a **non-response** from companies posting ads seems to be the new way of communicating.
+
+Unfortunately, it also means that these recruiters/HR personnel probably did **not** get the best candidate.
+
+The reason I can say this with such conviction is because of the type of buffoonery that takes place so often when creating job ads in the first place.
+
+Walter, another [Reallylinux.com][3] guest writer, presented how [**Job Want Ads Have Gone Mad**][4].
+
+Perhaps he's right. However, I believe every Linux job seeker can avoid pitfalls of a job hunt by keeping in mind **three key facts** about job ads.
+
+First, few advertisements for Linux administrators are exclusively about Linux.
+
+Bear in mind the occasional Linux system administrator job, where you would actually be using Linux on servers. Instead, many jobs that rise up on a "Linux administrator" search are actually referring to a plethora of 'NX operating systems.
+
+For example, here is a quote from a **"Linux Administrator"** job posting:
+This role will provide support for build system integration, especially operating system installation support for BSD applications...
+
+Or another ad declares in the bowels of its content:
+Windows administration experience required.
+
+Ironically, if you show up to interview for any of these types of jobs and focus on Linux, they probably will not choose you.
+
+Even more importantly, if you simply include Linux as your expertise, they may not even bother with your resume, because they can't tell the difference between UNIX, BSD, Linux, etc.
+
+As a result, if you are conscientious and only include Linux on your resume, you are automatically out. But change that Linux to UNIX/Linux and you end up getting a bit farther in the human resources bureaucracy.
+
+I had two colleagues that ended up changing this on their resumes and getting a much better hit ratio for interviews, which were still slim pickings because most job ads are tailored with some particular person already in mind. The main intent behind such job ads being a cover for the ass of the department making the claim of having an open job.
+
+Second, the only person at the company who cares at all about the system administrator position is the technical lead/manager hiring for the slot. Others at the company, including the HR contact or the management could not care less.
+
+I remember sitting in a board room as a fly on the wall, hearing one executive vice president refer to server administrators as "dime a dozen geeks." How wrong they are to suggest this.
+
+Ironically, one day should the mail system fail, or the PBX connectivity hiccup, or perhaps core business files disappear from the intranet, these same executives are the first to get on the phone and threaten to fire the system admins.
+
+Perhaps if they would stop leaving so many hot air telephone messages, or filling their emails with 35MB photographs of another vice president's fishing trip and wife, the servers wouldn't be so problematic.
+
+Be aware that a Linux administrator ad, or any job posting for server administrator is placed because someone at the TECHNICAL level sees an urgent need for staffing. You're not going to get any empathy talking to HR or any leader of the company. Instead, take the time to find out who the hiring technical manager is and try to telephone them.
+
+You can always call them directly because you have some "specific technical questions" you know the HR person could not answer. This opens the dialogue with the person who actually cares that the position is filled and ensures you get a foot in because you took the time for personal contact, even if it was a 60 second phone call.
+
+What if the HR beauracracy won't let you through?
+
+Start asking as many tech questions as possible direct to the HR hiring contact, such as how their Linux clusters are setup and do they run VMs exclusively? Anything relatively technical will send these HR people in a tizzy and allow you the question: "may I contact the technical manager of the team?"
+
+If the response is a fluffy "maybe" or "I'll get back to you on that" they already filled the slot in their mind with someone else two weeks earlier, such as the HR staff member's fiance. They simply wanted it to look less like nepotism and more like indeterminism with a dash of egoism.
+
+```
+"They simply wanted it to look less like nepotism and more like indeterminism with a dash of egoism."
+```
+
+So take the time to find out who is the direct TECHNICAL leader hiring for the position and talk to them. It can make a difference and get you past some of the baloney.
+
+Third, few job ads today include any semblance of reality.
+
+I've seen enough ads requiring a junior system administrator with expertise that senior level experts don't have, to know the plan is to list the blue sky wish list and then find out who applies.
+
+In this situation, the Linux administrator ad you apply for, should include some key phrases for which you already have experience or certifications.
+
+The trick is to so overload your resume with the key phrases that MATCH their ad, it becomes almost impossible for them to determine which phrases you left out.
+
+This doesn't necessarily translate to a job, but it often adds enough intrigue to get you an interview, which now a days is a major step.
+
+By understanding and applying these three techniques, hopefully those seeking Linux administrator jobs have a head start on those who have only a slim chance in hell.
+
+Even if these tips don't get you interviews right away, you can use the experience and awareness when you go to the next trade show, or company sponsored technical conference.
+
+I strongly recommend you regularly attend these as well, especially if they are reasonably close, as they always provide a kick start to networking.
+
+Remember that job networking now a days is a pseudonym for "getting the gossip on which companies are actually hiring and which ones are just lying about jobs to give the appearance of growth for shareholders."
+
+
+
+--------------------------------------------------------------------------------
+
+via: http://reallylinux.com/docs/gettinglinuxjobs.shtml
+
+作者:[Andrea W.Codingly][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://reallylinux.com
+[1]:http://www.reallylinux.com
+[2]:http://reallylinux.com/docs/linuxrecessionproof.shtml
+[3]:http://reallylinux.com
+[4]:http://reallylinux.com/docs/wantadsmad.shtml
diff --git a/sources/tech/20180128 How to add network bridge with nmcli (NetworkManager) on Linux.md b/sources/tech/20180128 How to add network bridge with nmcli (NetworkManager) on Linux.md
new file mode 100644
index 0000000000..bf7772ef1a
--- /dev/null
+++ b/sources/tech/20180128 How to add network bridge with nmcli (NetworkManager) on Linux.md
@@ -0,0 +1,146 @@
+How to add network bridge with nmcli (NetworkManager) on Linux
+======
+
+I am using Debian Linux 9 "stretch" on the desktop. I would like to create network bridge with NetworkManager. But, I am unable to find the option to add br0. How can I create or add network bridge with nmcli for NetworkManager on Linux?
+
+A bridge is nothing but a device which joins two local networks into one network. It works at the data link layer, i.e., layer 2 of the OSI model. Network bridge often used with virtualization and other software. Disabling NetworkManager for a simple bridge especially on Linux Laptop/desktop doesn't make any sense. The nmcli tool can create Persistent bridge configuration without editing any files. **This page shows how to create a bridge interface using the Network Manager command line tool called nmcli**.
+
+
+
+### How to create/add network bridge with nmcli
+
+The procedure to add a bridge interface on Linux is as follows when you want to use Network Manager:
+
+1. Open the Terminal app
+2. Get info about the current connection:
+```
+nmcli con show
+```
+3. Add a new bridge:
+```
+nmcli con add type bridge ifname br0
+```
+4. Create a slave interface:
+```
+nmcli con add type bridge-slave ifname eno1 master br0
+```
+5. Turn on br0:
+```
+nmcli con up br0
+```
+
+Let us see how to create a bridge, named br0 in details.
+
+### Get current network config
+
+You can view connection from the Network Manager GUI in settings:
+[![Getting Network Info on Linux][1]][1]
+Another option is to type the following command:
+```
+$ nmcli con show
+$ nmcli connection show --active
+```
+[![View the connections with nmcli][2]][2]
+I have a "Wired connection 1" which uses the eno1 Ethernet interface. My system has a VPN interface too. I am going to setup a bridge interface named br0 and add, (or enslave) an interface to eno1.
+
+### How to create a bridge, named br0
+
+```
+$ sudo nmcli con add ifname br0 type bridge con-name br0
+$ sudo nmcli con add type bridge-slave ifname eno1 master br0
+$ nmcli connection show
+```
+[![Create bridge interface using nmcli on Linux][3]][3]
+You can disable STP too:
+```
+$ sudo nmcli con modify br0 bridge.stp no
+$ nmcli con show
+$ nmcli -f bridge con show br0
+```
+The last command shows the bridge settings including disabled STP:
+```
+bridge.mac-address: --
+bridge.stp: no
+bridge.priority: 32768
+bridge.forward-delay: 15
+bridge.hello-time: 2
+bridge.max-age: 20
+bridge.ageing-time: 300
+bridge.multicast-snooping: yes
+```
+
+
+### How to turn on bridge interface
+
+You must turn off "Wired connection 1" and turn on br0:
+```
+$ sudo nmcli con down "Wired connection 1"
+$ sudo nmcli con up br0
+$ nmcli con show
+```
+Use [ip command][4] to view the IP settings:
+```
+$ ip a s
+$ ip a s br0
+```
+[![Build a network bridge with nmcli on Linux][5]][5]
+
+### Optional: How to use br0 with KVM
+
+Now you can connect VMs (virtual machine) created with KVM/VirtualBox/VMware workstation to a network directly without using NAT. Create a file named br0.xml for KVM using vi command or [cat command][6]:
+`$ cat /tmp/br0.xml`
+Append the following code:
+```
+
+ br0
+
+
+
+```
+
+Run virsh command as follows:
+```
+# virsh net-define /tmp/br0.xml
+# virsh net-start br0
+# virsh net-autostart br0
+# virsh net-list --all
+```
+Sample outputs:
+```
+ Name State Autostart Persistent
+----------------------------------------------------------
+ br0 active yes yes
+ default inactive no yes
+```
+
+
+For more info read the following man page:
+```
+$ man ip
+$ man nmcli
+```
+
+### about the author
+
+The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on [Twitter][7], [Facebook][8], [Google+][9].
+
+--------------------------------------------------------------------------------
+
+via: https://www.cyberciti.biz/faq/how-to-add-network-bridge-with-nmcli-networkmanager-on-linux/
+
+作者:[Vivek Gite][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.cyberciti.biz
+[1]:https://www.cyberciti.biz/media/new/faq/2018/01/Getting-Network-Info-on-Linux.jpg
+[2]:https://www.cyberciti.biz/media/new/faq/2018/01/View-the-connections-with-nmcli.jpg
+[3]:https://www.cyberciti.biz/media/new/faq/2018/01/Create-bridge-interface-using-nmcli-on-Linux.jpg
+[4]:https://www.cyberciti.biz/faq/linux-ip-command-examples-usage-syntax/ (See Linux/Unix ip command examples for more info)
+[5]:https://www.cyberciti.biz/media/new/faq/2018/01/Build-a-network-bridge-with-nmcli-on-Linux.jpg
+[6]:https://www.cyberciti.biz/faq/linux-unix-appleosx-bsd-cat-command-examples/ (See Linux/Unix cat command examples for more info)
+[7]:https://twitter.com/nixcraft
+[8]:https://facebook.com/nixcraft
+[9]:https://plus.google.com/+CybercitiBiz
diff --git a/sources/tech/20180129 5 Real World Uses for Redis.md b/sources/tech/20180129 5 Real World Uses for Redis.md
new file mode 100644
index 0000000000..61f7c09b3b
--- /dev/null
+++ b/sources/tech/20180129 5 Real World Uses for Redis.md
@@ -0,0 +1,109 @@
+5 Real World Uses for Redis
+============================================================
+
+
+Redis is a powerful in-memory data structure store which has many uses including a database, a cache, and a message broker. Most people often think of it a simple key-value store, but it has so much more power. I will be going over some real world examples of some of the many things Redis can do for you.
+
+### 1\. Full Page Cache
+
+The first thing is full page caching. If you are using server-side rendered content, you do not want to re-render each page for every single request. Using a cache like Redis, you can cache regularly requested content and drastically decrease latency for your most requested pages, and most frameworks have hooks for caching your pages with Redis.
+Simple Commands
+
+```
+// Set the page that will last 1 minute
+SET key "..." EX 60
+
+// Get the page
+GET key
+
+```
+
+### 2\. Leaderboard
+
+One of the places Redis shines is for leaderboards. Because Redis is in-memory, it can deal with incrementing and decrementing very fast and efficiently. Compare this to running a SQL query every request the performance gains are huge! This combined with Redis's sorted sets means you can grab only the highest rated items in the list in milliseconds, and it is stupid easy to implement.
+Simple Commands
+
+```
+// Add an item to the sorted set
+ZADD sortedSet 1 "one"
+
+// Get all items from the sorted set
+ZRANGE sortedSet 0 -1
+
+// Get all items from the sorted set with their score
+ZRANGE sortedSet 0 -1 WITHSCORES
+
+```
+
+### 3\. Session Storage
+
+The most common use for Redis I have seen is session storage. Unlike other session stores like Memcache, Redis can persist data so in the situation where your cache goes down when it comes back up all the data will still be there. Although this isn't mission critical to be persisted, this feature can save your users lots of headaches. No one likes their session to be randomly dropped for no reason.
+Simple Commands
+
+```
+// Set session that will last 1 minute
+SET randomHash "{userId}" EX 60
+
+// Get userId
+GET randomHash
+
+```
+
+### 4\. Queue
+
+One of the less common, but very useful things you can do with Redis is queue things. Whether it's a queue of emails or data to be consumed by another application, you can create an efficient queue it in Redis. Using this functionality is easy and natural for any developer who is familiar with Stacks and pushing and popping items.
+Simple Commands
+
+```
+// Add a Message
+HSET messages
+ZADD due
+
+// Recieving Message
+ZRANGEBYSCORE due -inf LIMIT 0 1
+HGET messages
+
+// Delete Message
+ZREM due
+HDEL messages
+
+```
+
+### 5\. Pub/Sub
+
+The final real world use for Redis I am going to bring up in this post is pub/sub. This is one of the most powerful features Redis has built in; the possibilities are limitless. You can create a real-time chat system with it, trigger notifications for friend requests on social networks, etc... This feature is one of the most underrated features Redis offers but is very powerful, yet simple to use.
+Simple Commands
+
+```
+// Add a message to a channel
+PUBLISH channel message
+
+// Recieve messages from a channel
+SUBSCRIBE channel
+
+```
+
+### Conclusion
+
+I hope you enjoyed this list of some of the many real world uses for Redis. This is just scratching the surface of what Redis can do for you, but I hope it gave you some ideas of how you can use the full potential Redis has to offer.
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Hi, my name is Ryan! I am a Software Developer with experience in many web frameworks and libraries including NodeJS, Django, Golang, and Laravel.
+
+
+-------------------
+
+
+via: https://ryanmccue.ca/5-real-world-uses-for-redis/
+
+作者:[Ryan McCue ][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://ryanmccue.ca/author/ryan/
+[1]:https://ryanmccue.ca/author/ryan/
\ No newline at end of file
diff --git a/sources/tech/20180129 A look inside Facebooks open source program.md b/sources/tech/20180129 A look inside Facebooks open source program.md
new file mode 100644
index 0000000000..3610cec043
--- /dev/null
+++ b/sources/tech/20180129 A look inside Facebooks open source program.md
@@ -0,0 +1,68 @@
+A look inside Facebook's open source program
+============================================================
+
+### Facebook developer Christine Abernathy discusses how open source helps the company share insights and boost innovation.
+
+
+Image by : opensource.com
+
+
+Open source becomes more ubiquitous every year, appearing everywhere from [government municipalities][11] to [universities][12]. Companies of all sizes are also increasingly turning to open source software. In fact, some companies are taking open source a step further by supporting projects financially or working with developers.
+
+Facebook's open source program, for example, encourages others to release their code as open source, while working and engaging with the community to support open source projects. [Christine Abernathy][13], a Facebook developer, open source advocate, and member of the company's open source team, visited the Rochester Institute of Technology last November, presenting at the [November edition][14] of the FOSS Talks speaker series. In her talk, Abernathy explained how Facebook approaches open source and why it's an important part of the work the company does.
+
+### Facebook and open source
+
+Abernathy said that open source plays a fundamental role in Facebook's mission to create community and bring the world closer together. This ideological match is one motivating factor for Facebook's participation in open source. Additionally, Facebook faces unique infrastructure and development challenges, and open source provides a platform for the company to share solutions that could help others. Open source also provides a way to accelerate innovation and create better software, helping engineering teams produce better software and work more transparently. Today, Facebook's 443 projects on GitHub comprise 122,000 forks, 292,000 commits, and 732,000 followers.
+
+
+
+
+
+Some of the Facebook projects released as open source include React, GraphQL, Caffe2, and others. (Image by Christine Abernathy, used with permission)
+
+### Lessons learned
+
+Abernathy emphasized that Facebook has learned many lessons from the open source community, and it looks forward to learning many more. She identified the three most important ones:
+
+* Share what's useful
+
+* Highlight your heroes
+
+* Fix common pain points
+
+ _Christine Abernathy visited RIT as part of the FOSS Talks speaker series. Every month, a guest speaker from the open source world shares wisdom, insight, and advice about the open source world with students interested in free and open source software. The [FOSS @ MAGIC][3] community is thankful to have Abernathy attend as a speaker._
+
+### About the author
+
+ [][15] Justin W. Flory - Justin is a student at the [Rochester Institute of Technology][4]majoring in Networking and Systems Administration. He is currently a contributor to the [Fedora Project][5]. In Fedora, Justin is the editor-in-chief of the [Fedora Magazine][6], the lead of the [Community... ][7][more about Justin W. Flory][8][More about me][9]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/inside-facebooks-open-source-program
+
+作者:[Justin W. Flory ][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/jflory
+[1]:https://opensource.com/file/383786
+[2]:https://opensource.com/article/18/1/inside-facebooks-open-source-program?rate=H9_bfSwXiJfi2tvOLiDxC_tbC2xkEOYtCl-CiTq49SA
+[3]:http://foss.rit.edu/
+[4]:https://www.rit.edu/
+[5]:https://fedoraproject.org/wiki/Overview
+[6]:https://fedoramagazine.org/
+[7]:https://fedoraproject.org/wiki/CommOps
+[8]:https://opensource.com/users/jflory
+[9]:https://opensource.com/users/jflory
+[10]:https://opensource.com/user/74361/feed
+[11]:https://opensource.com/article/17/8/tirana-government-chooses-open-source
+[12]:https://opensource.com/article/16/12/2016-election-night-hackathon
+[13]:https://twitter.com/abernathyca
+[14]:https://www.eventbrite.com/e/fossmagic-talks-open-source-facebook-with-christine-abernathy-tickets-38955037566#
+[15]:https://opensource.com/users/jflory
+[16]:https://opensource.com/users/jflory
+[17]:https://opensource.com/users/jflory
+[18]:https://opensource.com/article/18/1/inside-facebooks-open-source-program#comments
\ No newline at end of file
diff --git a/sources/tech/20180129 Advanced Python Debugging with pdb.md b/sources/tech/20180129 Advanced Python Debugging with pdb.md
new file mode 100644
index 0000000000..80f17e23a3
--- /dev/null
+++ b/sources/tech/20180129 Advanced Python Debugging with pdb.md
@@ -0,0 +1,363 @@
+translating by lujun9972
+Advanced Python Debugging with pdb
+======
+
+
+
+Python's built-in [`pdb`][1] module is extremely useful for interactive debugging, but has a bit of a learning curve. For a long time, I stuck to basic `print`-debugging and used `pdb` on a limited basis, which meant I missed out on a lot of features that would have made debugging faster and easier.
+
+In this post I will show you a few tips I've picked up over the years to level up my interactive debugging skills.
+
+## Print debugging vs. interactive debugging
+
+First, why would you want to use an interactive debugger instead of inserting `print` or `logging` statements into your code?
+
+With `pdb`, you have a lot more flexibility to run, resume, and alter the execution of your program without touching the underlying source. Once you get good at this, it means more time spent diving into issues and less time context switching back and forth between your editor and the command line.
+
+Also, by not touching the underlying source code, you will have the ability to step into third party code (e.g. modules installed from PyPI) and the standard library.
+
+## Post-mortem debugging
+
+The first workflow I used after moving away from `print` debugging was `pdb`'s "post-mortem debugging" mode. This is where you run your program as usual, but whenever an unhandled exception is thrown, you drop down into the debugger to poke around in the program state. After that, you attempt to make a fix and repeat the process until the problem is resolved.
+
+You can run an existing script with the post-mortem debugger by using Python's `-mpdb` option:
+```
+python3 -mpdb path/to/script.py
+
+```
+
+From here, you are dropped into a `(Pdb)` prompt. To start execution, you use the `continue` or `c` command. If the program executes successfully, you will be taken back to the `(Pdb)` prompt where you can restart the execution again. At this point, you can use `quit` / `q` or Ctrl+D to exit the debugger.
+
+If the program throws an unhandled exception, you'll also see a `(Pdb)` prompt, but with the program execution stopped at the line that threw the exception. From here, you can run Python code and debugger commands at the prompt to inspect the current program state.
+
+## Testing our basic workflow
+
+To see how these basic debugging steps work, I'll be using this (buggy) program:
+```
+import random
+
+MAX = 100
+
+def main(num_loops=1000):
+ for i in range(num_loops):
+ num = random.randint(0, MAX)
+ denom = random.randint(0, MAX)
+ result = num / denom
+ print("{} divided by {} is {:.2f}".format(num, denom, result))
+
+if __name__ == "__main__":
+ import sys
+ arg = sys.argv[-1]
+ if arg.isdigit():
+ main(arg)
+ else:
+ main()
+
+```
+
+We're expecting the program to do some basic math operations on random numbers in a loop and print the result. Try running it normally and you will see one of the bugs:
+```
+$ python3 script.py
+2 divided by 30 is 0.07
+65 divided by 41 is 1.59
+0 divided by 70 is 0.00
+...
+38 divided by 26 is 1.46
+Traceback (most recent call last):
+ File "script.py", line 16, in
+ main()
+ File "script.py", line 7, in main
+ result = num / denom
+ZeroDivisionError: division by zero
+
+```
+
+Let's try post-mortem debugging this error:
+```
+$ python3 -mpdb script.py
+> ./src/script.py(1)()
+-> import random
+(Pdb) c
+49 divided by 46 is 1.07
+...
+Traceback (most recent call last):
+ File "/usr/lib/python3.4/pdb.py", line 1661, in main
+ pdb._runscript(mainpyfile)
+ File "/usr/lib/python3.4/pdb.py", line 1542, in _runscript
+ self.run(statement)
+ File "/usr/lib/python3.4/bdb.py", line 431, in run
+ exec(cmd, globals, locals)
+ File "", line 1, in
+ File "./src/script.py", line 1, in
+ import random
+ File "./src/script.py", line 7, in main
+ result = num / denom
+ZeroDivisionError: division by zero
+Uncaught exception. Entering post mortem debugging
+Running 'cont' or 'step' will restart the program
+> ./src/script.py(7)main()
+-> result = num / denom
+(Pdb) num
+76
+(Pdb) denom
+0
+(Pdb) random.randint(0, MAX)
+56
+(Pdb) random.randint(0, MAX)
+79
+(Pdb) random.randint(0, 1)
+0
+(Pdb) random.randint(1, 1)
+1
+
+```
+
+Once the post-mortem debugger kicks in, we can inspect all of the variables in the current frame and even run new code to help us figure out what's wrong and attempt to make a fix.
+
+## Dropping into the debugger from Python code using `pdb.set_trace`
+
+Another technique that I used early on, after starting to use `pdb`, was forcing the debugger to run at a certain line of code before an error occurred. This is a common next step after learning post-mortem debugging because it feels similar to debugging with `print` statements.
+
+For example, in the above code, if we want to stop execution before the division operation, we could add a `pdb.set_trace` call to our program here:
+```
+ import pdb; pdb.set_trace()
+ result = num / denom
+
+```
+
+And then run our program without `-mpdb`:
+```
+$ python3 script.py
+> ./src/script.py(10)main()
+-> result = num / denom
+(Pdb) num
+94
+(Pdb) denom
+19
+
+```
+
+The problem with this method is that you have to constantly drop these statements into your source code, remember to remove them afterwards, and switch between running your code with `python` vs. `python -mpdb`.
+
+Using `pdb.set_trace` gets the job done, but **breakpoints** are an even more flexible way to stop the debugger at any line (even third party or standard library code), without needing to modify any source code. Let's learn about breakpoints and a few other useful commands.
+
+## Debugger commands
+
+There are over 30 commands you can give to the interactive debugger, a list that can be seen by using the `help` command when at the `(Pdb)` prompt:
+```
+(Pdb) help
+
+Documented commands (type help ):
+========================================
+EOF c d h list q rv undisplay
+a cl debug help ll quit s unt
+alias clear disable ignore longlist r source until
+args commands display interact n restart step up
+b condition down j next return tbreak w
+break cont enable jump p retval u whatis
+bt continue exit l pp run unalias where
+
+```
+
+You can use `help ` for more information on a given command.
+
+Instead of walking through each command, I'll list out the ones I've found most useful and what arguments they take.
+
+**Setting breakpoints** :
+
+ * `l(ist)`: displays the source code of the currently running program, with line numbers, for the 10 lines around the current statement.
+ * `l 1,999`: displays the source code of lines 1-999. I regularly use this to see the source for the entire program. If your program only has 20 lines, it'll just show all 20 lines.
+ * `b(reakpoint)`: displays a list of current breakpoints.
+ * `b 10`: set a breakpoint at line 10. Breakpoints are referred to by a numeric ID, starting at 1.
+ * `b main`: set a breakpoint at the function named `main`. The function name must be in the current scope. You can also set breakpoints on functions in other modules in the current scope, e.g. `b random.randint`.
+ * `b script.py:10`: sets a breakpoint at line 10 in `script.py`. This gives you another way to set breakpoints in another module.
+ * `clear`: clears all breakpoints.
+ * `clear 1`: clear breakpoint 1.
+
+
+
+**Stepping through execution** :
+
+ * `c(ontinue)`: execute until the program finishes, an exception is thrown, or a breakpoint is hit.
+ * `s(tep)`: execute the next line, whatever it is (your code, stdlib, third party code, etc.). Use this when you want to step down into function calls you're interested in.
+ * `n(ext)`: execute the next line in the current function (will not step into downstream function calls). Use this when you're only interested in the current function.
+ * `r(eturn)`: execute the remaining lines in the current function until it returns. Use this to skip over the rest of the function and go up a level. For example, if you've stepped down into a function by mistake.
+ * `unt(il) [lineno]`: execute until the current line exceeds the current line number. This is useful when you've stepped into a loop but want to let the loop continue executing without having to manually step through every iteration. Without any argument, this command behaves like `next` (with the loop skipping behavior, once you've stepped through the loop body once).
+
+
+
+**Moving up and down the stack** :
+
+ * `w(here)`: shows an annotated view of the stack trace, with your current frame marked by `>`.
+ * `u(p)`: move up one frame in the current stack trace. For example, when post-mortem debugging, you'll start off on the lowest level of the stack and typically want to move `up` a few times to help figure out what went wrong.
+ * `d(own)`: move down one frame in the current stack trace.
+
+
+
+**Additional commands and tips** :
+
+ * `pp `: This will "pretty print" the result of the given expression using the [`pprint`][2] module. Example:
+
+
+```
+(Pdb) stuff = "testing the pp command in pdb with a big list of strings"
+(Pdb) pp [(i, x) for (i, x) in enumerate(stuff.split())]
+[(0, 'testing'),
+ (1, 'the'),
+ (2, 'pp'),
+ (3, 'command'),
+ (4, 'in'),
+ (5, 'pdb'),
+ (6, 'with'),
+ (7, 'a'),
+ (8, 'big'),
+ (9, 'list'),
+ (10, 'of'),
+ (11, 'strings')]
+
+```
+
+ * `!`: sometimes the Python code you run in the debugger will be confused for a command. For example `c = 1` will trigger the `continue` command. To force the debugger to execute Python code, prefix the line with `!`, e.g. `!c = 1`.
+
+ * Pressing the Enter key at the `(Pdb)` prompt will execute the previous command again. This is most useful after the `s`/`n`/`r`/`unt` commands to quickly step through execution line-by-line.
+
+ * You can run multiple commands on one line by separating them with `;;`, e.g. `b 8 ;; c`.
+
+ * The `pdb` module can take multiple `-c` arguments on the command line to execute commands as soon as the debugger starts.
+
+
+
+
+Example:
+```
+python3 -mpdb -cc script.py # run the program without you having to enter an initial "c" at the prompt
+python3 -mpdb -c "b 8" -cc script.py # sets a breakpoint on line 8 and runs the program
+
+```
+
+## Restart behavior
+
+Another thing that can shave time off debugging is understanding how `pdb`'s restart behavior works. You may have noticed that after execution stops, `pdb` will give a message like, "The program finished and will be restarted," or "The script will be restarted." When I first started using `pdb`, I would always quit and re-run `python -mpdb ...` to make sure that my code changes were getting picked up, which was unnecessary in most cases.
+
+When `pdb` says it will restart the program, or when you use the `restart` command, code changes to the script you're debugging will be reloaded automatically. Breakpoints will still be set after reloading, but may need to be cleared and re-set due to line numbers shifting. Code changes to other imported modules will not be reloaded -- you will need to `quit` and re-run the `-mpdb` command to pick those up.
+
+## Watches
+
+One feature you may miss from other interactive debuggers is the ability to "watch" a variable change throughout the program's execution. `pdb` does not include a watch command by default, but you can get something similar by using `commands`, which lets you run arbitrary Python code whenever a breakpoint is hit.
+
+To watch what happens to the `denom` variable in our example program:
+```
+$ python3 -mpdb script.py
+> ./src/script.py(1)()
+-> import random
+(Pdb) b 9
+Breakpoint 1 at ./src/script.py:9
+(Pdb) commands
+(com) silent
+(com) print("DENOM: {}".format(denom))
+(com) c
+(Pdb) c
+DENOM: 77
+71 divided by 77 is 0.92
+DENOM: 27
+100 divided by 27 is 3.70
+DENOM: 10
+82 divided by 10 is 8.20
+DENOM: 20
+...
+
+```
+
+We first set a breakpoint (which is assigned ID 1), then use `commands` to start entering a block of commands. These commands function as if you had typed them at the `(Pdb)` prompt. They can be either Python code or additional `pdb` commands.
+
+Once we start the `commands` block, the prompt changes to `(com)`. The `silent` command means the following commands will not be echoed back to the screen every time they're executed, which makes reading the output a little easier.
+
+After that, we run a `print` statement to inspect the variable, similar to what we might do when `print` debugging. Finally, we end with a `c` to continue execution, which ends the command block. Typing `c` again at the `(Pdb)` prompt starts execution and we see our new `print` statement running.
+
+If you'd rather stop execution instead of continuing, you can use `end` instead of `c` in the command block.
+
+## Running pdb from the interpreter
+
+Another way to run `pdb` is via the interpreter, which is useful when you're experimenting interactively and would like to drop into `pdb` without running a standalone script.
+
+For post-mortem debugging, all you need is a call to `pdb.pm()` after an exception has occurred:
+```
+$ python3
+>>> import script
+>>> script.main()
+17 divided by 60 is 0.28
+...
+56 divided by 94 is 0.60
+Traceback (most recent call last):
+ File "", line 1, in
+ File "./src/script.py", line 9, in main
+ result = num / denom
+ZeroDivisionError: division by zero
+>>> import pdb
+>>> pdb.pm()
+> ./src/script.py(9)main()
+-> result = num / denom
+(Pdb) num
+4
+(Pdb) denom
+0
+
+```
+
+If you want to step through normal execution instead, use the `pdb.run()` function:
+```
+$ python3
+>>> import script
+>>> import pdb
+>>> pdb.run("script.main()")
+> (1)()
+(Pdb) b script:6
+Breakpoint 1 at ./src/script.py:6
+(Pdb) c
+> ./src/script.py(6)main()
+-> for i in range(num_loops):
+(Pdb) n
+> ./src/script.py(7)main()
+-> num = random.randint(0, MAX)
+(Pdb) n
+> ./src/script.py(8)main()
+-> denom = random.randint(0, MAX)
+(Pdb) n
+> ./src/script.py(9)main()
+-> result = num / denom
+(Pdb) n
+> ./src/script.py(10)main()
+-> print("{} divided by {} is {:.2f}".format(num, denom, result))
+(Pdb) n
+66 divided by 70 is 0.94
+> ./src/script.py(6)main()
+-> for i in range(num_loops):
+
+```
+
+This one is a little trickier than `-mpdb` because you don't have the ability to step through an entire program. Instead, you'll need to manually set a breakpoint, e.g. on the first statement of the function you're trying to execute.
+
+## Conclusion
+
+Hopefully these tips have given you a few new ideas on how to use `pdb` more effectively. After getting a handle on these, you should be able to pick up the [other commands][3] and start customizing `pdb` via a `.pdbrc` file ([example][4]).
+
+You can also look into other front-ends for debugging, like [pdbpp][5], [pudb][6], and [ipdb][7], or GUI debuggers like the one included in PyCharm. Happy debugging!
+
+--------------------------------------------------------------------------------
+
+via: https://www.codementor.io/stevek/advanced-python-debugging-with-pdb-g56gvmpfa
+
+作者:[Steven Kryskalla][a]
+译者:[lujun9972](https://github.com/lujun9972)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.codementor.io/stevek
+[1]:https://docs.python.org/3/library/pdb.html
+[2]:https://docs.python.org/3/library/pprint.html
+[3]:https://docs.python.org/3/library/pdb.html#debugger-commands
+[4]:https://nedbatchelder.com/blog/200704/my_pdbrc.html
+[5]:https://pypi.python.org/pypi/pdbpp/
+[6]:https://pypi.python.org/pypi/pudb/
+[7]:https://pypi.python.org/pypi/ipdb
diff --git a/sources/tech/20180129 CopperheadOS Security features installing apps and more.md b/sources/tech/20180129 CopperheadOS Security features installing apps and more.md
new file mode 100644
index 0000000000..fd6e110d35
--- /dev/null
+++ b/sources/tech/20180129 CopperheadOS Security features installing apps and more.md
@@ -0,0 +1,245 @@
+CopperheadOS: Security features, installing apps, and more
+============================================================
+
+### Fly your open source flag proudly with Copperhead, a mobile OS that takes its FOSS commitment seriously.
+
+
+
+Image by : Norebbo via [Flickr][15] (Original: [public domain][16]). Modified by Opensource.com. [CC BY-SA 4.0][17].
+
+ _Editor's note: CopperheadOS is [licensed][11] under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 license (userspace) and GPL2 license (kernel). It is also based on Android Open Source Project (AOSP)._
+
+Several years ago, I made the decision to replace proprietary technologies (mainly Apple products) with technology that ran on free and open source software (FOSS). I can't say it was easy, but I now happily use FOSS for pretty much everything.
+
+The hardest part involved my mobile handset. There are basically only two choices today for phones and tablets: Apple's iOS or Google's Android. Since Android is open source, it seemed the obvious choice, but I was frustrated by both the lack of open source applications on Android and the pervasiveness of Google on those devices.
+
+So I entered the world of custom ROMs. These are projects that take the base [Android Open Source Project][18] (AOSP) and customize it. Almost all these projects allow you to install the standard Google applications as a separate package, called GApps, and you can have as much or as little Google presence on your phone as you like. GApps packages come in a number of flavors, from the full suite of apps that Google ships with its devices to a "pico" version that includes just the minimal amount of software needed to run the Google Play Store, and from there you can add what you like.
+
+I started out using CyanogenMod, but when that project went in a direction I didn't like, I switched to OmniROM. I was quite happy with it, but still wondered what information I was sending to Google behind the scenes.
+
+Then I found out about [CopperheadOS][19]. Copperhead is a version of AOSP that focuses on delivering the most secure Android experience possible. I've been using it for a year now and have been quite happy with it.
+
+Unlike other custom ROMs that strive to add lots of new functionality, Copperhead runs a pretty vanilla version of AOSP. Also, while the first thing you usually do when playing with a custom ROM is to add root access to the device, not only does Copperhead prevent that, it also requires that you have a device that has verified boot, so there's no unlocking the bootloader. This is to prevent malicious code from getting access to the handset.
+
+Copperhead starts with a hardened version of the AOSP baseline, including full encryption, and then adds a [ton of stuff][20] I can only pretend to understand. It also applies a number of kernel and Android patches before they are applied to the mainline Android releases.
+
+### [copperos_extrapatches.png][1]
+
+
+
+It has a couple of more obvious features that I like. If you use a PIN to unlock your device, there is an option to scramble the digits.
+
+### [copperos_scrambleddigits.png][2]
+
+
+
+This should prevent any casual shoulder-surfer from figuring out your PIN, although it can make it a bit more difficult to unlock your device while, say, driving (but no one should be using their handset in the car, right?).
+
+Another issue it addresses involves tracking people by monitoring their WiFi MAC address. Most devices that use WiFi perform active scanning for wireless access points. This protocol includes the MAC address of the interface, and there are a number of ways people can use [mobile location analytics][21] to track your movement. Copperhead has an option to randomize your MAC address, which counters this process.
+
+### [copperos_randommac.png][3]
+
+
+
+### Installing apps
+
+This all sounds pretty good, right? Well, here comes the hard part. While Android is open source, much of the Google code, including the [Google Play Store][22], is not. If you install the Play Store and the code necessary for it to work, you allow Google to install software without your permission. [Google Play's terms of service][23] says:
+
+> "Google may update any Google app or any app you have downloaded from Google Play to a new version of such app, irrespective of any update settings that you may have selected within the Google Play app or your Device, if Google determines that the update will fix a critical security vulnerability related to the app."
+
+This is not acceptable from a security standpoint, so you cannot install Google applications on a Copperhead device.
+
+This took some getting used to, as I had come to rely on things such as Google Maps. The default application repository that ships with Copperhead is [F-Droid][24], which contains only FOSS applications. While I previously used many FOSS applications on Android, it took some effort to use _nothing but_ free software. I did find some ways to cheat this system, and I'll cover that below. First, here are some of the applications I've grown to love from F-Droid.
+
+### F-Droid favorites
+
+**K-9 Mail**
+
+### [copperheados_k9mail.png][4]
+
+
+
+Even before I started using Copperhead, I loved [K-9 Mail][25]. This is simply the best mobile email client I've found, period, and it is one of the first things I install on any new device. I even use it to access my Gmail account, via IMAP and SMTP.
+
+**Open Camera**
+
+### [copperheados_cameraapi.png][5]
+
+
+
+Copperhead runs only on rather new hardware, and I was consistently disappointed in the quality of the pictures from its default camera application. Then I discovered [Open Camera][26]. A full-featured camera app, it allows you to enable an advanced API to take advantage of the camera hardware. The only thing I miss is the ability to take a panoramic photo.
+
+**Amaze**
+
+### [copperheados_amaze.png][6]
+
+
+
+[Amaze][27] is one of the best file managers I've ever used, free or not. When I need to navigate the filesystem, Amaze is my go-to app.
+
+**Vanilla Music**
+
+### [copperheados_vanillamusic.png][7]
+
+
+
+I was unhappy with the default music player, so I checked out a number of them on F-Droid and settled on [Vanilla Music][28]. It has an easy-to-use interface and interacts well with my Bluetooth devices.
+
+**OCReader**
+
+### [coperheados_ocreader.png][8]
+
+
+
+I am a big fan of [Nextcloud][29], particularly [Nextcloud News][30], a replacement for the now-defunct [Google Reader][31]. While I can access my news feeds through a web browser, I really missed the ability to manage them through a dedicated app. Enter [OCReader][32]. While it stands for "ownCloud Reader," it works with Nextcloud, and I've had very few issues with it.
+
+**Noise**
+
+The SMS/MMS application of choice for most privacy advocates is [Signal][33] by [Open Whisper Systems][34]. Endorsed by [Edward Snowden][35], Signal allows for end-to-end encrypted messaging. If the person you are messaging is also on Signal, your messages will be sent, encrypted, over a data connection facilitated by centralized servers maintained by Open Whisper Systems. It also, until recently, relied on [Google Cloud Messaging][36] (GCM) for notifications, which requires Google Play Services.
+
+The fact that Signal requires a centralized server bothered some people, so the default application on Copperhead is a fork of Signal called [Silence][37]. This application doesn't use a centralized server but does require that all parties be on Silence for encryption to work.
+
+Well, no one I know uses Silence. At the moment you can't even get it from the Google Play Store in the U.S. due to a trademark issue, and there is no iOS client. An encrypted SMS client isn't very useful if you can't use it for encryption.
+
+Enter [Noise][38]. Noise is another application maintained by Copperhead that is a fork of Signal that removes the need for GCM. While not available in the standard F-Droid repositories, Copperhead includes their own repository in the version of F-Droid they ship, which at the moment contains only the Noise application. This app will let you communicate securely with anyone else using Noise or Signal.
+
+### F-Droid workarounds
+
+**FFUpdater**
+
+Copperhead ships with a hardened version of the Chromium web browser, but I am a Firefox fan. Unfortunately, [Firefox is no longer included][39] in the F-Droid repository. Apps on F-Droid are all built by the F-Droid maintainers, so the process for getting into F-Droid can be complicated. The [Compass app for OpenNMS][40] isn't in F-Droid because, at the moment, it does not support builds using the [Ionic Framework][41], which Compass uses.
+
+Luckily, there is a simple workaround: Install the [FFUpdater][42] app on F-Droid. This allows me to install Firefox and keep it up to date through the browser itself.
+
+**Amazon Appstore**
+
+This brings me to a cool feature of Android 8, Oreo. In previous versions of Android, you had a single "known source" for software, usually the Google Play Store, and if you wanted to install software from another repository, you had to go to settings and allow "Install from Unknown Sources." I always had to remember to turn that off after an install to prevent malicious code from being able to install software on my device.
+
+### [copperheados_sources.png][9]
+
+
+
+With Oreo, you can permanently allow a specified application to install applications. For example, I use some applications from the [Amazon Appstore][43] (such as the Amazon Shopping and Kindle apps). When I download and install the Amazon Appstore Android package (APK), I am prompted to allow the application to install apps and then I'm not asked again. Of course, this can be turned on and off on a per-application basis.
+
+The Amazon Appstore has a number of useful apps, such as [IMDB][44] and [eBay][45]. Many of them don't require Google Services, but some do. For example, if I install the [Skype][46] app via Amazon, it starts up, but then complains about the operating system. The American Airlines app would start, then complain about an expired certificate. (I contacted them and was told they were no longer maintaining the version in the Amazon Appstore and it would be removed.) In any case, I can pretty simply install a couple of applications I like without using Google Play.
+
+**Google Play**
+
+Well, what about those apps you love that don't use Google Play Services but are only available through the Google Play Store? There is yet another way to safely get those apps on your Copperhead device.
+
+This does require some technical expertise and another device. On the second device, install the [TWRP][47] recovery application. This is usually a key first step in installing any custom ROM, and TWRP is supported on a large number of devices. You will also need the Android Debug Bridge ([ADB][48]) application from the [Android SDK][49], which can be downloaded at no cost.
+
+On the second device, use the Google Play Store to install the applications you want. Then, reboot into recovery. You can mount the system partition via TWRP; plug the device into a computer via a USB cable and you should be able to see it via ADB. There is a system directory called `/data/app`, and in it you will find all the APK files for your applications. Copy those you want to your computer (I use the ADB `pull`command and copy over the whole directory).
+
+Disconnect that phone and connect your Copperhead device. Enable the "Transfer files" option, and you should see the storage directory mounted on your computer. Copy over the APK files for the applications you want, then install them via the Amaze file manager (just navigate to the APK file and click on it).
+
+Note that you can do this for any application, and it might even be possible to install Google Play Services this way on Copperhead, but that kind of defeats the purpose. I use this mainly to get the [Electric Sheep][50] screensaver and a guitar tuning app I like called [Cleartune][51]. Be aware that if you install TWRP, especially on a Google Pixel, security updates may not work, as they'll expect the stock recovery. In this case you can always use [fastboot][52] to access TWRP, but leave the default recovery in place.
+
+### Must-have apps without a workaround
+
+Unfortunately, there are still a couple of Google apps I find it hard to live without. Google Maps is probably the main Google application I use, and yes, while I know I'm giving up my location to Google, it has saved hours of my life by routing me around traffic issues. [OpenStreetMap][53] has an app available via F-Droid, but it doesn't have the real-time information that makes Google Maps so useful. I also use Skype on occasion, usually when I am out of the country and have only a data connection (i.e., through a hotel WiFi network). It lets me call home and other places at a very affordable price.
+
+My workaround is to carry two phones. I know this isn't an option for most people, but it is the only one I've found for now. I use my Copperhead phone for anything personal (email, contacts, calendars, pictures, etc.) and my "Googlephone" for Maps, Skype, and various games.
+
+My dream would be for someone to perfect a hypervisor on a handset. Then I could run Copperhead and stock Google Android on the same device. I don't think anyone has a strong business reason to do it, but I do hope it happens.
+
+### Devices that support Copperhead
+
+Before you rush out to install Copperhead, there are some hurdles you'll have to jump. First, it is supported on only a [limited number of handsets][54], almost all of them late-model Google devices. The logic behind this is simple: Google tends to release Android security updates for its devices quickly, and I've found that Copperhead is able to follow suit within a day, if not within hours. Second, like any open source project, it has limited resources and it is difficult to support even a fraction of the devices now available to end users. Finally, if you want to run Copperhead on handsets like the Pixel and Pixel XL, you'll either have to build from source or [buy a device][55] from Copperhead directly.
+
+When I discovered Copperhead, I had a Nexus 6P, which (along with the Nexus 5X) is one of the supported devices. This allowed me to play with and get used to the operating system. I liked it so much that I donated some money to the project, but I kind of balked at the price they were asking for Pixel and Pixel XL handsets.
+
+Recently, though, I ended up purchasing a Pixel XL directly from Copperhead. There were a couple of reasons. One, since all of the code is available on GitHub, I set out to do [my own build][56] for a Pixel device. That process (which I never completed) made me appreciate the amount of work Copperhead puts into its project. Two, there was an article on [Slashdot][57] discussing how people were selling devices with Copperhead pre-installed and using Copperhead's update servers. I didn't appreciate that very much. Finally, I support FOSS not only by being a vocal user but also with my wallet.
+
+### Putting the "libre" back into free
+
+Another thing I love about FOSS is that I have options. There is even a new option to Copperhead being developed called [Eelo][58]. Created by [Gaël Duval][59], the developer of Mandrake Linux, this is a privacy-based Android operating system based on [LineageOS][60] (the descendant of CyanogenMod). While it should be supported on more handsets than Copperhead is, it is still in the development stage, and Copperhead is very stable and mature. I am eager to check it out, though.
+
+For the year I've used CopperheadOS, I've never felt safer when using a mobile device to connect to a network. I've found the open source replacements for my old apps to be more than adequate, if not better than the original apps. I've also rediscovered the browser. Where I used to have around three to four tabs open, I now have around 10, because I've found that I usually don't need to install an app to easily access a site's content.
+
+With companies like Google and Apple trying more and more to insinuate themselves into the lives of their users, it is nice to have an option that puts the "libre" back into free.
+
+
+### About the author
+
+ [][61]
+
+Tarus Balog - Having been kicked out of some of the best colleges and universities in the country, I managed after seven years to get a BSEE and entered the telecommunications industry. I always ended up working on projects where we were trying to get the phone switch to talk to PCs. This got me interested in the creation and management of large communication networks. So I moved into the data communications field (they were separate back then) and started working with commercial network management tools... [more about Tarus Balog][12][More about me][13]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/copperheados-delivers-mobile-freedom-privacy-and-security
+
+作者:[Tarus Balog ][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/sortova
+[1]:https://opensource.com/file/384496
+[2]:https://opensource.com/file/384501
+[3]:https://opensource.com/file/384506
+[4]:https://opensource.com/file/384491
+[5]:https://opensource.com/file/384486
+[6]:https://opensource.com/file/384481
+[7]:https://opensource.com/file/384476
+[8]:https://opensource.com/file/384471
+[9]:https://opensource.com/file/384466
+[10]:https://opensource.com/article/18/1/copperheados-delivers-mobile-freedom-privacy-and-security?rate=P32BmRpJF5bYEYTHo4mW3Hp4XRk34Eq3QqMDf2oOGnw
+[11]:https://copperhead.co/android/docs/building#redistribution
+[12]:https://opensource.com/users/sortova
+[13]:https://opensource.com/users/sortova
+[14]:https://opensource.com/user/11447/feed
+[15]:https://www.flickr.com/photos/mstable/17517955832
+[16]:https://creativecommons.org/publicdomain/mark/1.0/
+[17]:https://creativecommons.org/licenses/by-sa/4.0/
+[18]:https://en.wikipedia.org/wiki/Android_(operating_system)#AOSP
+[19]:https://copperhead.co/
+[20]:https://copperhead.co/android/docs/technical_overview
+[21]:https://en.wikipedia.org/wiki/Mobile_location_analytics
+[22]:https://en.wikipedia.org/wiki/Google_Play#Compatibility
+[23]:https://play.google.com/intl/en-us_us/about/play-terms.html
+[24]:https://en.wikipedia.org/wiki/F-Droid
+[25]:https://f-droid.org/en/packages/com.fsck.k9/
+[26]:https://f-droid.org/en/packages/net.sourceforge.opencamera/
+[27]:https://f-droid.org/en/packages/com.amaze.filemanager/
+[28]:https://f-droid.org/en/packages/ch.blinkenlights.android.vanilla/
+[29]:https://nextcloud.com/
+[30]:https://github.com/nextcloud/news
+[31]:https://en.wikipedia.org/wiki/Google_Reader
+[32]:https://f-droid.org/packages/email.schaal.ocreader/
+[33]:https://en.wikipedia.org/wiki/Signal_(software)
+[34]:https://en.wikipedia.org/wiki/Open_Whisper_Systems
+[35]:https://en.wikipedia.org/wiki/Edward_Snowden
+[36]:https://en.wikipedia.org/wiki/Google_Cloud_Messaging
+[37]:https://f-droid.org/en/packages/org.smssecure.smssecure/
+[38]:https://github.com/copperhead/Noise
+[39]:https://f-droid.org/wiki/page/org.mozilla.firefox
+[40]:https://compass.opennms.io/
+[41]:https://ionicframework.com/
+[42]:https://f-droid.org/en/packages/de.marmaro.krt.ffupdater/
+[43]:https://www.amazon.com/gp/feature.html?docId=1000626391
+[44]:https://www.imdb.com/
+[45]:https://www.ebay.com/
+[46]:https://www.skype.com/
+[47]:https://twrp.me/
+[48]:https://en.wikipedia.org/wiki/Android_software_development#ADB
+[49]:https://developer.android.com/studio/index.html
+[50]:https://play.google.com/store/apps/details?id=com.spotworks.electricsheep&hl=en
+[51]:https://play.google.com/store/apps/details?id=com.bitcount.cleartune&hl=en
+[52]:https://en.wikipedia.org/wiki/Android_software_development#Fastboot
+[53]:https://f-droid.org/packages/net.osmand.plus/
+[54]:https://copperhead.co/android/downloads
+[55]:https://copperhead.co/android/store
+[56]:https://copperhead.co/android/docs/building
+[57]:https://news.slashdot.org/story/17/11/12/024231/copperheados-fights-unlicensed-installations-on-nexus-phones
+[58]:https://eelo.io/
+[59]:https://en.wikipedia.org/wiki/Ga%C3%ABl_Duval
+[60]:https://en.wikipedia.org/wiki/LineageOS
+[61]:https://opensource.com/users/sortova
+[62]:https://opensource.com/users/sortova
+[63]:https://opensource.com/users/sortova
+[64]:https://opensource.com/article/18/1/copperheados-delivers-mobile-freedom-privacy-and-security#comments
+[65]:https://opensource.com/tags/mobile
+[66]:https://opensource.com/tags/android
\ No newline at end of file
diff --git a/sources/tech/20180129 How To Resume Partially Transferred Files Over SSH Using Rsync.md b/sources/tech/20180129 How To Resume Partially Transferred Files Over SSH Using Rsync.md
new file mode 100644
index 0000000000..5e0583ab4f
--- /dev/null
+++ b/sources/tech/20180129 How To Resume Partially Transferred Files Over SSH Using Rsync.md
@@ -0,0 +1,101 @@
+How To Resume Partially Transferred Files Over SSH Using Rsync
+======
+
+
+
+There are chances that the large files which are being copied over SSH using SCP command might be interrupted or cancelled or broken due to various reasons such as power failure or network failure or user intervention. The other day I was copying the Ubuntu 16.04 ISO file to my remote system. Unfortunately, the power is gone, and the network connection is dropped immediately. The result? The copy process is terminated! This is just a simple example. The Ubuntu ISO is not so big, and I could restart the copy process as soon as the power is restored. But in production environment, you might not want to do it while you're transferring large files.
+
+Also, you can't always resume the aborted process using **scp** command. Because, If you do, It will simply overwrite the existing files. What would you do in such situations? No worries! This is where **Rsync** utility comes in handy! Rsync can help you to resume the interrupted copy or download process where you left it off. For those wondering, Rsync is a fast, versatile file copying utility that can be used to copy and transfer files or folders to and from remote and local systems.
+
+It offers a large number of options that control every aspect of its behavior and permit very flexible specification of the set of files to be copied. It is famous for its delta-transfer algorithm, which reduces the amount of data sent over the network by sending only the differences between the source files and the existing files in the destination. Rsync is widely used for backups and mirroring and as an improved copy command for everyday use.
+
+Just like SCP, rsync will also copy files over SSH. In case you wanted to download or transfer a big files and folders over SSH, I recommend you to use rsync utility. Be mindful that the **rsync utility should be installed on both sides** (remote and local systems) in order to resume partially transferred files.
+
+### Resume Partially Transferred Files Using Rsync
+
+Well, let me show you an example. I am going to copy Ubuntu 16.04 ISO from my local system to remote system with command:
+
+```
+$ scp Soft_Backup/OS\ Images/Linux/ubuntu-16.04-desktop-amd64.iso sk@192.168.43.2:/home/sk/
+```
+
+Here,
+
+ * **sk** is my remote system 's username
+ * **192.168.43.2** is the IP address of the remote machine.
+
+
+
+Now, I terminated it by pressing **CTRL+c**.
+
+**Sample output:**
+
+```
+sk@192.168.43.2's password:
+ubuntu-16.04-desktop-amd64.iso 26% 372MB 26.2MB/s 00:39 ETA^c
+```
+
+[![][1]][2]
+
+As you see in the above output, I terminated the copy process when it reached 26%.
+
+If I re-run the above command, it will simply overwrite the existing file. In other words, the copy process will not resume where I left it off.
+
+In order to resume the copy process, we can use **rsync** command as shown below.
+
+```
+$ rsync -P -rsh=ssh Soft_Backup/OS\ Images/Linux/ubuntu-16.04-desktop-amd64.iso sk@192.168.43.2:/home/sk/
+```
+
+**Sample output:**
+```
+sk@192.168.1.103's password:
+sending incremental file list
+ubuntu-16.04-desktop-amd64.iso
+ 380.56M 26% 41.05MB/s 0:00:25
+```
+
+[![][1]][4]
+
+See? Now, the copying process is resumed where we left it off earlier. You also can use "-partial" instead of parameter "-P" like below.
+```
+$ rsync --partial -rsh=ssh Soft_Backup/OS\ Images/Linux/ubuntu-16.04-desktop-amd64.iso sk@192.168.43.2:/home/sk/
+```
+
+Here, the parameter "-partial" or "-P" tells the rsync command to keep the partial downloaded file and resumes the process.
+
+Alternatively, we can use the following commands as well to resume partially transferred files over SSH.
+
+```
+$ rsync -avP Soft_Backup/OS\ Images/Linux/ubuntu-16.04-desktop-amd64.iso sk@192.168.43.2:/home/sk/
+```
+
+Or,
+
+```
+rsync -av --partial Soft_Backup/OS\ Images/Linux/ubuntu-16.04-desktop-amd64.iso sk@192.168.43.2:/home/sk/
+```
+
+That's it. You know now how to resume the cancelled, interrupted, and partially downloaded files using rsync command. As you can see, it is not so difficult either. If rsync is installed on both systems, we can easily resume the copy process as described above.
+
+If you find this tutorial helpful, please share it on your social, professional networks and support OSTechNix. More good stuffs to come. Stay tuned!
+
+Cheers!
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.ostechnix.com/how-to-resume-partially-downloaded-or-transferred-files-using-rsync/
+
+作者:[SK][a]
+译者:[译者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/02/scp.png ()
+[3]:/cdn-cgi/l/email-protection
+[4]:http://www.ostechnix.com/wp-content/uploads/2016/02/rsync.png ()
diff --git a/sources/tech/20180129 How programmers learn to code.md b/sources/tech/20180129 How programmers learn to code.md
new file mode 100644
index 0000000000..c741c01161
--- /dev/null
+++ b/sources/tech/20180129 How programmers learn to code.md
@@ -0,0 +1,63 @@
+How programmers learn to code
+============================================================
+
+ [][8]
+
+
+HackerRank recently published the results of its 2018 Developer Skills Report, in which it asked programmers when they started coding.
+
+39,441 professional and student developers completed the online survey from 16 October to 1 November 2016, with over 25% of the developers surveyed writing their first piece of code before they were 16 years old.
+
+### How programmers learn
+
+In terms of how programmers learnt to code, self-teaching is the norm for developers of all ages, stated the report.
+
+“Even though 67% of developers have computer science degrees, roughly 74% said they were at least partially self-taught.”
+
+On average, developers know four languages, but they want to learn four more.
+
+The thirst for learning varies by generations – developers between 18 and 24 plan to learn six languages, whereas developers older than 35 only plan to learn three.
+
+ [][5]
+
+### What programmers want
+
+HackerRank also looked at what developers want most from an employer.
+
+On average, a good work-life balance, closely followed by professional growth and learning, was the most desired requirement.
+
+Segmenting the data by region revealed that Americans crave work-life balance more than developers Asia and Europe.
+
+Students tend to rank growth and learning over work-life balance, while professionals rate compensation more highly than students do.
+
+People who work in smaller companies tended to rank work-life balance lower, but it was still in their top three.
+
+Age also made a difference, with developers 25 and older rating work-life balance as most important, while those between 18 and 24 rate it as less important.
+
+“In some ways, we’ve discovered a slight contradiction here. Developers want work-life balance, but they also have an insatiable thirst and need for learning,” said HackerRank.
+
+It advised that focusing on doing what you enjoy, as opposed to trying to learning everything, can help strike a better work-life balance.
+
+ [][6]
+
+ [][7]
+
+--------------------------------------------------------------------------------
+
+via: https://mybroadband.co.za/news/smartphones/246583-how-programmers-learn-to-code.html
+
+作者:[Staff Writer ][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://mybroadband.co.za/news/author/staff-writer
+[1]:https://mybroadband.co.za/news/author/staff-writer
+[2]:https://twitter.com/intent/tweet/?text=How+programmers+learn+to+code%20https://mybroadband.co.za/news/smartphones/246583-how-programmers-learn-to-code.html&via=mybroadband
+[3]:mailto:?subject=How%20programmers%20learn%20to%20code&body=HackerRank%20recently%20published%20the%20results%20of%20its%202018%20Developer%20Skills%20Report.%0A%0Ahttps%3A%2F%2Fmybroadband.co.za%2Fnews%2Fsmartphones%2F246583-how-programmers-learn-to-code.html
+[4]:https://mybroadband.co.za/news/smartphones/246583-how-programmers-learn-to-code.html#disqus_thread
+[5]:https://mybroadband.co.za/news/wp-content/uploads/2018/01/HackerRank-2018-how-did-you-learn-to-code.jpg
+[6]:https://mybroadband.co.za/news/wp-content/uploads/2018/01/HackerRank-2018-what-do-developers-want-most.jpg
+[7]:https://mybroadband.co.za/news/wp-content/uploads/2018/01/HackerRank-2018-how-to-improve-work-life-balance.jpg
+[8]:https://mybroadband.co.za/news/smartphones/246583-how-programmers-learn-to-code.html
\ No newline at end of file
diff --git a/sources/tech/20180129 How to Use DockerHub.md b/sources/tech/20180129 How to Use DockerHub.md
new file mode 100644
index 0000000000..3793a6b718
--- /dev/null
+++ b/sources/tech/20180129 How to Use DockerHub.md
@@ -0,0 +1,135 @@
+How to Use DockerHub
+======
+
+
+
+In the previous articles, we learned the basics of [Docker terminology][1], [how to install Docker][2] on desktop Linux, macOS, and Windows, and [how to create container images][3] and run them on your system. In this last article in the series, we will talk about using images from DockerHub and publishing your own images to DockerHub.
+
+First things first: what is DockerHub and why is it important? DockerHub is a cloud-based repository run and managed by Docker Inc. It's an online repository where Docker images can be published and used by other users. There are both public and private repositories. If you are a company, you can have a private repository for use within your own organization, whereas public images can be used by anyone.
+
+You can also use official Docker images that are published publicly. I use many such images, including for my test WordPress installations, KDE plasma apps, and more. Although we learned last time how to create your own Docker images, you don't have to. There are thousands of images published on DockerHub for you to use. DockerHub is hardcoded into Docker as the default registry, so when you run the docker pull command against any image, it will be downloaded from DockerHub.
+
+### Download images from Docker Hub and run locally
+
+Please check out the previous articles in the series to get started. Then, once you have Docker running on your system, you can open the terminal and run:
+```
+$ docker images
+```
+
+This command will show all the docker images currently on your system. Let's say you want to deploy Ubuntu on your local machine; you would do:
+```
+$ docker pull ubuntu
+```
+
+If you already have Ubuntu image on your system, the command will automatically update that image to the latest version. So, if you want to update the existing images, just run the docker pull command, easy peasy. It's like apt-get upgrade without any muss and fuss.
+
+You already know how to run an image:
+```
+$ docker run -it
+
+$ docker run -it ubuntu
+```
+
+The command prompt should change to something like this:
+```
+root@1b3ec4621737:/#
+```
+
+Now you can run any command and utility that you use on Ubuntu. It's all safe and contained. You can run all the experiments and tests you want on that Ubuntu. Once you are done testing, you can nuke the image and download a new one. There is no system overhead that you would get with a virtual machine.
+
+You can exit that container by running the exit command:
+```
+$ exit
+```
+
+Now let's say you want to install Nginx on your system. Run search to find the desired image:
+```
+$ docker search nginx
+
+aizMFFysICAEsgDDYrsrlqwoCgGbWVHtcOzgV9mA
+```
+
+As you can see, there are many images of Nginx on DockerHub. Why? Because anyone can publish an image. Various images are optimized for different projects, so you can choose the appropriate image. You just need to install the appropriate image for your use-case.
+
+Let's say you want to pull Bitnami's Nginx container:
+```
+$ docker pull bitnami/nginx
+```
+
+Now run it with:
+```
+$ docker run -it bitnami/nginx
+```
+
+### How to publish images to Docker Hub?
+
+Previously, [we learned how to create a Docker image][3], and we can easily publish that image to DockerHub. First, you need to log into DockerHub. If you don't already have an account, please [create one][5]. Then, you can open terminal app and log in:
+```
+$ docker login --username=
+```
+
+Replace with the name of your username for Docker Hub. In my case it's arnieswap:
+```
+$ docker login --username=arnieswap>
+```
+
+Enter the password, and you are logged in. Now run the docker images command to get the ID of the image that you created last time.
+```
+$ docker images
+
+tW1jDOugkX7J2FfyFyToM6B8m5OYFwMba-Ag5aez
+```
+
+Now, suppose you want to push the ng image to DockerHub. First, we need to tag that image ([learn more about tags][1]):
+```
+$ docker tag e7083fd898c7 arnieswap/my_repo:testing
+```
+
+Now push that image:
+```
+$ docker push arnieswap/my_repo
+```
+
+The push refers to repository [docker.io/arnieswap/my_repo]
+```
+12628b20827e: Pushed
+
+8600ee70176b: Mounted from library/ubuntu
+
+2bbb3cec611d: Mounted from library/ubuntu
+
+d2bb1fc88136: Mounted from library/ubuntu
+
+a6a01ad8b53f: Mounted from library/ubuntu
+
+833649a3e04c: Mounted from library/ubuntu
+
+testing: digest: sha256:286cb866f34a2aa85c9fd810ac2cedd87699c02731db1b8ca1cfad16ef17c146 size: 1569
+
+```
+
+Eureka! Your image is being uploaded. Once finished, open DockerHub, log into your account, and you can see your very first Docker image. Now anyone can deploy your image. It's the easiest and fastest way to develop and distribute software. Whenever you update the image, users can simply run:
+```
+$ docker run arnieswap/my_repo
+```
+
+Now you know why people love Docker containers. They solve many problems that traditional workloads face and allow you develop, test, and deploy applications in no time. And, by following the steps in this series, you can try them out for yourself.
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/learn/intro-to-linux/2018/1/how-use-dockerhub
+
+作者:[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/blog/intro-to-linux/2017/12/container-basics-terms-you-need-know
+[2]:https://www.linux.com/blog/learn/intro-to-linux/how-install-docker-ce-your-desktop
+[3]:https://www.linux.com/blog/learn/intro-to-linux/2018/1/how-create-docker-image
+[4]:https://lh3.googleusercontent.com/aizMFFysICAEsgDDYrsrlqwoCgGbWVHtcOzgV9mAtV8IdBZgHPJTdHIZhWBNCRvOyJb108ZBajJ_Nz10yCxGSvk-AF-yvFxpojLdVu3Jjihcwaup6CQLc67A5nglBuGDaOZWcrbV
+[5]:https://hub.docker.com/
+[6]:https://lh6.googleusercontent.com/tW1jDOugkX7J2FfyFyToM6B8m5OYFwMba-Ag5aezVGf2A5gsKJ47QrCh_TOKWgIKfE824Uc2Cwwwj9jWps1yJlUZqDyIceVQs-nEbKavFDxuUxLyd4thBA4_rsXrQH4r7hrG8FnD
diff --git a/sources/tech/20180129 How to make your LXD containers get IP addresses from your LAN using a bridge.md b/sources/tech/20180129 How to make your LXD containers get IP addresses from your LAN using a bridge.md
new file mode 100644
index 0000000000..6f26f182b8
--- /dev/null
+++ b/sources/tech/20180129 How to make your LXD containers get IP addresses from your LAN using a bridge.md
@@ -0,0 +1,173 @@
+How to make your LXD containers get IP addresses from your LAN using a bridge
+======
+**Background** : LXD is a hypervisor that manages machine containers on Linux distributions. You install LXD on your Linux distribution and then you can launch machine containers into your distribution running all sort of (other) Linux distributions.
+
+In the previous post, we saw how to get our LXD container to receive an IP address from the local network (instead of getting the default private IP address), using **macvlan**.
+
+In this post, we are going to see how to use a **bridge** to make our containers get an IP address from the local network. Specifically, we are going to see how to do this using NetworkManager. If you have several public IP addresses, you can use this method (or the other with the **macvlan** ) in order to expose your LXD containers directly to the Internet.
+
+### Creating the bridge with NetworkManager
+
+See this post [How to configure a Linux bridge with Network Manager on Ubuntu][1] on how to create the bridge with NetworkManager. It explains that you
+
+ 1. Use **NetworkManager** to **Add a New Connection** , a **Bridge**.
+ 2. When configuring the **Bridge** , you specify the real network connection (the device, like **eth0** or **enp3s12** ) that will be **the slave of the bridge**. You can verify the device of the network connection if you run **ip route list 0.0.0.0/0**.
+ 3. Then, you can remove the old network connection and just keep the slave. The slave device ( **bridge0** ) will now be the device that gets you your LAN IP address.
+
+
+
+At this point you would have again network connectivity. Here is the new device, **bridge0**.
+```
+$ ifconfig bridge0
+bridge0 Link encap:Ethernet HWaddr 00:e0:4b:e0:a8:c2
+ inet addr:192.168.1.64 Bcast:192.168.1.255 Mask:255.255.255.0
+ inet6 addr: fe80::d3ca:7a11:f34:fc76/64 Scope:Link
+ UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
+ RX packets:9143 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:7711 errors:0 dropped:0 overruns:0 carrier:0
+ collisions:0 txqueuelen:1000
+ RX bytes:7982653 (7.9 MB) TX bytes:1056263 (1.0 MB)
+```
+
+### Creating a new profile in LXD for bridge networking
+
+In LXD, there is a default profile and then you can create additional profile that either are independent from the default (like in the **macvlan** post), or can be chained with the default profile. Now we see the latter.
+
+First, create a new and empty LXD profile, called **bridgeprofile**.
+```
+$ lxc create profile bridgeprofile
+```
+
+Here is the fragment to add to the new profile. The **eth0** is the interface name in the container, so for the Ubuntu containers it does not change. Then, **bridge0** is the interface that was created by NetworkManager. If you created that bridge by some other way, add here the appropriate interface name. The **EOF** at the end is just a marker when we copy and past to the profile.
+```
+description: Bridged networking LXD profile
+devices:
+ eth0:
+ name: eth0
+ nictype: bridged
+ parent: bridge0
+ type: nic
+**EOF**
+```
+
+Paste the fragment to the new profile.
+```
+$ cat <:] [:][] [--ephemeral|-e] [--profile|-p ...] [--config|-c ...] [--type|-t ]
+
+Create and start containers from images.
+
+Not specifying -p will result in the default profile.
+Specifying "-p" with no argument will result in no profile.
+
+Examples:
+ lxc launch ubuntu:16.04 u1
+
+Options:
+ -c, --config (= map[]) Config key/value to apply to the new container
+ --debug (= false) Enable debug mode
+ -e, --ephemeral (= false) Ephemeral container
+ --force-local (= false) Force using the local unix socket
+ --no-alias (= false) Ignore aliases when determining what command to run
+ -p, --profile (= []) Profile to apply to the new container
+**-t (= "") Instance type**
+ --verbose (= false) Enable verbose mode
+```
+
+What do we put for Instance type? Here is the documentation,
+
+
+
+Simply put, an instance type is just a mnemonic shortcut for specific pair of CPU cores and RAM memory settings. For CPU you specify the number of cores and for RAM memory the amount in GB (assuming your own computer has enough cores and RAM so that LXD can allocate them to the newly created container).
+
+You would need an instance type if you want to create a machine container that resembles in the specs as close as possible what you will be installing later on, on AWS (Amazon), Azure (Microsoft) or GCE (Google).
+
+The instance type can have any of the following forms,
+
+ * `` for example: **t2.micro** (LXD figures out that this refers to AWS t2.micro, therefore 1 core, 1GB RAM).
+ * `:` for example, **aws:t2.micro** (LXD quickly looks into the AWS types, therefore 1core, 1GB RAM).
+ * `c-m` for example, **c1-m1** (LXD explicitly allocates one core, and 1GB RAM).
+
+
+
+Where do these mnemonics like **t2.micro** come from? The documentation says from
+
+[![][1]][2]
+
+There are three sets of instance types, **aws** , **azure** and **gce**. Their names are listed in [the LXD instance type index file ][3]**.yaml,**
+```
+aws: "aws.yaml"
+gce: "gce.yaml"
+azure: "azure.yaml"
+
+```
+
+Over there, there are YAML configuration files for each of AWS, Azure and GCE, and in them there are settings for CPU cores and RAM memory.
+
+The actual URLs that the LXD client will be using, are
+
+
+
+Sample for AWS:
+```
+t2.large:
+ cpu: 2.0
+ mem: 8.0
+t2.medium:
+ cpu: 2.0
+ mem: 4.0
+t2.micro:
+ cpu: 1.0
+ mem: 1.0
+t2.nano:
+ cpu: 1.0
+ mem: 0.5
+t2.small:
+ cpu: 1.0
+ mem: 2.0
+```
+
+
+
+Sample for Azure:
+```
+ExtraSmall:
+ cpu: 1.0
+ mem: 0.768
+Large:
+ cpu: 4.0
+ mem: 7.0
+Medium:
+ cpu: 2.0
+ mem: 3.5
+Small:
+ cpu: 1.0
+ mem: 1.75
+Standard_A1_v2:
+ cpu: 1.0
+ mem: 2.0
+```
+
+
+
+Sample for GCE:
+```
+f1-micro:
+ cpu: 0.2
+ mem: 0.6
+g1-small:
+ cpu: 0.5
+ mem: 1.7
+n1-highcpu-16:
+ cpu: 16.0
+ mem: 14.4
+n1-highcpu-2:
+ cpu: 2.0
+ mem: 1.8
+n1-highcpu-32:
+ cpu: 32.0
+ mem: 28.8
+```
+
+Let's see an example. Here, all of the following are all equivalent! Just run one of them to get a 1 CPU core/1GB RAM container.
+```
+$ lxc launch ubuntu:x -t t2.micro aws-t2-micro
+
+$ lxc launch ubuntu:x -t aws:t2.micro aws-t2-micro
+
+$ lxc launch ubuntu:x -t c1-m1 aws-t2-micro
+```
+
+Let's verify that the constraints have been actually set for the container.
+```
+$ lxc config get aws-t2-micro limits.cpu
+1
+
+$ lxc config get aws-t2-micro limits.cpu.allowance
+
+
+$ lxc config get aws-t2-micro limits.memory
+1024MB
+
+$ lxc config get aws-t2-micro limits.memory.enforce
+
+
+```
+
+There are generic limits for 1 CPU core and 1024MB/1GB RAM. For more, see [LXD resource control][4].
+
+If you already have a running container and you wanted to set limits live (no need to restart it), here is how you would do that.
+```
+$ lxc launch ubuntu:x mycontainer
+Creating mycontainer
+Starting mycontainer
+
+$ lxc config set mycontainer limits.cpu 1
+$ lxc config set mycontainer limits.memory 1GB
+```
+
+Let's see the config with the limits,
+```
+$ lxc config show mycontainer
+architecture: x86_64
+config:
+ image.architecture: amd64
+ image.description: ubuntu 16.04 LTS amd64 (release) (20180126)
+ image.label: release
+ image.os: ubuntu
+ image.release: xenial
+ image.serial: "20180126"
+ image.version: "16.04"
+ limits.cpu: "1"
+ limits.memory: 1GB
+...
+```
+
+### Troubleshooting
+
+#### I tried to the the memory limit but I get an error!
+
+I got this error,
+```
+$ lxc config set mycontainer limits.memory 1
+error: Failed to set cgroup memory.limit_in_bytes="1": setting cgroup item for the container failed
+Exit 1
+```
+
+When you set the memory limit ( **limits.memory** ), you need to append a specifier like **GB** (as in 1GB). Because the number there is in bytes if no specifier is present, and one byte of memory is not going to work.
+
+#### I cannot set the limits in lxc launch -config!
+
+How do I use **lxc launch -config ConfigurationGoesHere**?
+
+Here is the documentation:
+```
+$ lxc launch --help
+Usage: lxc launch [ :] ... [--config|-c ...]
+```
+
+Here it is,
+```
+$ lxc launch ubuntu:x --config limits.cpu=1 --config limits.memory=1GB mycontainer
+Creating mycontainer
+Starting mycontainer
+```
+
+That is, use multiple **- config** parameters.
+
+
+--------------------------------------------------------------------------------
+
+via: https://blog.simos.info/how-to-use-lxd-instance-types/
+
+作者:[Simos Xenitellis][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://blog.simos.info/author/simos/
+[1]:https://i1.wp.com/blog.simos.info/wp-content/uploads/2018/01/lxd-instance-types.png?resize=750%2C277&ssl=1
+[2]:https://i1.wp.com/blog.simos.info/wp-content/uploads/2018/01/lxd-instance-types.png?ssl=1
+[3]:https://uk.images.linuxcontainers.org/meta/instance-types/.yaml
+[4]:https://stgraber.org/2016/03/26/lxd-2-0-resource-control-412/
diff --git a/sources/tech/20180129 Install Zabbix Monitoring Server and Agent on Debian 9.md b/sources/tech/20180129 Install Zabbix Monitoring Server and Agent on Debian 9.md
new file mode 100644
index 0000000000..308b6f1341
--- /dev/null
+++ b/sources/tech/20180129 Install Zabbix Monitoring Server and Agent on Debian 9.md
@@ -0,0 +1,401 @@
+Install Zabbix Monitoring Server and Agent on Debian 9
+======
+
+Monitoring tools are used to continuously keep track of the status of the system and send out alerts and notifications if anything goes wrong. Also, monitoring tools help you to ensure that your critical systems, applications and services are always up and running. Monitoring tools are a supplement for your network security, allowing you to detect malicious traffic, where it's coming from and how to cancel it.
+
+Zabbix is a free, open source and the ultimate enterprise-level monitoring tool designed for real-time monitoring of millions of metrics collected from tens of thousands of servers, virtual machines and network devices. Zabbix has been designed to skill from small environment to large environment. Its web front-end is written in PHP, backend is written in C and uses MySQL, PostgreSQL, SQLite, Oracle or IBM DB2 to store data. Zabbix provides graphing functionality that allows you to get an overview of the current state of specific nodes and the network
+
+Some of the major features of the Zabbix are listed below:
+
+ * Monitoring Servers, Databases, Applications, Network Devices, Vmware hypervisor, Virtual Machines and much more.
+ * Special designed to support small to large environments to improve the quality of your services and reduce operating costs by avoiding downtime.
+ * Fully open source, so you don't need to pay anything.
+ * Provide user friendly web interface to do everything from a central location.
+ * Comes with SNMP to monitor Network device and IPMI to monitor Hardware device.
+ * Web-based front end that allows full system control from a browser.
+
+This tutorial will walk you through the step by step instruction of how to install Zabbix Server and Zabbix agent on Debian 9 server. We will also explain how to add the Zabbix agent to the Zabbix server for monitoring.
+
+#### Requirements
+
+ * Two system with Debian 9 installed.
+ * Minimum 1 GB of RAM and 10 DB of disk space required. Amount of RAM and Disk space depends on the number of hosts and the parameters that are being monitored.
+ * A non-root user with sudo privileges setup on your server.
+
+
+
+#### Getting Started
+
+Before starting, it is necessary to update your server's package repository to the latest stable version. You can update it by just running the following command on both instances:
+
+```
+sudo apt-get update -y
+sudo apt-get upgrade -y
+```
+
+Next, restart your system to apply these changes.
+
+#### Install Apache, PHP and MariaDB
+
+Zabbix runs on Apache web server, written in PHP and uses MariaDB/MySQL to store their data. So in order to install Zabbix, you will require Apache, MariaDB and PHP to work. First, install Apache, PHP and Other PHP modules by running the following command:
+
+```
+sudo apt-get install apache2 libapache2-mod-php7.0 php7.0 php7.0-xml php7.0-bcmath php7.0-mbstring -y
+```
+
+Next, you will need to add MariaDB repository to your system. Because, latest version of the MariaDB is not available in Debian 9 default repository.
+
+You can add the repository by running the following command:
+
+```
+sudo apt-get install software-properties-common -y
+sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xF1656F24C74CD1D8
+sudo add-apt-repository 'deb [arch=amd64] http://www.ftp.saix.net/DB/mariadb/repo/10.1/debian stretch main'
+```
+
+Next, update the repository by running the following command:
+
+```
+sudo apt-get update -y
+```
+
+Finally, install the MariaDB server with the following command:
+
+```
+sudo apt-get install mariadb-server -y
+```
+
+By default, MariaDB installation is not secured. So you will need to secure it first. You can do this by running the mysql_secure_installation script.
+
+```
+sudo mysql_secure_installation
+```
+
+Answer all the questions as shown below:
+```
+
+Enter current password for root (enter for none): Enter
+Set root password? [Y/n]: Y
+New password:
+Re-enter new password:
+Remove anonymous users? [Y/n]: Y
+Disallow root login remotely? [Y/n]: Y
+Remove test database and access to it? [Y/n]: Y
+Reload privilege tables now? [Y/n]: Y
+
+```
+
+The above script will set the root password, remove test database, remove anonymous user and Disallow root login from a remote location.
+
+Once the MariaDB installation is secured, start the Apache and MariaDB service and enable them to start on boot time by running the following command:
+
+```
+sudo systemctl start apache2
+sudo systemctl enable apache2
+sudo systemctl start mysql
+sudo systemctl enable mysql
+```
+
+#### Installing Zabbix Server
+
+By default, Zabbix is available in the Debian 9 repository, but it might be outdated. So it is recommended to install most recent version from the official Zabbix repositories. You can download and add the latest version of the Zabbix repository with the following command:
+
+```
+wget http://repo.zabbix.com/zabbix/3.0/debian/pool/main/z/zabbix-release/zabbix-release_3.0-2+stretch_all.deb
+```
+
+Next, install the downloaded repository with the following command:
+
+```
+sudo dpkg -i zabbix-release_3.0-2+stretch_all.deb
+```
+
+Next, update the package cache and install Zabbix server with web front-end and Mysql support by running the following command:
+
+```
+sudo apt-get update -y
+sudo apt-get install zabbix-server-mysql zabbix-frontend-php -y
+```
+
+You will also need to install the Zabbix agent to collect data about the Zabbix server status itself:
+
+```
+sudo apt-get install zabbix-agent -y
+```
+
+After installing Zabbix agent, start the Zabbix agent service and enable it to start on boot time by running the following command:
+
+```
+sudo systemctl start zabbix-agent
+sudo systemctl enable zabbix-agent
+```
+
+#### Configuring Zabbix Database
+
+Zabbix uses MariaDB/MySQL as a database backend. So, you will need to create a MySQL database and User for zabbix installation:
+
+First, log into MySQL shell with the following command:
+
+```
+mysql -u root -p
+```
+
+Enter your root password, then create a database for Zabbix with the following command:
+
+```
+MariaDB [(none)]> CREATE DATABASE zabbixdb character set utf8 collate utf8_bin;
+```
+
+Next, create a user for Zabbix, assign a password and grant all privileges on Zabbix database with the following command:
+
+```
+MariaDB [(none)]> CREATE user zabbix identified by 'password';
+MariaDB [(none)]> GRANT ALL PRIVILEGES on zabbixdb.* to zabbixuser@localhost identified by 'password';
+```
+
+Next, flush the privileges with the following command:
+
+```
+MariaDB [(none)]> FLUSH PRIVILEGES;
+```
+
+Finally, exit from the MySQL shell with the following command:
+
+```
+MariaDB [(none)]> exit;
+```
+
+Next, import initial schema and data to the newly created database with the following command:
+
+```
+cd /usr/share/doc/zabbix-server-mysql*/
+zcat create.sql.gz | mysql -u zabbix -p zabbixdb
+```
+
+#### Configuring Zabbix
+
+Zabbix creates its own configuration file at `/etc/zabbix/apache.conf`. Edit this file and update the Timezone and PHP setting as per your need:
+
+```
+sudo nano /etc/zabbix/apache.conf
+```
+
+Change the file as shown below:
+```
+ php_value max_execution_time 300
+ php_value memory_limit 128M
+ php_value post_max_size 32M
+ php_value upload_max_filesize 8M
+ php_value max_input_time 300
+ php_value always_populate_raw_post_data -1
+ php_value date.timezone Asia/Kolkata
+
+```
+
+Save the file when you are finished.
+
+Next, you will need to update the database details for Zabbix. You can do this by editing `/etc/zabbix/zabbix_server.conf` file:
+
+```
+sudo nano /etc/zabbix/zabbix_server.conf
+```
+
+Change the following lines:
+```
+DBHost=localhost
+DBName=zabbixdb
+DBUser=zabbixuser
+DBPassword=password
+
+```
+
+Save and close the file when you are finished. Then restart all the services with the following command:
+
+```
+sudo systemctl restart apache2
+sudo systemctl restart mysql
+sudo systemctl restart zabbix-server
+```
+
+#### Configuring Firewall
+
+Before proceeding, you will need to configure the UFW firewall to secure Zabbix server.
+
+First, make sure UFW is installed on your system. Otherewise, you can install it by running the following command:
+
+```
+sudo apt-get install ufw -y
+```
+
+Next, enable the UFW firewall:
+
+```
+sudo ufw enable
+```
+
+Next, allow port 10050, 10051 and 80 through UFW with the following command:
+
+```
+sudo ufw allow 10050/tcp
+sudo ufw allow 10051/tcp
+sudo ufw allow 80/tcp
+```
+
+Finally, reload the firewall to apply these changes with the following command:
+
+```
+sudo ufw reload
+```
+
+Once the UFW firewall is configured you can proceed to install the Zabbix server via web interface.
+
+#### Accessing Zabbix Web Installation Wizard
+
+Once everything is fine, it's time to access Zabbix web installation wizard.
+
+Open your web browser and navigate the URL , you will be redirected to the following page:
+
+[![Zabbix 3.0][2]][3]
+
+Click on the **Next step** button, you should see the following page:
+
+[![Zabbix Prerequisites][4]][5]
+
+Here, all the Zabbix pre-requisites are checked and verified, then click on the **Next step** button you should see the following page:
+
+[![Database Configuration][6]][7]
+
+Here, provide the Zabbix database name, database user and password then click on the **Next step** button, you should see the following page:
+
+[![Zabbix Server Details][8]][9]
+
+Here, specify the Zabbix server details and Port number then click on the **Next step** button, you should see the pre-installation summary of Zabbix Server in following page:
+
+[![Installation summary][10]][11]
+
+Next, click on the **Next step** button to start the Zabbix installation. Once the Zabbix installation is completed successfully, you should see the following page:
+
+[![Zabbix installed successfully][12]][13]
+
+Here, click on the **Finish** button, it will redirect to the Zabbix login page as shown below:
+
+[![Login to Zabbix][14]][15]
+
+Here, provide username as Admin and password as zabbix then click on the **Sign in** button. You should see the Zabbix server dashboard in the following image:
+
+[![Zabbix Dashboard][16]][17]
+
+Your Zabbix web installation is now finished.
+
+#### Install Zabbix Agent
+
+Now your Zabbix server is up and functioning. It's time to add Zabbix agent node to the Zabbix Server for Monitoring.
+
+First, log into Zabbix agent instance and add the Zabbix repository with the following command:
+
+```
+wget http://repo.zabbix.com/zabbix/3.0/debian/pool/main/z/zabbix-release/zabbix-release_3.0-2+stretch_all.deb
+sudo dpkg -i zabbix-release_3.0-2+stretch_all.deb
+sudo apt-get update -y
+```
+
+Once you have configured Zabbix repository on your system, install the Zabbix agent by just running the following command:
+
+```
+sudo apt-get install zabbix-agent -y
+```
+
+Once the Zabbix agent is installed, you will need to configure Zabbix agent to communicate with Zabbix server. You can do this by editing the Zabbix agent configuration file:
+
+```
+sudo nano /etc/zabbix/zabbix_agentd.conf
+```
+
+Change the file as shown below:
+```
+ #Zabbix Server IP Address / Hostname
+
+ Server=192.168.0.103
+
+ #Zabbix Agent Hostname
+
+ Hostname=zabbix-agent
+
+
+```
+
+Save and close the file when you are finished, then restart the Zabbix agent service and enable it to start on boot time with the following command:
+
+```
+sudo systemctl restart zabbix-agent
+sudo systemctl enable zabbix-agent
+```
+
+#### Add Zabbix Agent Node to Zabbix Server
+
+Next, you will need to add the Zabbix agent node to the Zabbix server for monitoring. First, log in to the Zabbix server web interface.
+
+[![Zabbix UI][18]][19]
+
+Next, Click on **Configuration --> Hosts -> Create Host**, you should see the following page:
+
+[![Create Host in Zabbix][20]][21]
+
+Here, specify the Hostname, IP address and Group names of Zabbix agent. Then navigate to Templates tab, you should see the following page:
+
+[![specify the Hostname, IP address and Group name][22]][23]
+
+Here, search appropriate templates and click on **Add** button, you should see the following page:
+
+[![OS Template][24]][25]
+
+Finally, click on **Add** button again. You will see your new host with green labels indicating that everything is working fine.
+
+[![Hast successfully added to Zabbix][26]][27]
+
+If you have extra servers and network devices that you want to monitor, log into each host, install the Zabbix agent and add each host from the Zabbix web interface.
+
+#### Conclusion
+
+Congratulations! you have successfully installed the Zabbix server and Zabbix agent in Debian 9 server. You have also added Zabbix agent node to the Zabbix server for monitoring. You can now easily list the current issue and past history, get the latest data of hosts, list the current problems and also visualized the collected resource statistics such as CPU load, CPU utilization, Memory usage, etc via graphs. I hope you can now easily install and configure Zabbix on Debian 9 server and deploy it on production environment. Compared to other monitoring software, Zabbix allows you to build your own maps of different network segments while monitoring many hosts. You can also monitor Windows host using Zabbix windows agent. For more information, you can refer the [Zabbix Documentation Page][28]. Feel free to ask me if you have any questions.
+
+
+--------------------------------------------------------------------------------
+
+via: https://www.howtoforge.com/tutorial/install-zabbix-monitoring-server-and-agent-on-debian-9/
+
+作者:[Hitesh Jethva][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.howtoforge.com
+[1]:/cdn-cgi/l/email-protection
+[2]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-welcome-page.png
+[3]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-welcome-page.png
+[4]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-pre-requisite-check-page.png
+[5]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-pre-requisite-check-page.png
+[6]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-db-config-page.png
+[7]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-db-config-page.png
+[8]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-server-details.png
+[9]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-server-details.png
+[10]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-pre-installation-summary.png
+[11]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-pre-installation-summary.png
+[12]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-install-success.png
+[13]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-install-success.png
+[14]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-login-page.png
+[15]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-login-page.png
+[16]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-welcome-dashboard.png
+[17]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-welcome-dashboard.png
+[18]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-welcome-dashboard1.png
+[19]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-welcome-dashboard1.png
+[20]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-agent-host1.png
+[21]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-agent-host1.png
+[22]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-agent-add-templates.png
+[23]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-agent-add-templates.png
+[24]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-agent-select-templates.png
+[25]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-agent-select-templates.png
+[26]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/Screenshot-of-zabbix-agent-dashboard.png
+[27]:https://www.howtoforge.com/images/install_zabbix_monitoring_server_and_agent_on_debian_9/big/Screenshot-of-zabbix-agent-dashboard.png
+[28]:https://www.zabbix.com/documentation/3.2/
diff --git a/sources/tech/20180129 Parsing HTML with Python.md b/sources/tech/20180129 Parsing HTML with Python.md
new file mode 100644
index 0000000000..d0dbee596f
--- /dev/null
+++ b/sources/tech/20180129 Parsing HTML with Python.md
@@ -0,0 +1,212 @@
+Parsing HTML with Python
+======
+
+
+
+Image by : Jason Baker for Opensource.com.
+
+As a long-time member of the documentation team at Scribus, I keep up-to-date with the latest updates of the source so I can help make updates and additions to the documentation. When I recently did a "checkout" using Subversion on a computer I had just upgraded to Fedora 27, I was amazed at how long it took to download the documentation, which consists of HTML pages and associated images. I became concerned that the project's documentation seemed much larger than it should be and suspected that some of the content was "zombie" documentation--HTML files that aren't used anymore and images that have lost all references in the currently used HTML.
+
+I decided to create a project for myself to figure this out. One way to do this is to search for existing image files that aren't used. If I could scan through all the HTML files for image references, then compare that list to the actual image files, chances are I would see a mismatch.
+
+Here is a typical image tag:
+```
+
+```
+
+I'm interested in the part between the first set of quotation marks, after `src=`. After some searching for a solution, I found a Python module called [BeautifulSoup][1]. The tasty part of the script I wrote looks like this:
+```
+soup = BeautifulSoup(all_text, 'html.parser')
+match = soup.findAll("img")
+if len(match) > 0:
+ for m in match:
+ imagelist.append(str(m))
+```
+
+We can use this `findAll` method to pluck out the image tags. Here is a tiny piece of the output:
+```
+
+
+
+```
+
+So far, so good. I thought that the next step might be to just carve this down, but when I tried some string methods in the script, it returned errors about this being tags and not strings. I saved the output to a file and went through the process of editing in [KWrite][2]. One nice thing about KWrite is that you can do a "find & replace" using regular expressions (regex), so I could replace `', all_text)
+if len(match)>0:
+ for m in match:
+ imagelist.append(m)
+```
+
+And a tiny piece of its output looks like this:
+```
+images/cmcanvas.png" title="Context Menu for the document canvas" alt="Context Menu for the document canvas" /> `, which is termed greedy, meaning it doesn't necessarily stop at the first instance of `/>` it encounters. I should add that I also tried `src="(.*)"` which was really no better. Not being a regexpert (just made this up), my searching around for various ideas to improve this didn't help.
+
+After a series of other things, even trying out `HTML::Parser` with Perl, I finally tried to compare this to the situation of some scripts that I wrote for Scribus that analyze the contents of a text frame, character by character, then take some action. For my purposes, what I finally came up with improves on all these methods and requires no regex or HTML parser at all. Let's go back to that example `img` tag I showed.
+```
+
+```
+
+I decided to home in on the `src=` piece. One way would be to wait for an occurrence of `s`, then see if the next character is `r`, the next `c`, and the next `=`. If so, bingo! Then what follows between two sets of double quotation marks is what I need. The problem with this is the structure it takes to hang onto these. One way of looking at a string of characters representing a line of HTML text would be:
+```
+for c in all_text:
+```
+
+But the logic was just too messy to hang onto the previous `c`, and the one before that, the one before that, and the one before that.
+
+In the end, I decided to focus on the `=` and to use an indexing method whereby I could easily reference any prior or future character in the string. Here is the searching part:
+```
+ index = 3
+ while index < linelength:
+ if (all_text[index] == '='):
+ if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and (all_text[index-1] == 'c'):
+ imagefound(all_text, imagelist, index)
+ index += 1
+ else:
+ index += 1
+ else:
+ index += 1
+```
+
+I start the search with the fourth character (indexing starts at 0), so I don't get an indexing error down below, and realistically, there will not be an equal sign before the fourth character of a line. The first test is to see if we find `=` as we're marching through the string, and if not, we march on. If we do see one, then we ask if the three previous characters were `s`, `r`, and `c`, in that order. If that happens, we call the function `imagefound`:
+```
+def imagefound(all_text, imagelist, index):
+ end = 0
+ index += 2
+ newimage = ''
+ while end == 0:
+ if (all_text[index] != '"'):
+ newimage = newimage + all_text[index]
+ index += 1
+ else:
+ newimage = newimage + '\n'
+ imagelist.append(newimage)
+ end = 1
+ return
+```
+
+We're sending the function the current index, which represents the `=`. We know the next character will be `"`, so we jump two characters and begin adding characters to a holding string named `newimage`, until we reach the following `"`, at which point we're done. We add the string plus a `newline` character to our list `imagelist` and `return`, keeping in mind there may be more image tags in this remaining string of HTML, so we're right back in the middle of our searching loop.
+
+Here's what our output looks like now:
+```
+images/text-frame-link.png
+images/text-frame-unlink.png
+images/gimpoptions1.png
+images/gimpoptions3.png
+images/gimpoptions2.png
+images/fontpref3.png
+images/font-subst.png
+images/fontpref2.png
+images/fontpref1.png
+images/dtp-studio.png
+```
+
+Ahhh, much cleaner, and this only took a few seconds to run. I could have jumped seven more index spots to cut out the `images/` part, but I like having it there to make sure I haven't chopped off the first letter of the image filename, and this is so easy to edit out with KWrite--you don't even need regex. After doing that and saving the file, the next step was to run another script I wrote called `sortlist.py`:
+```
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# sortlist.py
+
+import os
+
+imagelist = []
+for line in open('/tmp/imagelist_parse4.txt').xreadlines():
+ imagelist.append(line)
+
+imagelist.sort()
+
+outfile = open('/tmp/imagelist_parse4_sorted.txt', 'w')
+outfile.writelines(imagelist)
+outfile.close()
+```
+
+This pulls in the file contents as a list, sorts it, then saves it as another file. After that I could just do the following:
+```
+ls /home/gregp/development/Scribus15x/doc/en/images/*.png > '/tmp/actual_images.txt'
+```
+
+Then I need to run `sortlist.py` on that file too, since the method `ls` uses to sort is different from Python. I could have run a comparison script on these files, but I preferred to do this visually. In the end, I ended up with 42 images that had no HTML reference from the documentation.
+
+Here is my parsing script in its entirety:
+```
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# parseimg4.py
+
+import os
+
+def imagefound(all_text, imagelist, index):
+ end = 0
+ index += 2
+ newimage = ''
+ while end == 0:
+ if (all_text[index] != '"'):
+ newimage = newimage + all_text[index]
+ index += 1
+ else:
+ newimage = newimage + '\n'
+ imagelist.append(newimage)
+ end = 1
+ return
+
+htmlnames = []
+imagelist = []
+tempstring = ''
+filenames = os.listdir('/home/gregp/development/Scribus15x/doc/en/')
+for name in filenames:
+ if name.endswith('.html'):
+ htmlnames.append(name)
+#print htmlnames
+for htmlfile in htmlnames:
+ all_text = open('/home/gregp/development/Scribus15x/doc/en/' + htmlfile).read()
+ linelength = len(all_text)
+ index = 3
+ while index < linelength:
+ if (all_text[index] == '='):
+ if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and
+(all_text[index-1] == 'c'):
+ imagefound(all_text, imagelist, index)
+ index += 1
+ else:
+ index += 1
+ else:
+ index += 1
+
+outfile = open('/tmp/imagelist_parse4.txt', 'w')
+outfile.writelines(imagelist)
+outfile.close()
+imageno = len(imagelist)
+print str(imageno) + " images were found and saved"
+```
+
+Its name, `parseimg4.py`, doesn't really reflect the number of scripts I wrote along the way, with both minor and major rewrites, plus discards and starting over. Notice that I've hardcoded these directory and filenames, but it would be easy enough to generalize, asking for user input for these pieces of information. Also as they were working scripts, I sent the output to `/tmp`, so they disappear once I reboot my system.
+
+This wasn't the end of the story, since the next question was: What about zombie HTML files? Any of these files that are not used might reference images not picked up by the previous method. We have a `menu.xml` file that serves as the table of contents for the online manual, but I also needed to consider that some files listed in the TOC might reference files not in the TOC, and yes, I did find some.
+
+I'll conclude by saying that this was a simpler task than this image search, and it was greatly helped by the processes I had already developed.
+
+
+### About the author
+
+ [][7] Greg Pittman - Greg is a retired neurologist in Louisville, Kentucky, with a long-standing interest in computers and programming, beginning with Fortran IV in the 1960s. When Linux and open source software came along, it kindled a commitment to learning more, and eventually contributing. He is a member of the Scribus Team.[More about me][8]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/parsing-html-python
+
+作者:[Greg Pittman][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/greg-p
+[1]:https://www.crummy.com/software/BeautifulSoup/
+[2]:https://www.kde.org/applications/utilities/kwrite/
+[7]:https://opensource.com/users/greg-p
+[8]:https://opensource.com/users/greg-p
diff --git a/sources/tech/20180129 Rapid, Secure Patching- Tools and Methods.md b/sources/tech/20180129 Rapid, Secure Patching- Tools and Methods.md
new file mode 100644
index 0000000000..9ac7340c14
--- /dev/null
+++ b/sources/tech/20180129 Rapid, Secure Patching- Tools and Methods.md
@@ -0,0 +1,583 @@
+Rapid, Secure Patching: Tools and Methods
+======
+
+It was with some measure of disbelief that the computer science community greeted the recent [EternalBlue][1]-related exploits that have torn through massive numbers of vulnerable systems. The SMB exploits have kept coming (the most recent being [SMBLoris][2] presented at the last DEF CON, which impacts multiple SMB protocol versions, and for which Microsoft will issue no corrective patch. Attacks with these tools [incapacitated critical infrastructure][3] to the point that patients were even turned away from the British National Health Service.
+
+It is with considerable sadness that, during this SMB catastrophe, we also have come to understand that the famous Samba server presented an exploitable attack surface on the public internet in sufficient numbers for a worm to propagate successfully. I previously [have discussed SMB security][4] in Linux Journal, and I am no longer of the opinion that SMB server processes should run on Linux.
+
+In any case, systems administrators of all architectures must be able to down vulnerable network servers and patch them quickly. There is often a need for speed and competence when working with a large collection of Linux servers. Whether this is due to security situations or other concerns is immaterial—the hour of greatest need is not the time to begin to build administration tools. Note that in the event of an active intrusion by hostile parties, [forensic analysis][5] may be a legal requirement, and no steps should be taken on the compromised server without a careful plan and documentation. Especially in this new era of the black hats, computer professionals must step up their game and be able to secure vulnerable systems quickly.
+
+### Secure SSH Keypairs
+
+Tight control of a heterogeneous UNIX environment must begin with best-practice use of SSH authentication keys. I'm going to open this section with a simple requirement. SSH private keys must be one of three types: Ed25519, ECDSA using the E-521 curve or RSA keys of 3072 bits. Any key that does not meet those requirements should be retired (in particular, DSA keys must be removed from service immediately).
+
+The [Ed25519][6] key format is associated with Daniel J. Bernstein, who has such a preeminent reputation in modern cryptography that the field is becoming a DJB [monoculture][7]. The Ed25519 format is deigned for speed, security and size economy. If all of your SSH servers are recent enough to support Ed25519, then use it, and consider nothing else.
+
+[Guidance on creating Ed25519 keys][8] suggests 100 rounds for a work factor in the "-o" secure format. Raising the number of rounds raises the strength of the encrypted key against brute-force attacks (should a file copy of the private key fall into hostile hands), at the cost of more work and time in decrypting the key when ssh-add is executed. Although there always is [controversy and discussion][9] with security advances, I will repeat the guidance here and suggest that the best format for a newly created SSH key is this:
+
+```
+
+ssh-keygen -a 100 -t ed25519
+
+```
+
+Your systems might be too old to support Ed25519—Oracle/CentOS/Red Hat 7 have this problem (the 7.1 release introduced support). If you cannot upgrade your old SSH clients and servers, your next best option is likely E-521, available in the ECDSA key format.
+
+The ECDSA curves came from the US government's National Institute of Standards (NIST). The best known and most implemented of all of the NIST curves are P-256, P-384 and E-521\. All three curves are approved for secret communications by a variety of government entities, but a number of cryptographers have [expressed growing suspicion][10] that the P-256 and P-384 curves are tainted. Well known cryptographer Bruce Schneier [has remarked][11]: "I no longer trust the constants. I believe the NSA has manipulated them through their relationships with industry." However, DJB [has expressed][12] limited praise of the E-521 curve: "To be fair I should mention that there's one standard NIST curve using a nice prime, namely 2521 – 1; but the sheer size of this prime makes it much slower than NIST P-256." All of the NIST curves have greater issues with "side channel" attacks than Ed25519—P-521 is certainly a step down, and many assert that none of the NIST curves are safe. In summary, there is a slight risk that a powerful adversary exists with an advantage over the P-256 and P-384 curves, so one is slightly inclined to avoid them. Note that even if your OpenSSH (source) release is capable of E-521, it may be [disabled by your vendor][13] due to patent concerns, so E-521 is not an option in this case. If you cannot use DJB's 2255 – 19 curve, this command will generate an E-521 key on a capable system:
+
+```
+
+ssh-keygen -o -a 100 -b 521 -t ecdsa
+
+```
+
+And, then there is the unfortunate circumstance with SSH servers that support neither ECDSA nor Ed25519\. In this case, you must fall back to RSA with much larger key sizes. An absolute minimum is the modern default of 2048 bits, but 3072 is a wiser choice:
+
+```
+
+ssh-keygen -o -a 100 -b 3072 -t rsa
+
+```
+
+Then in the most lamentable case of all, when you must use old SSH clients that are not able to work with private keys created with the -o option, you can remove the password on id_rsa and create a naked key, then use OpenSSL to encrypt it with AES256 in the PKCS#8 format, as [first documented by Martin Kleppmann][14]. Provide a blank new password for the keygen utility below, then supply a new password when OpenSSL reprocesses the key:
+
+```
+
+$ cd ~/.ssh
+
+$ cp id_rsa id_rsa-orig
+
+$ ssh-keygen -p -t rsa
+Enter file in which the key is (/home/cfisher/.ssh/id_rsa):
+Enter old passphrase:
+Key has comment 'cfisher@localhost.localdomain'
+Enter new passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved with the new passphrase.
+
+$ openssl pkcs8 -topk8 -v2 aes256 -in id_rsa -out id_rsa-strong
+Enter Encryption Password:
+Verifying - Enter Encryption Password:
+
+mv id_rsa-strong id_rsa
+chmod 600 id_rsa
+
+```
+
+After creating all of these keys on a newer system, you can compare the file sizes:
+
+```
+
+$ ll .ssh
+total 32
+-rw-------. 1 cfisher cfisher 801 Aug 10 21:30 id_ecdsa
+-rw-r--r--. 1 cfisher cfisher 283 Aug 10 21:30 id_ecdsa.pub
+-rw-------. 1 cfisher cfisher 464 Aug 10 20:49 id_ed25519
+-rw-r--r--. 1 cfisher cfisher 111 Aug 10 20:49 id_ed25519.pub
+-rw-------. 1 cfisher cfisher 2638 Aug 10 21:45 id_rsa
+-rw-------. 1 cfisher cfisher 2675 Aug 10 21:42 id_rsa-orig
+-rw-r--r--. 1 cfisher cfisher 583 Aug 10 21:42 id_rsa.pub
+
+```
+
+Although they are relatively enormous, all versions of OpenSSH that I have used have been compatible with the RSA private key in PKCS#8 format. The Ed25519 public key is now small enough to fit in 80 columns without word wrap, and it is as convenient as it is efficient and secure.
+
+Note that PuTTY may have problems using various versions of these keys, and you may need to remove passwords for a successful import into the PuTTY agent.
+
+These keys represent the most secure formats available for various OpenSSH revisions. They really aren't intended for PuTTY or other general interactive activity. Although one hopes that all users create strong keys for all situations, these are enterprise-class keys for major systems activities. It might be wise, however, to regenerate your system host keys to conform to these guidelines.
+
+These key formats may soon change. Quantum computers are causing increasing concern for their ability to run [Shor's Algorithm][15], which can be used to find prime factors to break these keys in reasonable time. The largest commercially available quantum computer, the [D-Wave 2000Q][16], effectively [presents under 200 qubits][17] for this activity, which is not (yet) powerful enough for a successful attack. NIST [announced a competition][18] for a new quantum-resistant public key system with a deadline of November 2017 In response, a team including DJB has released source code for [NTRU Prime][19]. It does appear that we will likely see a post-quantum public key format for OpenSSH (and potentially TLS 1.3) released within the next two years, so take steps to ease migration now.
+
+Also, it's important for SSH servers to restrict their allowed ciphers, MACs and key exchange lest strong keys be wasted on broken crypto (3DES, MD5 and arcfour should be long-disabled). My [previous guidance][20] on the subject involved the following (three) lines in the SSH client and server configuration (note that formatting in the sshd_config file requires all parameters on the same line with no spaces in the options; line breaks have been added here for clarity):
+
+```
+
+Ciphers chacha20-poly1305@openssh.com,
+ aes256-gcm@openssh.com,
+ aes128-gcm@openssh.com,
+ aes256-ctr,
+ aes192-ctr,
+ aes128-ctr
+
+MACs hmac-sha2-512-etm@openssh.com,
+ hmac-sha2-256-etm@openssh.com,
+ hmac-ripemd160-etm@openssh.com,
+ umac-128-etm@openssh.com,
+ hmac-sha2-512,
+ hmac-sha2-256,
+ hmac-ripemd160,
+ umac-128@openssh.com
+
+KexAlgorithms curve25519-sha256@libssh.org,
+ diffie-hellman-group-exchange-sha256
+
+```
+
+Since the previous publication, RIPEMD160 is likely no longer safe and should be removed. Older systems, however, may support only SHA1, MD5 and RIPEMD160\. Certainly remove MD5, but users of PuTTY likely will want to retain SHA1 when newer MACs are not an option. Older servers can present a challenge in finding a reasonable Cipher/MAC/KEX when working with modern systems.
+
+At this point, you should have strong keys for secure clients and servers. Now let's put them to use.
+
+### Scripting the SSH Agent
+
+Modern OpenSSH distributions contain the ssh-copy-id shell script for easy key distribution. Below is an example of installing a specific, named key in a remote account:
+
+```
+
+$ ssh-copy-id -i ~/.ssh/some_key.pub person@yourserver.com
+ssh-copy-id: INFO: Source of key(s) to be installed:
+ "/home/cfisher/.ssh/some_key.pub"
+ssh-copy-id: INFO: attempting to log in with the new key(s),
+ to filter out any that are already installed
+ssh-copy-id: INFO: 1 key(s) remain to be installed --
+ if you are prompted now it is to install the new keys
+person@yourserver.com's password:
+
+Number of key(s) added: 1
+
+Now try logging into the machine, with:
+ "ssh 'person@yourserver.com'"
+and check to make sure that only the key(s) you wanted were added.
+
+```
+
+If you don't have the ssh-copy-id script, you can install a key manually with the following command:
+
+```
+
+$ ssh person@yourserver.com 'cat >> ~/.ssh/authorized_keys' < \
+ ~/.ssh/some_key.pub
+
+```
+
+If you have SELinux enabled, you might have to mark a newly created authorized_keys file with a security type; otherwise, the sshd server dæmon will be prevented from reading the key (the syslog may report this issue):
+
+```
+
+$ ssh person@yourserver.com 'chcon -t ssh_home_t
+ ↪~/.ssh/authorized_keys'
+
+```
+
+Once your key is installed, test it in a one-time use with the -i option (note that you are entering a local key password, not a remote authentication password):
+
+```
+
+$ ssh -i ~/.ssh/some_key person@yourserver.com
+Enter passphrase for key '/home/v-fishecj/.ssh/some_key':
+Last login: Wed Aug 16 12:20:26 2017 from 10.58.17.14
+yourserver $
+
+```
+
+General, interactive users likely will cache their keys with an agent. In the example below, the same password is used on all three types of keys that were created in the previous section:
+
+```
+
+$ eval $(ssh-agent)
+Agent pid 4394
+
+$ ssh-add
+Enter passphrase for /home/cfisher/.ssh/id_rsa:
+Identity added: ~cfisher/.ssh/id_rsa (~cfisher/.ssh/id_rsa)
+Identity added: ~cfisher/.ssh/id_ecdsa (cfisher@init.com)
+Identity added: ~cfisher/.ssh/id_ed25519 (cfisher@init.com)
+
+```
+
+The first command above launches a user agent process, which injects environment variables (named SSH_AGENT_SOCK and SSH_AGENT_PID) into the parent shell (via eval). The shell becomes aware of the agent and passes these variables to the programs that it runs from that point forward.
+
+When launched, the ssh-agent has no credentials and is unable to facilitate SSH activity. It must be primed by adding keys, which is done with ssh-add. When called with no arguments, all of the default keys will be read. It also can be called to add a custom key:
+
+```
+
+$ ssh-add ~/.ssh/some_key
+Enter passphrase for /home/cfisher/.ssh/some_key:
+Identity added: /home/cfisher/.ssh/some_key
+ ↪(cfisher@localhost.localdomain)
+
+```
+
+Note that the agent will not retain the password on the key. ssh-add uses any and all passwords that you enter while it runs to decrypt keys that it finds, but the passwords are cleared from memory when ssh-add terminates (they are not sent to ssh-agent). This allows you to upgrade to new key formats with minimal inconvenience, while keeping the keys reasonably safe.
+
+The current cached keys can be listed with ssh-add -l (from, which you can deduce that "some_key" is an Ed25519):
+
+```
+
+$ ssh-add -l
+3072 SHA256:cpVFMZ17oO5n/Jfpv2qDNSNcV6ffOVYPV8vVaSm3DDo
+ /home/cfisher/.ssh/id_rsa (RSA)
+521 SHA256:1L9/CglR7cstr54a600zDrBbcxMj/a3RtcsdjuU61VU
+ cfisher@localhost.localdomain (ECDSA)
+256 SHA256:Vd21LEM4lixY4rIg3/Ht/w8aoMT+tRzFUR0R32SZIJc
+ cfisher@localhost.localdomain (ED25519)
+256 SHA256:YsKtUA9Mglas7kqC4RmzO6jd2jxVNCc1OE+usR4bkcc
+ cfisher@localhost.localdomain (ED25519)
+
+```
+
+While a "primed" agent is running, the SSH clients may use (trusting) remote servers fluidly, with no further prompts for credentials:
+
+```
+
+$ sftp person@yourserver.com
+Connected to yourserver.com.
+sftp> quit
+
+$ scp /etc/passwd person@yourserver.com:/tmp
+passwd 100% 2269 65.8KB/s 00:00
+
+$ ssh person@yourserver.com
+ (motd for yourserver.com)
+$ ls -l /tmp/passwd
+-rw-r--r-- 1 root wheel 2269 Aug 16 09:07 /tmp/passwd
+$ rm /tmp/passwd
+$ exit
+Connection to yourserver.com closed.
+
+```
+
+The OpenSSH agent can be locked, preventing any further use of the credentials that it holds (this might be appropriate when suspending a laptop):
+
+```
+
+$ ssh-add -x
+Enter lock password:
+Again:
+Agent locked.
+
+$ ssh yourserver.com
+Enter passphrase for key '/home/cfisher/.ssh/id_rsa': ^C
+
+```
+
+It will provide credentials again when it is unlocked:
+
+```
+
+$ ssh-add -X
+Enter lock password:
+Agent unlocked.
+
+```
+
+You also can set ssh-agent to expire keys after a time limit with the -t option, which may be useful for long-lived agents that must clear keys after a set daily shift.
+
+General shell users may cache many types of keys with a number of differing agent implementations. In addition to the standard OpenSSH agent, users may rely upon PuTTY's pageant.exe, GNOME keyring or KDE Kwallet, among others (the use of the PUTTY agent could likely fill an article on its own).
+
+However, the goal here is to create "enterprise" keys for critical server controls. You likely do not want long-lived agents in order to limit the risk of exposure. When scripting with "enterprise" keys, you will run an agent only for the duration of the activity, then kill it at completion.
+
+There are special options for accessing the root account with OpenSSH—the PermitRootLogin parameter can be added to the sshd_config file (usually found in /etc/ssh). It can be set to a simple yes or no, forced-commands-only, which will allow only explicitly-authorized programs to be executed, or the equivalent options prohibit-password or without-password, both of which will allow access to the keys generated here.
+
+Many hold that root should not be allowed any access. [Michael W. Lucas][21] addresses the question in SSH Mastery:
+
+> Sometimes, it seems that you need to allow users to SSH in to the system as root. This is a colossally bad idea in almost all environments. When users must log in as a regular user and then change to root, the system logs record the user account, providing accountability. Logging in as root destroys that audit trail....It is possible to override the security precautions and make sshd permit a login directly as root. It's such a bad idea that I'd consider myself guilty of malpractice if I told you how to do it. Logging in as root via SSH almost always means you're solving the wrong problem. Step back and look for other ways to accomplish your goal.
+
+When root action is required quickly on more than a few servers, the above advice can impose painful delays. Lucas' direct criticism can be addressed by allowing only a limited set of "bastion" servers to issue root commands over SSH. Administrators should be forced to log in to the bastions with unprivileged accounts to establish accountability.
+
+However, one problem with remotely "changing to root" is the [statistical use of the Viterbi algorithm][22] Short passwords, the su - command and remote SSH calls that use passwords to establish a trinary network configuration are all uniquely vulnerable to timing attacks on a user's keyboard movement. Those with the highest security concerns will need to compensate.
+
+For the rest of us, I recommend that PermitRootLogin without-password be set for all target machines.
+
+Finally, you can easily terminate ssh-agent interactively with the -k option:
+
+```
+
+$ eval $(ssh-agent -k)
+Agent pid 4394 killed
+
+```
+
+With these tools and the intended use of them in mind, here is a complete script that runs an agent for the duration of a set of commands over a list of servers for a common named user (which is not necessarily root):
+
+```
+
+# cat artano
+
+#!/bin/sh
+
+if [[ $# -lt 1 ]]; then echo "$0 - requires commands"; exit; fi
+
+R="-R5865:127.0.0.1:5865" # set to "-2" if you don't want
+ ↪port forwarding
+
+eval $(ssh-agent -s)
+
+function cleanup { eval $(ssh-agent -s -k); }
+
+trap cleanup EXIT
+
+function remsh { typeset F="/tmp/${1}" h="$1" p="$2";
+ ↪shift 2; echo "#$h"
+ if [[ "$ARTANO" == "PARALLEL" ]]
+ then ssh "$R" -p "$p" "$h" "$@" < /dev/null >>"${F}.out"
+ ↪2>>"${F}.err" &
+ else ssh "$R" -p "$p" "$h" "$@"
+ fi } # HOST PORT CMD
+
+if ssh-add ~/.ssh/master_key
+then remsh yourserver.com 22 "$@"
+ remsh container.yourserver.com 2200 "$@"
+ remsh anotherserver.com 22 "$@"
+ # Add more hosts here.
+else echo Bad password - killing agent. Try again.
+fi
+
+wait
+
+#######################################################################
+# Examples: # Artano is an epithet of a famous mythical being
+# artano 'mount /patchdir' # you will need an fstab entry for this
+# artano 'umount /patchdir'
+# artano 'yum update -y 2>&1'
+# artano 'rpm -Fvh /patchdir/\*.rpm'
+#######################################################################
+
+```
+
+This script runs all commands in sequence on a collection of hosts by default. If the ARTANO environment variable is set to PARALLEL, it instead will launch them all as background processes simultaneously and append their STDOUT and STDERR to files in /tmp (this should be no problem when dealing with fewer than a hundred hosts on a reasonable server). The PARALLEL setting is useful not only for pushing changes faster, but also for collecting audit results.
+
+Below is an example using the yum update agent. The source of this particular invocation had to traverse a firewall and relied on a proxy setting in the /etc/yum.conf file, which used the port-forwarding option (-R) above:
+
+```
+
+# ./artano 'yum update -y 2>&1'
+Agent pid 3458
+Enter passphrase for /root/.ssh/master_key:
+Identity added: /root/.ssh/master_key (/root/.ssh/master_key)
+#yourserver.com
+Loaded plugins: langpacks, ulninfo
+No packages marked for update
+#container.yourserver.com
+Loaded plugins: langpacks, ulninfo
+No packages marked for update
+#anotherserver.com
+Loaded plugins: langpacks, ulninfo
+No packages marked for update
+Agent pid 3458 killed
+
+```
+
+The script can be used for more general maintenance functions. Linux installations running the XFS filesystem should "defrag" periodically. Although this normally would be done with cron, it can be a centralized activity, stored in a separate script that includes only on the appropriate hosts:
+
+```
+
+&1'
+Agent pid 7897
+Enter passphrase for /root/.ssh/master_key:
+Identity added: /root/.ssh/master_key (/root/.ssh/master_key)
+#yourserver.com
+#container.yourserver.com
+#anotherserver.com
+Agent pid 7897 killed
+
+```
+
+An easy method to collect the contents of all authorized_keys files for all users is the following artano script (this is useful for system auditing and is coded to remove file duplicates):
+
+```
+
+artano 'awk -F: {print\$6\"/.ssh/authorized_keys\"} \
+ /etc/passwd | sort -u | xargs grep . 2> /dev/null'
+
+```
+
+It is convenient to configure NFS mounts for file distribution to remote nodes. Bear in mind that NFS is clear text, and sensitive content should not traverse untrusted networks while unencrypted. After configuring an NFS server on host 1.2.3.4, I add the following line to the /etc/fstab file on all the clients and create the /patchdir directory. After the change, the artano script can be used to mass-mount the directory if the network configuration is correct:
+
+```
+
+# tail -1 /etc/fstab
+1.2.3.4:/var/cache/yum/x86_64/7Server/ol7_latest/packages
+ ↪/patchdir nfs4 noauto,proto=tcp,port=2049 0 0
+
+```
+
+Assuming that the NFS server is mounted, RPMs can be upgraded from images stored upon it (note that Oracle Spacewalk or Red Hat Satellite might be a more capable patch method):
+
+```
+
+# ./artano 'rpm -Fvh /patchdir/\*.rpm'
+Agent pid 3203
+Enter passphrase for /root/.ssh/master_key:
+Identity added: /root/.ssh/master_key (/root/.ssh/master_key)
+#yourserver.com
+Preparing... ########################
+Updating / installing...
+xmlsec1-1.2.20-7.el7_4 ########################
+xmlsec1-openssl-1.2.20-7.el7_4 ########################
+Cleaning up / removing...
+xmlsec1-openssl-1.2.20-5.el7 ########################
+xmlsec1-1.2.20-5.el7 ########################
+#container.yourserver.com
+Preparing... ########################
+Updating / installing...
+xmlsec1-1.2.20-7.el7_4 ########################
+xmlsec1-openssl-1.2.20-7.el7_4 ########################
+Cleaning up / removing...
+xmlsec1-openssl-1.2.20-5.el7 ########################
+xmlsec1-1.2.20-5.el7 ########################
+#anotherserver.com
+Preparing... ########################
+Updating / installing...
+xmlsec1-1.2.20-7.el7_4 ########################
+xmlsec1-openssl-1.2.20-7.el7_4 ########################
+Cleaning up / removing...
+xmlsec1-openssl-1.2.20-5.el7 ########################
+xmlsec1-1.2.20-5.el7 ########################
+Agent pid 3203 killed
+
+```
+
+I am assuming that my audience is already experienced with package tools for their preferred platforms. However, to avoid criticism that I've included little actual discussion of patch tools, the following is a quick reference of RPM manipulation commands, which is the most common package format on enterprise systems:
+
+* rpm -Uvh package.i686.rpm — install or upgrade a package file.
+
+* rpm -Fvh package.i686.rpm — upgrade a package file, if an older version is installed.
+
+* rpm -e package — remove an installed package.
+
+* rpm -q package — list installed package name and version.
+
+* rpm -q --changelog package — print full changelog for installed package (including CVEs).
+
+* rpm -qa — list all installed packages on the system.
+
+* rpm -ql package — list all files in an installed package.
+
+* rpm -qpl package.i686.rpm — list files included in a package file.
+
+* rpm -qi package — print detailed description of installed package.
+
+* rpm -qpi package — print detailed description of package file.
+
+* rpm -qf /path/to/file — list package that installed a particular file.
+
+* rpm --rebuild package.src.rpm — unpack and build a binary RPM under /usr/src/redhat.
+
+* rpm2cpio package.src.rpm | cpio -icduv — unpack all package files in the current directory.
+
+Another important consideration for scripting the SSH agent is limiting the capability of an authorized key. There is a [specific syntax][23] for such limitations Of particular interest is the from="" clause, which will restrict logins on a key to a limited set of hosts. It is likely wise to declare a set of "bastion" servers that will record non-root logins that escalate into controlled users who make use of the enterprise keys.
+
+An example entry might be the following (note that I've broken this line, which is not allowed syntax but done here for clarity):
+
+```
+
+from="*.c2.security.yourcompany.com,4.3.2.1" ssh-ed25519
+ ↪AAAAC3NzaC1lZDI1NTE5AAAAIJSSazJz6A5x6fTcDFIji1X+
+↪svesidBonQvuDKsxo1Mx
+
+```
+
+A number of other useful restraints can be placed upon authorized_keys entries. The command="" will restrict a key to a single program or script and will set the SSH_ORIGINAL_COMMAND environment variable to the client's attempted call—scripts can set alarms if the variable does not contain approved contents. The restrict option also is worth consideration, as it disables a large set of SSH features that can be both superfluous and dangerous.
+
+Although it is possible to set server identification keys in the known_hosts file to a @revoked status, this cannot be done with the contents of authorized_keys. However, a system-wide file for forbidden keys can be set in the sshd_config with RevokedKeys. This file overrides any user's authorized_keys. If set, this file must exist and be readable by the sshd server process; otherwise, no keys will be accepted at all (so use care if you configure it on a machine where there are obstacles to physical access). When this option is set, use the artano script to append forbidden keys to the file quickly when they should be disallowed from the network. A clear and convenient file location would be /etc/ssh/revoked_keys.
+
+It is also possible to establish a local Certificate Authority (CA) for OpenSSH that will [allow keys to be registered with an authority][24] with expiration dates. These CAs can [become quite elaborate][25] in their control over an enterprise. Although the maintenance of an SSH CA is beyond the scope of this article, keys issued by such CAs should be strong by adhering to the requirements for Ed25519/E-521/RSA-3072.
+
+### pdsh
+
+Many higher-level tools for the control of collections of servers exist that are much more sophisticated than the script I've presented here. The most famous is likely [Puppet][26], which is a Ruby-based configuration management system for enterprise control. Puppet has a somewhat short list of supported operating systems. If you are looking for low-level control of Android, Tomato, Linux smart terminals or other "exotic" POSIX, Puppet is likely not the appropriate tool. Another popular Ruby-based tool is [Chef][27], which is known for its complexity. Both Puppet and Chef require Ruby installations on both clients and servers, and they both will catalog any SSH keys that they find, so this key strength discussion is completely applicable to them.
+
+There are several similar Python-based tools, including [Ansible][28], [Bcfg2][29], [Fabric][30] and [SaltStack][31]. Of these, only Ansible can run "agentless" over a bare SSH connection; the rest will require agents that run on target nodes (and this likely includes a Python runtime).
+
+Another popular configuration management tool is [CFEngine][32], which is coded in C and claims very high performance. [Rudder][33] has evolved from portions of CFEngine and has a small but growing user community.
+
+Most of the previously mentioned packages are licensed commercially and some are closed source.
+
+The closest low-level tool to the activities presented here is the Parallel Distributed Shell (pdsh), which can be found in the [EPEL repository][34]. The pdsh utilities grew out of an IBM-developed package named dsh designed for the control of compute clusters. Install the following packages from the repository to use pdsh:
+
+```
+
+# rpm -qa | grep pdsh
+pdsh-2.31-1.el7.x86_64
+pdsh-rcmd-ssh-2.31-1.el7.x86_64
+
+```
+
+An SSH agent must be running while using pdsh with encrypted keys, and there is no obvious way to control the destination port on a per-host basis as was done with the artano script. Below is an example using pdsh to run a command on three remote servers:
+
+```
+
+# eval $(ssh-agent)
+Agent pid 17106
+
+# ssh-add ~/.ssh/master_key
+Enter passphrase for /root/.ssh/master_key:
+Identity added: /root/.ssh/master_key (/root/.ssh/master_key)
+
+# pdsh -w hosta.com,hostb.com,hostc.com uptime
+hosta: 13:24:49 up 13 days, 2:13, 6 users, load avg: 0.00, 0.01, 0.05
+hostb: 13:24:49 up 7 days, 21:15, 5 users, load avg: 0.05, 0.04, 0.05
+hostc: 13:24:49 up 9 days, 3:26, 3 users, load avg: 0.00, 0.01, 0.05
+
+# eval $(ssh-agent -k)
+Agent pid 17106 killed
+
+```
+
+The -w option above defines a host list. It allows for limited arithmetic expansion and can take the list of hosts from standard input if the argument is a dash (-). The PDSH_SSH_ARGS and PDSH_SSH_ARGS_APPEND environment variables can be used to pass custom options to the SSH call. By default, 32 sessions will be launched in parallel, and this "fanout/sliding window" will be maintained by launching new host invocations as existing connections complete and close. You can adjust the size of the "fanout" either with the -f option or the FANOUT environment variable. It's interesting to note that there are two file copy commands: pdcp and rpdcp, which are analogous to scp.
+
+Even a low-level utility like pdsh lacks some flexibility that is available by scripting OpenSSH, so prepare to feel even greater constraints as more complicated tools are introduced.
+
+### Conclusion
+
+Modern Linux touches us in many ways on diverse platforms. When the security of these systems is not maintained, others also may touch our platforms and turn them against us. It is important to realize the maintenance obligations when you add any Linux platform to your environment. This obligation always exists, and there are consequences when it is not met.
+
+In a security emergency, simple, open and well understood tools are best. As tool complexity increases, platform portability certainly declines, the number of competent administrators also falls, and this likely impacts speed of execution. This may be a reasonable trade in many other aspects, but in a security context, it demands a much more careful analysis. Emergency measures must be documented and understood by a wider audience than is required for normal operations, and using more general tools facilitates that discussion.
+
+I hope the techniques presented here will prompt that discussion for those who have not yet faced it.
+
+### Disclaimer
+
+The views and opinions expressed in this article are those of the author and do not necessarily reflect those of Linux Journal.
+
+### Note:
+
+An exploit [compromising Ed25519][35] was recently demonstrated that relies upon custom hardware changes to derive a usable portion of a secret key. Physical hardware security is a basic requirement for encryption integrity, and many common algorithms are further vulnerable to cache timing or other side channel attacks that can be performed by the unprivileged processes of other users. Use caution when granting access to systems that process sensitive data.
+
+
+--------------------------------------------------------------------------------
+
+via: http://www.linuxjournal.com/content/rapid-secure-patching-tools-and-methods
+
+作者:[Charles Fisher][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://www.linuxjournal.com/users/charles-fisher
+[1]:https://en.wikipedia.org/wiki/EternalBlue
+[2]:http://securityaffairs.co/wordpress/61530/hacking/smbloris-smbv1-flaw.html
+[3]:http://www.telegraph.co.uk/news/2017/05/13/nhs-cyber-attack-everything-need-know-biggest-ransomware-offensive
+[4]:http://www.linuxjournal.com/content/smbclient-security-windows-printing-and-file-transfer
+[5]:https://staff.washington.edu/dittrich/misc/forensics
+[6]:https://ed25519.cr.yp.to
+[7]:http://www.metzdowd.com/pipermail/cryptography/2016-March/028824.html
+[8]:https://blog.g3rt.nl/upgrade-your-ssh-keys.html
+[9]:https://news.ycombinator.com/item?id=12563899
+[10]:http://safecurves.cr.yp.to/rigid.html
+[11]:https://en.wikipedia.org/wiki/Curve25519
+[12]:http://blog.cr.yp.to/20140323-ecdsa.html
+[13]:https://lwn.net/Articles/573166
+[14]:http://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html
+[15]:https://en.wikipedia.org/wiki/Shor's_algorithm
+[16]:https://www.dwavesys.com/d-wave-two-system
+[17]:https://crypto.stackexchange.com/questions/40893/can-or-can-not-d-waves-quantum-computers-use-shors-and-grovers-algorithm-to-f
+[18]:https://yro.slashdot.org/story/16/12/21/2334220/nist-asks-public-for-help-with-quantum-proof-cryptography
+[19]:https://ntruprime.cr.yp.to/index.html
+[20]:http://www.linuxjournal.com/content/cipher-security-how-harden-tls-and-ssh
+[21]:https://www.michaelwlucas.com/tools/ssh
+[22]:https://people.eecs.berkeley.edu/~dawnsong/papers/ssh-timing.pdf
+[23]:https://man.openbsd.org/sshd#AUTHORIZED_KEYS_FILE_FORMAT
+[24]:https://ef.gy/hardening-ssh
+[25]:https://code.facebook.com/posts/365787980419535/scalable-and-secure-access-with-ssh
+[26]:https://puppet.com
+[27]:https://www.chef.io
+[28]:https://www.ansible.com
+[29]:http://bcfg2.org
+[30]:http://www.fabfile.org
+[31]:https://saltstack.com
+[32]:https://cfengine.com
+[33]:http://www.rudder-project.org/site
+[34]:https://fedoraproject.org/wiki/EPEL
+[35]:https://research.kudelskisecurity.com/2017/10/04/defeating-eddsa-with-faults
diff --git a/sources/tech/20180129 WebSphere MQ programming in Python with Zato.md b/sources/tech/20180129 WebSphere MQ programming in Python with Zato.md
new file mode 100644
index 0000000000..3e53d67201
--- /dev/null
+++ b/sources/tech/20180129 WebSphere MQ programming in Python with Zato.md
@@ -0,0 +1,262 @@
+WebSphere MQ programming in Python with Zato
+======
+[WebSphere MQ][1] is a messaging middleware product by IBM - a message queue server - and this post shows how to integrate with MQ from Python and [Zato][2].
+
+The article will go through a short process that will let you:
+
+ * Send messages to queues in 1 line of Python code
+ * Receive messages from queues without coding
+ * Seamlessly integrate with Java JMS applications - frequently found in WebSphere MQ environments
+ * Push MQ messages from [Django][3] or [Flask][4]
+
+
+
+### Prerequisites
+
+ * [Zato][2] 3.0+ (e.g. from [source code][5])
+ * WebSphere MQ 6.0+
+
+
+
+### Preliminary steps
+
+ * Obtain connection details and credentials to the queue manager that you will be connecting to:
+
+ * host, e.g. 10.151.13.11
+ * port, e.g. 1414
+ * channel name, e.g. DEV.SVRCONN.1
+ * queue manager name (optional)
+ * username (optional)
+ * password (optional)
+ * Install [Zato][6]
+
+ * On the same system that Zato is on, install a [WebSphere MQ Client][7] \- this is an umbrella term for a set of development headers and libraries that let applications connect to remote queue managers
+
+ * Install [PyMQI][8] \- an additional dependency implementing the low-level proprietary MQ protocol. Note that you need to use the pip command that Zato ships with:
+
+
+
+```
+# Assuming Zato is in /opt/zato/current
+zato$ cd /opt/zato/current/bin
+zato$ ./pip install pymqi
+
+```
+
+ * That is it - everything is installed and the rest is a matter of configuration
+
+
+
+### Understanding definitions, outgoing connections and channels
+
+Everything in Zato revolves around re-usability and hot-reconfiguration - each individual piece of configuration can be changed on the fly, while servers are running, without restarts.
+
+Note that the concepts below are presented in the context of WebSphere MQ but they apply to other connection types in Zato too.
+
+ * **Definitions** \- encapsulate common details that apply to other parts of configuration, e.g. a connection definition may contain remote host and port
+ * **Outgoing connections** \- objects through which data is sent to remote resources, such as MQ queues
+ * **Channels** \- objects through which data can be received, for instance, from MQ queues
+
+
+
+It is usually most convenient to configure environments during development using [web-admin GUI][9] but afterwards this can be automated with [enmasse][10], [API][11] or [command-line interface][12].
+
+Once configuration is defined, it can be used from Zato services which in turn represent APIs that Zato clients invoke. Then, external applications, such as a Django or Flask, will connect using HTTP to a Zato service which will on their behalf send messages to MQ queues.
+
+Let's use web-admin to define all the Zato objects required for MQ integrations. (Hint: web-admin by default runs on )
+
+### Definition
+
+ * Go to Connections -> Definitions -> WebSphere MQ
+ * Fill out the form and click OK
+ * Observe the 'Use JMS' checkbox - more about it later on
+
+
+
+![Screenshots][13]
+
+ * Note that a password is by default set to an unusable one (a random UUID4) so once a definition is created, click on Change password to set it to a required one
+
+
+
+![Screenshots][14]
+
+ * Click Ping to confirm that connections to the remote queue manager can be established
+
+
+
+![Screenshots][15]
+
+### Outgoing connection
+
+ * Go to Connections -> Outgoing -> WebSphere MQ
+ * Fill out the form - the connection's name is just a descriptive label
+ * Note that you do not specify a queue name here - this is because a single connection can be used with as many queues as needed
+
+
+
+![Screenshots][16]
+
+ * You can now send a test MQ message directly from web-admin after click Send a message
+
+
+
+![Screenshots][17]
+
+![Screenshots][18]
+
+### API services
+
+ * Having carried out the steps above, you can now send messages to queue managers from web-admin, which is a great way to confirm MQ-level connectivity but the crucial point of using Zato is to offer API services to client applications so let's create two services now, one for sending messages to MQ and one that will receive them.
+
+
+
+```
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+# Zato
+from zato.server.service import Service
+
+class MQSender(Service):
+ """ Sends all incoming messages as they are straight to a remote MQ queue.
+ """
+ def handle(self):
+
+ # This single line suffices
+ self.out.wmq.send(self.request.raw_request, 'customer.updates', 'CUSTOMER.1')
+```
+
+ * In practice, a service such as the one above could perform transformation on incoming messages or read its destination queue names from configuration files but it serves to illustrate the point that literally 1 line of code is needed to send MQ messages
+
+ * Let's create a channel service now - one that will act as a callback invoked for each message consumed off a queue:
+
+
+
+```
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+# Zato
+from zato.server.service import Service
+
+class MQReceiver(Service):
+ """ Invoked for each message taken from a remote MQ queue
+ """
+ def handle(self):
+ self.logger.info(self.request.raw_request)
+```
+
+But wait - if this is the service that is a callback one then how does it know which queue to get messages from?
+
+That is the key point of Zato architecture - services do not need to know it and unless you really need it, they won't ever access this information.
+
+Such configuration details are configured externally (for instance, in web-admin) and a service is just a black box that receives some input, operates on it and produces output.
+
+In fact, the very same service could be mounted not only on WebSphere MQ ones but also on REST or AMQP channels.
+
+Without further ado, let's create a channel in that case, but since this is an article about MQ, only this connection type will be shown even if the same principle applies to other channel types.
+
+### Channel
+
+ * Go to Connections -> Channels -> WebSphere MQ
+ * Fill out the form and click OK
+ * Data format may be JSON, XML or blank if no automatic de-serialization is required
+
+
+
+![Screenshots][19]
+
+After clicking OK a lightweight background task will start to listen for messages pertaining to a given queue and upon receiving any, the service configured for channel will be invoked.
+
+You can start as many channels as there are queues to consume messages from, that is, each channel = one input queue and each channel may declare a different service.
+
+### JMS Java integration
+
+In many MQ environments the majority of applications will be based on Java JMS and Zato implements the underlying wire-level MQ JMS protocol to let services integrate with such systems without any effort from a Python programmer's perspective.
+
+When creating connection definitions, merely check Use JMS and everything will be taken care of under the hood - all the necessary wire headers will be added or removed when it needs to be done.
+
+![Screenshots][20]
+
+### No restarts required
+
+It's worth to emphasize again that at no point are server restarts required to reconfigure connection details.
+
+No matter how many definitions, outgoing connections, channels there are, and no matter of what kind they are (MQ or not), changing any of them will only update that very one across the whole cluster of Zato servers without interrupting other API services running concurrently.
+
+### Configuration wrap-up
+
+ * MQ connection definitions are re-used across outgoing connections and channels
+ * Outgoing connections are used by services to send messages to queues
+ * Data from queues is read through channels that invoke user-defined services
+ * Everything is reconfigurable on the fly
+
+
+
+Let's now check how to add a REST channel for the MQSender service thus letting Django and Flask push MQ messages.
+
+### Django and Flask integration
+
+ * Any Zato-based API service can be mounted on a channel
+ * For Django and Flask, it is most convenient to mount one's services on REST channels and invoke them using the [zato-client][21] from PyPI
+ * zato-client is a set of convenience clients that lets any Python application, including ones based on Django or Flask, to invoke Zato services in just a few steps
+ * There is [a dedicated chapter][22] in documentation about Django and Flask, including a sample integration scenario
+ * It's recommended to go through the chapter step-by-step - since all Zato configuration objects share the same principles, the whole of its information applies to any sort of technology that Django or Flask may need to integrate with, including WebSphere MQ
+ * After completing that chapter, to push messages to MQ, you will only need to:
+ * Create a security definition for a new REST channel for Django or Flask
+ * Create the REST channel itself
+ * Assign a service to it (e.g. MQSender)
+ * Use a Python client from zato-client to invoke that channel from Django or Flask
+ * And that is it - no MQ programming is needed to send messages to MQ queues from any Python application :-)
+
+
+
+### Summary
+
+ * Zato lets Python programmers integrate with WebSphere MQ with little to no effort
+ * Built-in support for JMS lets one integrate with existing Java applications in a transparent manner
+ * Built-in Python clients offer trivial access to Zato-based API services from other Python applications, including Django or Flask
+
+
+
+Where to next? Start off with the [tutorial][23], then consult the [documentation][24], there is a lot of information for all types of API and integration projects, and have a look at [support options][25] in case you need absolutely any sort of assistance!
+
+--------------------------------------------------------------------------------
+
+via: https://zato.io/blog/posts/websphere-mq-python-zato.html
+
+作者:[zato][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://zato.io
+[1]:https://en.wikipedia.org/wiki/IBM_WebSphere_MQ
+[2]:https://zato.io/docs
+[3]:https://www.djangoproject.com/
+[4]:http://flask.pocoo.org/
+[5]:https://zato.io/docs/admin/guide/install/source.html
+[6]:https://zato.io/docs/admin/guide/install/index.html
+[7]:https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.0.1/com.ibm.mq.csqzaf.doc/cs10230_.htm
+[8]:https://github.com/dsuch/pymqi/
+[9]:https://zato.io/docs/web-admin/intro.html
+[10]:https://zato.io/docs/admin/guide/enmasse.html
+[11]:https://zato.io/docs/public-api/intro.html
+[12]:https://zato.io/docs/admin/cli/index.html
+[13]:https://zato.io/blog/images/wmq-python-zato/def-create.png
+[14]:https://zato.io/blog/images/wmq-python-zato/def-options.png
+[15]:https://zato.io/blog/images/wmq-python-zato/def-ping.png
+[16]:https://zato.io/blog/images/wmq-python-zato/outconn-create.png
+[17]:https://zato.io/blog/images/wmq-python-zato/outconn-options.png
+[18]:https://zato.io/blog/images/wmq-python-zato/outconn-send.png
+[19]:https://zato.io/blog/images/wmq-python-zato/channel-create.png
+[20]:https://zato.io/blog/images/wmq-python-zato/def-create-jms.png
+[21]:https://pypi.python.org/pypi/zato-client
+[22]:https://zato.io/docs/progguide/clients/django-flask.html
+[23]:https://zato.io/docs/tutorial/01.html
+[24]:https://zato.io/docs/
+[25]:https://zato.io/support.html
diff --git a/sources/tech/20180129 What Happens When You Want to Create a Special Fille with All Special Characters in Linux.md b/sources/tech/20180129 What Happens When You Want to Create a Special Fille with All Special Characters in Linux.md
new file mode 100644
index 0000000000..60e923fd46
--- /dev/null
+++ b/sources/tech/20180129 What Happens When You Want to Create a Special Fille with All Special Characters in Linux.md
@@ -0,0 +1,189 @@
+What Happens When You Want to Create a Special File with All Special Characters in Linux?
+============================================================
+
+
+
+Learn how to handle creation of a special file filled with special characters.[Used with permission][1]
+
+I recently joined Holberton School as a student, hoping to learn full-stack software development. What I did not expect was that in two weeks I would be pretty much proficient with creating shell scripts that would make my coding life easy and fast!
+
+So what is the post about? It is about a novel problem that my peers and I faced when we were asked to create a file with no regular alphabets/ numbers but instead special characters!! Just to give you a look at what kind of file name we were dealing with —
+
+### \*\\’”Holberton School”\’\\*$\?\*\*\*\*\*:)
+
+What a novel file name! Of course, this question was met with the collective groaning and long drawn sighs of all 55 (batch #5) students!
+
+
+
+Some proceeded to make their lives easier by breaking the file name into pieces on a doc file and adding in the **“\\” or “\”** in front of certain special character which kind of resulted in this format -
+
+#### \\*\\\\’\”Holberton School\”\\’\\\\*$\\?\\*\\*\\*\\*\\*:)
+
+
+
+Everyone trying to get the \\ right
+
+bamboozled? me, too! I did not want to believe that this was the only way to solve this, as I was getting frustrated with every “\\” or “\” that was required to escape and print those special characters as normal characters!
+
+If you’re new to shell scripting, here is a quick walk through on why so many “\\” , “\” were required and where.
+
+In shell scripting “ ” and ‘ ’ have special usage and once you understand and remember when and where to use them it can make your life easier!
+
+#### Double Quoting
+
+The first type of quoting we will look at is double quotes. **If you place text inside double quotes, all the special characters used by the shell lose their special meaning and are treated as ordinary characters. The exceptions are “$”, “\” (backslash), and “`” (back- quote).**This means that word-splitting, pathname expansion, tilde expansion, and brace expansion are suppressed, but parameter expansion, arithmetic expansion, and command substitution are still carried out. Using double quotes, we can cope with filenames containing embedded spaces.
+
+So this means that you can create file with names that have spaces between words — if that is your thing, but I would suggest you to not do that as it is inconvenient and rather an unpleasant experience for you to try to find that file when you need !
+
+**Quoting “THE” guide for linux I follow and read like it is the Harry Potter of the linux coding world —**
+
+Say you were the unfortunate victim of a file called two words.txt. If you tried to use this on the command line, word-splitting would cause this to be treated as two separate arguments rather than the desired single argument:
+
+**[[me@linuxbox][3] me]$ ls -l two words.txt**
+
+```
+ls: cannot access two: No such file or directory
+ls: cannot access words.txt: No such file or directory
+```
+
+By using double quotes, you can stop the word-splitting and get the desired result; further, you can even repair the damage:
+
+```
+[me@linuxbox me]$ ls -l “two words.txt”
+-rw-rw-r — 1 me me 18 2008–02–20 13:03 two words.txt
+[me@linuxbox me]$ mv “two words.txt” two_words.t
+```
+
+There! Now we don’t have to keep typing those pesky double quotes.
+
+Now, let us talk about single quotes and what is their significance in shell —
+
+#### Single Quotes
+
+Enclosing characters in single quotes (‘’’) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
+
+Yes! that got me and I was wondering how will I use it, apparently when I was googling to find and easier way to do it I stumbled across this piece of information on the internet —
+
+### Strong quoting
+
+Strong quoting is very easy to explain:
+
+Inside a single-quoted string **nothing** is interpreted, except the single-quote that closes the string.
+
+```
+echo 'Your PATH is: $PATH'
+```
+
+`$PATH` won't be expanded, it's interpreted as ordinary text because it's surrounded by strong quotes.
+
+In practice that means to produce a text like `Here's my test…` as a single-quoted string, **you have to leave and re-enter the single quoting to get the character "`'`" as literal text:**
+
+```
+# WRONG
+echo 'Here's my test...'
+```
+
+```
+# RIGHT
+echo 'Here'\''s my test...'
+```
+
+```
+# ALTERNATIVE: It's also possible to mix-and-match quotes for readability:
+echo "Here's my test"
+```
+
+Well now you’re wondering — “well that explains the quotes but what about the “\”??”
+
+So for certain characters we need a special way to escape those pesky “\” we saw in that file name.
+
+#### Escaping Characters
+
+Sometimes you only want to quote a single character. To do this, you can precede a character with a backslash, which in this context is called the _escape character_ . Often this is done inside double quotes to selectively prevent an expansion:
+
+```
+[me@linuxbox me]$ echo “The balance for user $USER is: \$5.00”
+The balance for user me is: $5.00
+```
+
+It is also common to use escaping to eliminate the special meaning of a character in a filename. For example, it is possible to use characters in filenames that normally have special meaning to the shell. These would include “$”, “!”, “&”, “ “, and others. To include a special character in a filename you can to this:
+
+```
+[me@linuxbox me]$ mv bad\&filename good_filename
+```
+
+> _**To allow a backslash character to appear, escape it by typing “\\”. Note that within single quotes, the backslash loses its special meaning and is treated as an ordinary character.**_
+
+Looking at the filename now we can understand better as to why the “\\” were used in front of all those “\”s.
+
+So, to print the file name without losing “\” and other special characters what others did was to suppress the “\” with “\\” and to print the single quotes there are a few ways you can do that.
+
+```
+1. echo $'It\'s Shell Programming' # ksh, bash, and zsh only, does not expand variables
+2. echo "It's Shell Programming" # all shells, expands variables
+3. echo 'It'\''s Shell Programming' # all shells, single quote is outside the quotes
+4\. echo 'It'"'"'s Shell Programming' # all shells, single quote is inside double quotes
+```
+
+```
+for further reading please follow this link
+```
+
+Looking at option 3, I realized this would mean that I would only need to use “\” and single quotes at certain places to be able to write the whole file without getting frustrated with “\\” placements.
+
+So with the hope in mind and lesser trial and errors I was actually able to print out the file name like this:
+
+#### ‘\*\\’\’’”Holberton School”\’\’’\\*$\?\*\*\*\*\*:)’
+
+to understand better I have added an **“a”** instead of my single quotes so that the file name and process becomes more clearer. For a better understanding, I’ll break them down into modules:
+
+
+
+#### a\*\\a \’ a”Holberton School”\a \’ a\\*$\?\*\*\*\*\*:)a
+
+#### Module 1 — a\*\\a
+
+Here the use of single quote (a) creates a safe suppression for \*\\ and as mentioned before in strong quoting, the only way we can print the ‘ is to leave and re-enter the single quoting to get the character.
+
+#### Module 2 , 4— \’
+
+The \ suppresses the single quote as a standalone module.
+
+#### Module 3 — a”Holberton School”\a
+
+Here the use of single quote (a) creates a safe suppression for double quotes and \ along with regular text.
+
+#### Module 5 — a\\*$\?\*\*\*\*\*:)a
+
+Here the use of single quote (a) creates a safe suppression for all special characters being used such as *, \, $, ?, : and ).
+
+so in the end I was able to be lazy and maintain my sanity, and got away with only using single quotes to create small modules and “\” in certain places.
+
+
+
+And, that is how I was able to get the file to work right! After a few misses, it felt amazing and it was great to learn a new way to do things!
+
+
+
+Handled that curve-ball pretty well! Hope this helps you in the future when, someday you might need to create a special file for a special reason in shell!
+
+ _**Mitali Sengupta **is a former digital marketing professional, currently enrolled as a full-stack engineering student at Holberton School. She is passionate about innovation in AI and Blockchain technologies.. You can contact Mitali on [Twitter][4], [LinkedIn][5] or [GitHub][6]._
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/what-happens-when-you-want-create-special-file-all-special-characters-linux
+
+作者:[MITALI SENGUPTA ][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/mitalisengupta
+[1]:https://www.linux.com/licenses/category/used-permission
+[2]:https://www.linux.com/files/images/special-charspng
+[3]:mailto:me@linuxbox
+[4]:https://twitter.com/aadhiBangalan
+[5]:https://www.linkedin.com/in/mitali-sengupta-auger
+[6]:https://github.com/MitaliSengupta
+[7]:http://mywiki.wooledge.org/Quotes#Examples
\ No newline at end of file
diff --git a/sources/tech/20180130 An introduction to the DomTerm terminal emulator for Linux.md b/sources/tech/20180130 An introduction to the DomTerm terminal emulator for Linux.md
new file mode 100644
index 0000000000..4553570166
--- /dev/null
+++ b/sources/tech/20180130 An introduction to the DomTerm terminal emulator for Linux.md
@@ -0,0 +1,126 @@
+An introduction to the DomTerm terminal emulator for Linux
+======
+
+
+[DomTerm][1] is a modern terminal emulator that uses a browser engine as a "GUI toolkit." This enables some neat features, such as embeddable graphics and links, HTML rich text, and foldable (show/hide) commands. Otherwise it looks and feels like a feature-full, standalone terminal emulator, with excellent xterm compatibility (including mouse handling and 24-bit color), and appropriate "chrome" (menus). In addition, there is built-in support for session management and sub-windows (as in `tmux` and `GNU screen`), basic input editing (as in `readline`), and paging (as in `less`).
+
+
+Image 1: The DomTerminal terminal emulator. View larger image.
+
+Below we'll look more at these features. We'll assume you have `domterm` installed (skip to the end of this article if you need to get and build DomTerm). First, though, here's a quick overview of the technology.
+
+### Frontend vs. backend
+
+Most of DomTerm is written in JavaScript and runs in a browser engine. This can be a desktop web browser, such as Chrome or Firefox (see image 3), or it can be an embedded browser. Using a general web browser works fine, but the user experience isn't as nice (as the menus are designed for general browsing, not for a terminal emulator), and the security model gets in the way, so using an embedded browser is nicer.
+
+The following are currently supported:
+
+ * `qtdomterm`, which uses the Qt toolkit and `QtWebEngine`
+ * An `[Electron][2]` embedding (see image 1)
+ * `atom-domterm` runs DomTerm as a package in the [Atom text editor][3] (which is also based on Electron) and integrates with the Atom pane system (see image 2)
+ * A wrapper for JavaFX's `WebEngine`, which is useful for code written in Java (see image 4)
+ * Previously, the preferred frontend used [Firefox-XUL][4], but Mozilla has since dropped XUL
+
+
+
+![DomTerm terminal panes in Atom editor][6]
+
+Image 2: DomTerm terminal panes in Atom editor. [View larger image.][7]
+
+Currently, the Electron frontend is probably the nicest option, closely followed by the Qt frontend. If you use Atom, `atom-domterm` works pretty well.
+
+The backend server is written in C. It manages pseudo terminals (PTYs) and sessions. It is also an HTTP server that provides the JavaScript and other files to the frontend. The `domterm` command starts terminal jobs and performs other requests. If there is no server running, `domterm` daemonizes itself. Communication between the backend and the server is normally done using WebSockets (with [libwebsockets][8] on the server). However, the JavaFX embedding uses neither WebSockets nor the DomTerm server; instead Java applications communicate directly using the Java-JavaScript bridge.
+
+### A solid xterm-compatible terminal emulator
+
+DomTerm looks and feels like a modern terminal emulator. It handles mouse events, 24-bit color, Unicode, double-width (CJK) characters, and input methods. DomTerm does a very good job on the [vttest testsuite][9].
+
+Unusual features include:
+
+**Show/hide buttons ("folding"):** The little triangles (seen in image 2 above) are buttons that hide/show the corresponding output. To create the buttons, just add certain [escape sequences][10] in the [prompt text][11].
+
+**Mouse-click support for`readline` and similar input editors:** If you click in the (yellow) input area, DomTerm will send the right sequence of arrow-key keystrokes to the application. (This is enabled by escape sequences in the prompt; you can also force it using Alt+Click.)
+
+**Style the terminal using CSS:** This is usually done in `~/.domterm/settings.ini`, which is automatically reloaded when saved. For example, in image 2, terminal-specific background colors were set.
+
+### A better REPL console
+
+A classic terminal emulator works on rectangular grids of character cells. This works for a REPL (command shell), but it is not ideal. Here are some DomTerm features useful for REPLs that are not typically found in terminal emulators:
+
+**A command can "print" an image, a graph, a mathematical formula, or a set of clickable links:** An application can send an escape sequence containing almost any HTML. (The HTML is scrubbed to remove JavaScript and other dangerous features.)
+
+The image 3 shows a fragment from a [`gnuplot`][12] session. Gnuplot (2.1 or later) supports `domterm` as a terminal type. Graphical output is converted to an [SVG image][13], which is then printed to the terminal. My blog post [Gnuplot display on DomTerm][14] provides more information on this.
+
+
+Image 3: Gnuplot screenshot. View larger image.
+
+The [Kawa][15] language has a library for creating and transforming [geometric picture values][16]. If you print such a picture value to a DomTerm terminal, the picture is converted to SVG and embedded in the output.
+
+
+Image 4: Computable geometry in Kawa. View larger image.
+
+**Rich text in output:** Help messages are more readable and look nicer with HTML styling. The lower pane of image 1 shows the ouput from `domterm help`. (The output is plaintext if not running under DomTerm.) Note the `PAUSED` message from the built-in pager.
+
+**Error messages can include clickable links:** DomTerm recognizes the syntax `filename:line:column:` and turns it into a link that opens the file and line in a configurable text editor. (This works for relative filenames if you use `PROMPT_COMMAND` or similar to track directories.)
+
+A compiler can detect that it is running under DomTerm and directly emit file links in an escape sequence. This is more robust than depending on DomTerm's pattern matching, as it handles spaces and other special characters, and it does not depend on directory tracking. In image 4, you can see error messages from the [Kawa compiler][15]. Hovering over the file position causes it to be underlined, and the `file:` URL shows in the `atom-domterm` message area (bottom of the window). (When not using `atom-domterm`, such messages are shown in an overlay box, as seen for the `PAUSED` message in image 1.)
+
+The action when clicking on a link is configurable. The default action for a `file:` link with a `#position` suffix is to open the file in a text editor.
+
+**Structured internal representation:** The following are all represented in the internal node structure: Commands, prompts, input lines, normal and error output, tabs, and preserving the structure if you "Save as HTML." The HTML file is compatible with XML, so you can use XML tools to search or transform the output. The command `domterm view-saved` opens a saved HTML file in a way that enables command folding (show/hide buttons are active) and reflow on window resize.
+
+**Built-in Lisp-style pretty-printing:** You can include pretty-printing directives (e.g., grouping) in the output such that line breaks are recalculated on window resize. See my article [Dynamic pretty-printing in DomTerm][17] for a deeper discussion.
+
+**Basic built-in line editing** with history (like `GNU readline`): This uses the browser's built-in editor, so it has great mouse and selection handling. You can switch between normal character-mode (most characters typed are sent directly to the process); or line-mode (regular characters are inserted while control characters cause editing actions, with Enter sending the edited line to the process). The default is automatic mode, where DomTerm switches between character-mode and line-mode depending on whether the PTY is in raw or canonical mode.
+
+**A built-in pager** (like a simplified `less`): Keyboard shortcuts will control scrolling. In "paging mode," the output pauses after each new screen (or single line, if you move forward line-by-line). The paging mode is unobtrusive and smart about user input, so you can (if you wish) run it without it interfering with interactive programs.
+
+### Multiplexing and sessions
+
+**Tabs and tiling:** Not only can you create multiple terminal tabs, you can also tile them. You can use either the mouse or a keyboard shortcut to move between panes and tabs as well as create new ones. They can be rearranged and resized with the mouse. This is implemented using the [GoldenLayout][18] JavaScript library. [Image 1][19] shows a window with two panes. The top one has two tabs, with one running [Midnight Commander][20]; the bottom pane shows `domterm help` output as HTML. However, on Atom we instead use its built-in draggable tiles and tabs; you can see this in image 2.
+
+**Detaching and reattaching to sessions:** DomTerm supports sessions arrangement, similar to `tmux` and GNU `screen`. You can even attach multiple windows or panes to the same session. This supports multi-user session sharing and remote connections. (For security, all sessions of the same server need to be able to read a Unix domain socket and a local file containing a random key. This restriction will be lifted when we have a good, safe remote-access story.)
+
+**The** **`domterm`** **command** is also like `tmux` or GNU `screen` in that has multiple options for controlling or starting a server that manages one or more sessions. The major difference is that, if it's not already running under DomTerm, the `domterm` command creates a new top-level window, rather than running in the existing terminal.
+
+The `domterm` command has a number of sub-commands, similar to `tmux` or `git`. Some sub-commands create windows or sessions. Others (such as "printing" an image) only work within an existing DomTerm session.
+
+The command `domterm browse` opens a window or pane for browsing a specified URL, such as when browsing documentation.
+
+### Getting and installing DomTerm
+
+DomTerm is available from its [GitHub repository][21]. Currently, there are no prebuilt packages, but there are [detailed instructions][22]. All prerequisites are available on Fedora 27, which makes it especially easy to build.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/introduction-domterm-terminal-emulator
+
+作者:[Per Bothner][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/perbothner
+[1]:http://domterm.org/
+[2]:https://electronjs.org/
+[3]:https://atom.io/
+[4]:https://en.wikipedia.org/wiki/XUL
+[5]:/file/385346
+[6]:https://opensource.com/sites/default/files/images/dt-atom1.png (DomTerm terminal panes in Atom editor)
+[7]:https://opensource.com/sites/default/files/images/dt-atom1.png
+[8]:https://libwebsockets.org/
+[9]:http://invisible-island.net/vttest/
+[10]:http://domterm.org/Wire-byte-protocol.html
+[11]:http://domterm.org/Shell-prompts.html
+[12]:http://www.gnuplot.info/
+[13]:https://developer.mozilla.org/en-US/docs/Web/SVG
+[14]:http://per.bothner.com/blog/2016/gnuplot-in-domterm/
+[15]:https://www.gnu.org/software/kawa/
+[16]:https://www.gnu.org/software/kawa/Composable-pictures.html
+[17]:http://per.bothner.com/blog/2017/dynamic-prettyprinting/
+[18]:https://golden-layout.com/
+[19]:https://opensource.com/sites/default/files/u128651/domterm1.png
+[20]:https://midnight-commander.org/
+[21]:https://github.com/PerBothner/DomTerm
+[22]:http://domterm.org/Downloading-and-building.html
diff --git a/sources/tech/20180130 Ansible- Making Things Happen.md b/sources/tech/20180130 Ansible- Making Things Happen.md
new file mode 100644
index 0000000000..88210cd20c
--- /dev/null
+++ b/sources/tech/20180130 Ansible- Making Things Happen.md
@@ -0,0 +1,174 @@
+Ansible: Making Things Happen
+======
+In my [last article][1], I described how to configure your server and clients so you could connect to each client from the server. Ansible is a push-based automation tool, so the connection is initiated from your "server", which is usually just a workstation or a server you ssh in to from your workstation. In this article, I explain how modules work and how you can use Ansible in ad-hoc mode from the command line.
+
+Ansible is supposed to make your job easier, so the first thing you need to learn is how to do familiar tasks. For most sysadmins, that means some simple command-line work. Ansible has a few quirks when it comes to command-line utilities, but it's worth learning the nuances, because it makes for a powerful system.
+
+### Command Module
+
+This is the safest module to execute remote commands on the client machine. As with most Ansible modules, it requires Python to be installed on the client, but that's it. When Ansible executes commands using the Command Module, it does not process those commands through the user's shell. This means some variables like $HOME are not available. It also means stream functions (redirects, pipes) don't work. If you don't need to redirect output or to reference the user's home directory as a shell variable, the Command Module is what you want to use. To invoke the Command Module in ad-hoc mode, do something like this:
+
+```
+
+ansible host_or_groupname -m command -a "whoami"
+
+```
+
+Your output should show SUCCESS for each host referenced and then return the user name that the user used to log in. You'll notice that the user is not root, unless that's the user you used to connect to the client computer.
+
+If you want to see the elevated user, you'll add another argument to the ansible command. You can add -b in order to "become" the elevated user (or the sudo user). So, if you were to run the same command as above with a "-b" flag:
+
+```
+
+ansible host_or_groupname -b -m command -a "whoami"
+
+```
+
+you should see a similar result, but the whoami results should say root instead of the user you used to connect. That flag is important to use, especially if you try to run remote commands that require root access!
+
+### Shell Module
+
+There's nothing wrong with using the Shell Module to execute remote commands. It's just important to know that since it uses the remote user's environment, if there's something goofy with the user's account, it might cause problems that the Command Module avoids. If you use the Shell Module, however, you're able to use redirects and pipes. You can use the whoami example to see the difference. This command:
+
+```
+
+ansible host_or_groupname -m command -a "whoami > myname.txt"
+
+```
+
+should result in an error about > not being a valid argument. Since the Command Module doesn't run inside any shell, it interprets the greater-than character as something you're trying to pass to the whoami command. If you use the Shell Module, however, you have no problems:
+
+```
+
+ansible host_or_groupname -m shell -a "whom > myname.txt"
+
+```
+
+This should execute and give you a SUCCESS message for each host, but there should be nothing returned as output. On the remote machine, however, there should be a file called myname.txt in the user's home directory that contains the name of the user. My personal policy is to use the Command Module whenever possible and to use the Shell Module if needed.
+
+### The Raw Module
+
+Functionally, the Raw Module works like the Shell Module. The key difference is that Ansible doesn't do any error checking, and STDERR, STDOUT and Return Code is returned. Other than that, Ansible has no idea what happens, because it just executes the command over SSH directly. So while the Shell Module will use /bin/sh by default, the Raw Module just uses whatever the user's personal default shell might be.
+
+Why would a person decide to use the Raw Module? It doesn't require Python on the remote computer—at all. Although it's true that most servers have Python installed by default, or easily could have it installed, many embedded devices don't and can't have Python installed. For most configuration management tools, not having an agent program installed means the remote device can't be managed. With Ansible, if all you have is SSH, you still can execute remote commands using the Raw Module. I've used the Raw Module to manage Bitcoin miners that have a very minimal embedded environment. It's a powerful tool, and when you need it, it's invaluable!
+
+### Copy Module
+
+Although it's certainly possible to do file and folder manipulation with the Command and Shell Modules, Ansible includes a module specifically for copying files to the server. Even though it requires learning a new syntax for copying files, I like to use it because Ansible will check to see whether a file exists, and whether it's the same file. That means it copies the file only if it needs to, saving time and bandwidth. It even will make backups of existing files! I can't tell you how many times I've used scp and sshpass in a Bash FOR loop and dumped files on servers, even if they didn't need them. Ansible makes it easy and doesn't require FOR loops and IP iterations.
+
+The syntax is a little more complicated than with Command, Shell or Raw. Thankfully, as with most things in the Ansible world, it's easy to understand—for example:
+
+```
+
+ansible host_or_groupname -b -m copy \
+ -a "src=./updated.conf dest=/etc/ntp.conf \
+ owner=root group=root mode=0644 backup=yes"
+
+```
+
+This will look in the current directory (on the Ansible server/workstation) for a file called updated.conf and then copy it to each host. On the remote system, the file will be put in /etc/ntp.conf, and if a file already exists, and it's different, the original will be backed up with a date extension. If the files are the same, Ansible won't make any changes.
+
+I tend to use the Copy Module when updating configuration files. It would be perfect for updating configuration files on Bitcoin miners, but unfortunately, the Copy Module does require that the remote machine has Python installed. Nevertheless, it's a great way to update common files on many remote machines with one simple command. It's also important to note that the Copy Module supports copying remote files to other locations on the remote filesystem using the remote_src=true directive.
+
+### File Module
+
+The File Module has a lot in common with the Copy Module, but if you try to use the File Module to copy a file, it doesn't work as expected. The File Module does all its actions on the remote machine, so src and dest are all references to the remote filesystem. The File Module often is used for creating directories, creating links or deleting remote files and folders. The following will simply create a folder named /etc/newfolder on the remote servers and set the mode:
+
+```
+
+ansible host_or_groupname -b -m file \
+ -a "path=/etc/newfolder state=directory mode=0755"
+
+```
+
+You can, of course, set the owner and group, along with a bunch of other options, which you can learn about on the Ansible doc site. I find I most often will either create a folder or symbolically link a file using the File Module. To create a symlink:
+
+```
+
+sensible host_or_groupname -b -m file \
+ -a "src=/etc/ntp.conf dest=/home/user/ntp.conf \
+ owner=user group=user state=link"
+
+```
+
+Notice that the state directive is how you inform Ansible what you actually want to do. There are several state options:
+
+* link — create symlink.
+
+* directory — create directory.
+
+* hard — create hardlink.
+
+* touch — create empty file.
+
+* absent — delete file or directory recursively.
+
+This might seem a bit complicated, especially when you easily could do the same with a Command or Shell Module command, but the clarity of using the appropriate module makes it more difficult to make mistakes. Plus, learning these commands in ad-hoc mode will make playbooks, which consist of many commands, easier to understand (I plan to cover this in my next article).
+
+### File Management
+
+Anyone who manages multiple distributions knows it can be tricky to handle the various package managers. Ansible handles this in a couple ways. There are specific modules for apt and yum, but there's also a generic module called "package" that will install on the remote computer regardless of whether it's Red Hat- or Debian/Ubuntu-based.
+
+Unfortunately, while Ansible usually can detect the type of package manager it needs to use, it doesn't have a way to fix packages with different names. One prime example is Apache. On Red Hat-based systems, the package is "httpd", but on Debian/Ubuntu systems, it's "apache2". That means some more complex things need to happen in order to install the correct package automatically. The individual modules, however, are very easy to use. I find myself just using apt or yum as appropriate, just like when I manually manage servers. Here's an apt example:
+
+```
+
+ansible host_or_groupname -b -m apt \
+ -a "update_cache=yes name=apache2 state=latest"
+
+```
+
+With this one simple line, all the host machines will run apt-get update (that's the update_cache directive at work), then install apache2's latest version including any dependencies required. Much like the File Module, the state directive has a few options:
+
+* latest — get the latest version, upgrading existing if needed.
+
+* absent — remove package if installed.
+
+* present — make sure package is installed, but don't upgrade existing.
+
+The Yum Module works similarly to the Apt Module, but I generally don't bother with the update_cache directive, because yum updates automatically. Although very similar, installing Apache on a Red Hat-based system looks like this:
+
+```
+
+ansible host_or_groupname -b -m yum \
+ -a "name=httpd state=present"
+
+```
+
+The difference with this example is that if Apache is already installed, it won't update, even if an update is available. Sometimes updating to the latest version isn't want you want, so this stops that from accidentally happening.
+
+### Just the Facts, Ma'am
+
+One frustrating thing about using Ansible in ad-hoc mode is that you don't have access to the "facts" about the remote systems. In my next article, where I plan to explore creating playbooks full of various tasks, you'll see how you can reference the facts Ansible learns about the systems. It makes Ansible far more powerful, but again, it can be utilized only in playbook mode. Nevertheless, it's possible to use ad-hoc mode to peek at the sorts information Ansible gathers. If you run the setup module, it will show you all the details from a remote system:
+
+```
+
+ansible host_or_groupname -b -m setup
+
+```
+
+That command will spew a ton of variables on your screen. You can scroll through them all to see the vast amount of information Ansible pulls from the host machines. In fact, it shows so much information, it can be overwhelming. You can filter the results:
+
+```
+
+ansible host_or_groupname -b -m setup -a "filter=*family*"
+
+```
+
+That should just return a single variable, ansible_os_family, which likely will be Debian or Red Hat. When you start building more complex Ansible setups with playbooks, it's possible to insert some logic and conditionals in order to use yum where appropriate and apt where the system is Debian-based. Really, the facts variables are incredibly useful and make building playbooks that much more exciting.
+
+But, that's for another article, because you've come to the end of the second installment. Your assignment for now is to get comfortable using Ansible in ad-hoc mode, doing one thing at a time. Most people think ad-hoc mode is just a stepping stone to more complex Ansible setups, but I disagree. The ability to configure hundreds of servers consistently and reliably with a single command is nothing to scoff at. I love making elaborate playbooks, but just as often, I'll use an ad-hoc command in a situation that used to require me to ssh in to a bunch of servers to do simple tasks. Have fun with Ansible; it just gets more interesting from here!
+
+
+--------------------------------------------------------------------------------
+
+via: http://www.linuxjournal.com/content/ansible-making-things-happen
+
+作者:[Shawn Powers][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://www.linuxjournal.com/users/shawn-powers
+[1]:http://www.linuxjournal.com/content/ansible-automation-framework-thinks-sysadmin
diff --git a/sources/tech/20180130 Create and manage MacOS LaunchAgents using Go.md b/sources/tech/20180130 Create and manage MacOS LaunchAgents using Go.md
new file mode 100644
index 0000000000..8bd6b8bf64
--- /dev/null
+++ b/sources/tech/20180130 Create and manage MacOS LaunchAgents using Go.md
@@ -0,0 +1,305 @@
+Create and manage MacOS LaunchAgents using Go
+============================================================
+
+If you have ever tried writing a daemon for MacOS you have met with `launchd`. For those that don’t have the experience, think of it as a framework for starting, stopping and managing daemons, applications, processes, and scripts. If you have any *nix experience the word daemon should not be too alien to you.
+
+For those unfamiliar, a daemon is a program running in the background without requiring user input. A typical daemon might, for instance, perform daily maintenance tasks or scan a device for malware when connected.
+
+This post is aimed at folks that know a little bit about what daemons are, what is the common way of using them and know a bit about Go. Also, if you have ever written a daemon for any other *nix system, you will have a good idea of what we are going to talk here. If you are an absolute beginner in Go or systems this might prove to be an overwhelming article. Still, feel free to give it a shot and let me know how it goes.
+
+If you ever find yourself wanting to write a MacOS daemon with Go you would like to know most of the stuff we are going to talk about in this article. Without further ado, let’s dive in.
+
+### What is `launchd` and how it works?
+
+`launchd` is a unified service-management framework, that starts, stops and manages daemons, applications, processes, and scripts in MacOS.
+
+One of its key features is that it differentiates between agents and daemons. In `launchd` land, an agent runs on behalf of the logged in user while a daemon runs on behalf of the root user or any specified user.
+
+### Defining agents and daemons
+
+An agent/daemon is defined in an XML file, which states the properties of the program that will execute, among a list of other properties. Another aspect to keep in mind is that `launchd` decides if a program will be treated as a daemon or an agent by where the program XML is located.
+
+Over at [launchd.info][3], there’s a simple table that shows where you would (or not) place your program’s XML:
+
+```
++----------------+-------------------------------+----------------------------------------------------+| Type | Location | Run on behalf of |+----------------+-------------------------------+----------------------------------------------------+| User Agents | ~/Library/LaunchAgents | Currently logged in user || Global Agents | /Library/LaunchAgents | Currently logged in user || Global Daemons | /Library/LaunchDaemons | root or the user specified with the key 'UserName' || System Agents | /System/Library/LaunchAgents | Currently logged in user || System Daemons | /System/Library/LaunchDaemons | root or the user specified with the key 'UserName' |+----------------+-------------------------------+----------------------------------------------------+
+```
+
+This means that when we set our XML file in, for example, the `/Library/LaunchAgents` path our process will be treated as a global agent. The main difference between the daemons and agents is that LaunchDaemons will run as root, and are generally background processes. On the other hand, LaunchAgents are jobs that will run as a user or in the context of userland. These may be scripts or other foreground items and they also have access to the MacOS UI (e.g. you can send notifications, control the windows, etc.)
+
+So, how do we define an agent? Let’s take a look at a simple XML file that `launchd`understands:
+
+```
+Labelcom.example.appProgram/Users/Me/Scripts/cleanup.shRunAtLoad
+```
+
+The XML is quite self-explanatory, unless it’s the first time you are seeing an XML file. The file has three main properties, with values. In fact, if you take a better look you will see the `dict` keyword which means `dictionary`. This actually means that the XML represents a key-value structure, so in Go it would look like:
+
+```
+map[string]string{ "Label": "com.example.app", "Program": "/Users/Me/Scripts/cleanup.sh", "RunAtLoad": "true",}
+```
+
+Let’s look at each of the keys:
+
+1. `Label` - The job definition or the name of the job. This is the unique identifier for the job within the `launchd` instance. Usually, the label (and hence the name) is written in [Reverse domain name notation][1].
+
+2. `Program` - This key defines what the job should start, in our case a script with the path `/Users/Me/Scripts/cleanup.sh`.
+
+3. `RunAtLoad` - This key specifies when the job should be run, in this case right after it’s loaded.
+
+As you can see, the keys used in this XML file are quite self-explanatory. This is the case for the remaining 30-40 keys that `launchd` supports. Last but not least these files although have an XML syntax, in fact, they have a `.plist` extension (which means `Property List`). Makes a lot of sense, right?
+
+### `launchd` v.s. `launchctl`
+
+Before we continue with our little exercise of creating daemons/agents with Go, let’s first see how `launchd` allows us to control these jobs. While `launchd`’s job is to boot the system and to load and maintain services, there is a different command used for jobs management - `launchctl`. With `launchd` facilitating jobs, the control of services is centralized in the `launchctl` command.
+
+`launchctl` has a long list of subcommands that we can use. For example, loading or unloading a job is done via:
+
+```
+launchctl unload/load ~/Library/LaunchAgents/com.example.app.plist
+```
+
+Or, starting/stopping a job is done via:
+
+```
+launchctl start/stop ~/Library/LaunchAgents/com.example.app.plist
+```
+
+To get any confusion out of the way, `load` and `start` are different. While `start`only starts the agent/daemon, `load` loads the job and it might also start it if the job is configured to run on load. This is achieved by setting the `RunAtLoad` property in the property list XML of the job:
+
+```
+Labelcom.example.appProgram/Users/Me/Scripts/cleanup.shRunAtLoad
+```
+
+If you would like to see what other commands `launchctl` supports, you can run`man launchctl` in your terminal and see the options in detail.
+
+### Automating with Go
+
+After getting the basics of `launchd` and `launctl` out of the way, why don’t we see how we can add an agent to any Go package? For our example, we are going to write a simple way of plugging in a `launchd` agent for any of your Go packages.
+
+As we already established before, `launchd` speaks in XML. Or, rather, it understands XML files, called _property lists_ (or `.plist`). This means, for our Go package to have an agent running on MacOS, it will need to tell `launchd` “hey, `launchd`, run this thing!”. And since `launch` speaks only in `.plist`, that means our package needs to be capable of generating XML files.
+
+### Templates in Go
+
+While one could have a hardcoded `.plist` file in their project and copy it across to the `~/Library/LaunchAgents` path, a more programmatical way to do this would be to use a template to generate these XML files. The good thing is Go’s standard library has us covered - the `text/template` package ([docs][4]) does exactly what we need.
+
+In a nutshell, `text/template` implements data-driven templates for generating textual output. Or in other words, you give it a template and a data structure, it will mash them up together and produce a nice and clean text file. Perfect.
+
+Let’s say the `.plist` we need to generate in our case is the following:
+
+```
+LabelTickerProgram/usr/local/bin/tickerStandardOutPath/tmp/ticker.out.logStandardErrorPath/tmp/ticker.err.logKeepAliveRunAtLoad
+```
+
+We want to keep it quite simple in our little exercise. It will contain only six properties: `Label`, `Program`, `StandardOutPath`, `StandardErrorPath`, `KeepAlive` and `RunAtLoad`. To generate such a XML, its template would look something like this:
+
+```
+
+
+
+
+ Label{{.Label}}
+ Program{{.Program}}
+ StandardOutPath/tmp/{{.Label}}.out.log
+ StandardErrorPath/tmp/{{.Label}}.err.log
+ KeepAlive<{{.KeepAlive}}/>
+ RunAtLoad<{{.RunAtLoad}}/>
+
+
+
+```
+
+As you can see, the difference between the two XMLs is that the second one has the double curly braces with expressions in them in places where the first XML has some sort of a value. These are called “actions”, which can be data evaluations or control structures and are delimited by “ and “. Any of the text outside actions is copied to the output untouched.
+
+### Injecting your data
+
+Now that we have our template with its glorious XML and curly braces (or actions), let’s see how we can inject our data into it. Since things are generally simple in Go, especially when it comes to its standard library, you should not worry - this will be easy!
+
+To keep thing simple, we will store the whole XML template in a plain old string. Yes, weird, I know. The best way would be to store it in a file and read it from there, or embed it in the binary itself, but in our little example let’s keep it simple:
+
+```
+// template.go
+package main
+
+func Template() string {
+ return `
+
+
+
+
+ Label{{.Label}}
+ Program{{.Program}}
+ StandardOutPath/tmp/{{.Label}}.out.log
+ StandardErrorPath/tmp/{{.Label}}.err.log
+ KeepAlive<{{.KeepAlive}}/>
+ RunAtLoad<{{.RunAtLoad}}/>
+
+
+`
+}
+
+```
+
+And the program that will use our little template function:
+
+```
+// main.gopackage mainimport ( "log" "os" "text/template")func main() { data := struct { Label string Program string KeepAlive bool RunAtLoad bool }{ Label: "ticker", Program: "/usr/local/bin/ticker", KeepAlive: true, RunAtLoad: true, } t := template.Must(template.New("launchdConfig").Parse(Template())) err := t.Execute(os.Stdout, data) if err != nil { log.Fatalf("Template generation failed: %s", err) }}
+```
+
+So, what happens there, in the `main` function? It’s actually quite simple:
+
+1. We declare a small `struct`, which has only the properties that will be needed in the template, and we immediately initialize it with the values for our program.
+
+2. We build a new template, using the `template.New` function, with the name`launchdConfig`. Then, we invoke the `Parse` function on it, which takes the XML template as an argument.
+
+3. We invoke the `template.Must` function, which takes our built template as argument. From the documentation, `template.Must` is a helper that wraps a call to a function returning `(*Template, error)` and panics if the error is non-`nil`. Actually, `template.Must` is built to, in a way, validate if the template can be understood by the `text/template` package.
+
+4. Finally, we invoke `Execute` on our built template, which takes a data structure and applies its attributes to the actions in the template. Then it sends the output to `os.Stdout`, which does the trick for our example. Of course, the output can be sent to any struct that implements the `io.Writer` interface, like a file (`os.File`).
+
+### Make and load my `.plist`
+
+Instead of sending all this nice XML to standard out, let’s throw in an open file descriptor to the `Execute` function and finally save our `.plist` file in`~/Library/LaunchAgents`. There are a couple of main points we need to change.
+
+First, getting the location of the binary. Since it’s a Go binary, and we will install it via `go install`, we can assume that the path will be at `$GOPATH/bin`. Second, since we don’t know the actual `$HOME` of the current user, we will have to get it through the environment. Both of these can be done via `os.Getenv` ([docs][5]) which takes a variable name and returns its value.
+
+```
+// main.gopackage mainimport ( "log" "os" "text/template")func main() { data := struct { Label string Program string KeepAlive bool RunAtLoad bool }{ Label: "com.ieftimov.ticker", // Reverse-DNS naming convention Program: fmt.Sprintf("%s/bin/ticker", os.Getenv("GOPATH")), KeepAlive: true, RunAtLoad: true, } plistPath := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), data.Label) f, err := os.Open(plistPath) t := template.Must(template.New("launchdConfig").Parse(Template())) err := t.Execute(f, data) if err != nil { log.Fatalf("Template generation failed: %s", err) }}
+```
+
+That’s about it. The first part, about setting the correct `Program` property, is done by concatenating the name of the program and `$GOPATH`:
+
+```
+fmt.Sprintf("%s/bin/ticker", os.Getenv("GOPATH"))// Output: /Users//go/bin/ticker
+```
+
+The second part is slightly more complex, and it’s done by concatenating three strings, the `$HOME` environment variable, the `Label` property of the program and the `/Library/LaunchAgents` string:
+
+```
+fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), data.Label)// Output: /Users//Library/LaunchAgents/com.ieftimov.ticker.plist
+```
+
+By having these two paths, opening the file and writing to it is very trivial - we open the file via `os.Open` and we pass in the `os.File` structure to `t.Execute` which writes to the file descriptor.
+
+### What about the Launch Agent?
+
+We will keep this one simple as well. Let’s throw in a command to our package, make it installable via `go install` (not that there’s much to it) and make it runnable by our `.plist` file:
+
+```
+// cmd/ticker/main.gopackage tickerimport ( "time" "fmt")func main() { for range time.Tick(30 * time.Second) { fmt.Println("tick!") }}
+```
+
+This the `ticker` program will use `time.Tick`, to execute an action every 30 seconds. Since this will be an infinite loop, `launchd` will kick off the program on boot (because `RunAtLoad` is set to `true` in the `.plist` file) and will keep it running. But, to make the program controllable from the operating system, we need to make the program react to some OS signals, like `SIGINT` or `SIGTERM`.
+
+### Understanding and handling OS signals
+
+While there’s quite a bit to be learned about OS signals, in our example we will scratch a bit off the surface. (If you know a lot about inter-process communication this might be too much of an oversimplification to you - and I apologize up front. Feel free to drop some links on the topic in the comments so others can learn more!)
+
+The best way to think about a signal is that it’s a message from the operating system or another process, to a process. It is an asynchronous notification sent to a process or to a specific thread within the same process to notify it of an event that occurred.
+
+There are quite a bit of various signals that can be sent to a process (or a thread), like `SIGKILL` (which kills a process), `SIGSTOP` (stop), `SIGTERM` (termination), `SIGILL`and so on and so forth. There’s an exhaustive list of signal types on [Wikipedia’s page][6]on signals.
+
+To get back to `launchd`, if we look at its documentation about stopping a job we will notice the following:
+
+> Stopping a job will send the signal `SIGTERM` to the process. Should this not stop the process launchd will wait `ExitTimeOut` seconds (20 seconds by default) before sending `SIGKILL`.
+
+Pretty self-explanatory, right? We need to handle one signal - `SIGTERM`. Why not `SIGKILL`? Because `SIGKILL` is a special signal that cannot be caught - it kills the process without any chance for a graceful shutdown, no questions asked. That’s why there’s a termination signal and a “kill” signal.
+
+Let’s throw in a bit of signal handling in our code, so our program knows that it needs to exit when it gets told to do so:
+
+```
+package mainimport ( "fmt" "os" "os/signal" "syscall" "time")func main() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) go func() { <-sigs os.Exit(0) }() for range time.Tick(30 * time.Second) { fmt.Println("tick!") }}
+```
+
+In the new version, the agent program has two new packages imported: `os/signal`and `syscall`. `os/signal` implements access to incoming signals, that are primarily used on Unix-like systems. Since in this article we are specifically interested in MacOS, this is exactly what we need.
+
+Package `syscall` contains an interface to the low-level operating system primitives. An important note about `syscall` is that it is locked down since Go v1.4\. This means that any code outside of the standard library that uses the `syscall` package should be migrated to use the new `golang.org/x/sys` [package][7]. Since we are using **only**the signals constants of `syscall` we can get away with this.
+
+(If you want to read more about the package lockdown, you can see [the rationale on locking it down][8] by the Go team and the new [golang.org/s/sys][9] package.)
+
+Having the basics of the packages out of the way, let’s go step by step through the new lines of code added:
+
+1. We make a buffered channel of type `os.Signal`, with a size of `1`. `os.Signal`is a type that represents an operating system signal.
+
+2. We call `signal.Notify` with the new channel as an argument, plus`syscall.SIGINT` and `syscall.SIGTERM`. This function states “when the OS sends a `SIGINT` or a `SIGTERM` signal to this program, send the signal to the channel”. This allows us to somehow handle the sent OS signal.
+
+3. The new goroutine that we spawn waits for any of the signals to arrive through the channel. Since we know that any of the signals that will arrive are about shutting down the program, after receiving any signal we use `os.Exit(0)`([docs][2]) to gracefully stop the program. One caveat here is that if we had any `defer`red calls they would not be run.
+
+Now `launchd` can run the agent program and we can `load` and `unload`, `start`and `stop` it using `launchctl`.
+
+### Putting it all together
+
+Now that we have all the pieces ready, we need to put them together to a good use. Our application will consist of two binaries - a CLI tool and an agent (daemon). Both of the programs will be stored in separate subdirectories of the `cmd` directory.
+
+The CLI tool:
+
+```
+// cmd/cli/main.gopackage mainimport ( "log" "os" "text/template")func main() { data := struct { Label string Program string KeepAlive bool RunAtLoad bool }{ Label: "com.ieftimov.ticker", // Reverse-DNS naming convention Program: fmt.Sprintf("%s/bin/ticker", os.Getenv("GOPATH")), KeepAlive: true, RunAtLoad: true, } plistPath := fmt.Sprintf("%s/Library/LaunchAgents/%s.plist", os.Getenv("HOME"), data.Label) f, err := os.Open(plistPath) t := template.Must(template.New("launchdConfig").Parse(Template())) err := t.Execute(f, data) if err != nil { log.Fatalf("Template generation failed: %s", err) }}
+```
+
+And the ticker program:
+
+```
+// cmd/ticker/main.gopackage mainimport ( "fmt" "os" "os/signal" "syscall" "time")func main() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) go func() { <-sigs os.Exit(0) }() for range time.Tick(30 * time.Second) { fmt.Println("tick!") }}
+```
+
+To install them both, we need to run `go install ./...` in the project root. The command will install all the sub-packages that are located within the project. This will leave us with two available binaries, installed in the `$GOPATH/bin` path.
+
+To install our launch agent, we need to run only the CLI tool, via the `cli` command. This will generate the `.plist` file and place it in the `~/Library/LaunchAgents`path. We don’t need to touch the `ticker` binary - that one will be managed by `launchd`.
+
+To load the newly created `.plist` file, we need to run:
+
+```
+launchctl load ~/Library/LaunchAgents/com.ieftimov.ticker.plist
+```
+
+When we run it, we will not see anything immediately, but after 30 seconds the ticker will add a `tick!` line in `/tmp/ticker.out.log`. We can `tail` the file to see the new lines being added. If we want to unload the agent, we can use:
+
+```
+launchctl unload ~/Library/LaunchAgents/com.ieftimov.ticker.plist
+```
+
+This will unload the launch agent and will stop the ticker from running. Remember the signal handling we added? This is the case where it’s being used! Also, we could have automated the (un)loading of the file via the CLI tool but for simplicity, we left it out. You can try to improve the CLI tool by making it a bit smarter with subcommands and flags, as a follow-up exercise from this tutorial.
+
+Finally, if you decide to completely delete the launch agent, you can remove the`.plist` file:
+
+```
+rm ~/Library/LaunchAgents/com.ieftimov.ticker.plist
+```
+
+### In closing
+
+As part of this (quite long!) article, we saw how we can work with `launchd` and Golang. We took a detour, like learning about `launchd` and `launchctl`, generating XML files using the `text/template` package, we took a look at OS signals and how we can gracefully shutdown a Go program by handling the `SIGINT` and `SIGTERM`signals. There was quite a bit to learn and see, but we got to the end.
+
+Of course, we only scratched the surface with this article. For example, `launchd` is quite an interesting tool. You can use it also like `crontab` because it allows running programs at explicit time/date combinations or on specific days. Or, for example, the XML template can be embedded in the program binary using tools like [`go-bindata`][10], instead of hardcoding it in a function. Also, you explore more about signals, how they work and how Go implements these low-level primitives so you can use them with ease in your programs. The options are plenty, feel free to explore!
+
+If you have found any mistakes in the article, feel free to drop a comment below - I will appreciate it a ton. I find learning through teaching (blogging) a very pleasant experience and would like to have all the details fully correct in my posts.
+
+--------------------------------------------------------------------------------
+
+作者简介:
+
+Backend engineer, interested in Ruby, Go, microservices, building resilient architectures and solving challenges at scale. I coach at Rails Girls in Amsterdam, maintain a list of small gems and often contribute to Open Source.
+This is where I write about software development, programming languages and everything else that interests me.
+
+---------------------
+
+
+via: https://ieftimov.com/create-manage-macos-launchd-agents-golang
+
+作者:[Ilija Eftimov ][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://ieftimov.com/about
+[1]:https://ieftimov.com/en.wikipedia.org/wiki/Reverse_domain_name_notation
+[2]:https://godoc.org/os#Exit
+[3]:https://launchd.info/
+[4]:https://godoc.org/text/template
+[5]:https://godoc.org/os#Getenv
+[6]:https://en.wikipedia.org/wiki/Signal_(IPC)
+[7]:https://golang.org/x/sys
+[8]:https://docs.google.com/document/d/1QXzI9I1pOfZPujQzxhyRy6EeHYTQitKKjHfpq0zpxZs/edit
+[9]:https://golang.org/x/sys
+[10]:https://github.com/jteeuwen/go-bindata
\ No newline at end of file
diff --git a/sources/tech/20180130 Graphics and music tools for game development.md b/sources/tech/20180130 Graphics and music tools for game development.md
new file mode 100644
index 0000000000..7414e89704
--- /dev/null
+++ b/sources/tech/20180130 Graphics and music tools for game development.md
@@ -0,0 +1,179 @@
+Graphics and music tools for game development
+======
+
+
+
+In early October, our club, [Geeks and Gadgets][1] from Marshall University, participated in the inaugural [Open Jam][2], a game jam that celebrated the best of open source tools. Game jams are events where participants work as teams to develop computer games for fun. Jams tend to be very short--only three days long--and very exhausting. Opensource.com [announced][3] Open Jam in late August, and more than [three dozen games][4] were entered into the competition.
+
+Our club likes to create and use open source software in our projects, so Open Jam was naturally the jam we wanted to participate in. Our submission was an experimental game called [Mark My Words][5]. We used a variety of free and open source (FOSS) tools to develop it; in this article we'll discuss some of the tools we used and potential stumbling blocks to be aware of.
+
+### Audio tools
+
+#### MilkyTracker
+
+[MilkyTracker][6] is one of the best software packages available for composing old-style video game music. It is an example of a [music tracker][7], a powerful MOD and XM file creator with a characteristic grid-based pattern editor. We used it to compose most of the musical pieces in our game. One of the great things about this program is that it consumed much less disk space and RAM than most of our other tools. Even so, MilkyTracker is still extremely powerful.
+
+
+
+The user interface took a while to get used to, so here are some pointers for any musician who wants to try out MilkyTracker:
+
+ * Go to Config > Misc. and set the edit mode control style to "MilkyTracker." This will give you modern keyboard shortcuts for almost everything
+ * Undo with Ctrl+Z
+ * Redo with Ctrl+Y
+ * Toggle pattern-edit mode with the Spacebar
+ * Delete the previous note with the Backspace key
+ * Insert a row with the Insert key
+ * By default, a note will continue playing until it is replaced on that channel. You can end a note explicitly by inserting a KeyOff note with the backquote (`) key
+ * You will have to create or find samples before you can start composing. We recommend finding [Creative Commons][8] licensed samples at websites such as [Freesound][9] or [ccMixter][10]
+
+
+
+In addition, keep the [MilkyTracker documentation page][11] handy. It contains links to numerous tutorials and manuals. A good starting point is the [MilkyTracker Guide][12] on the project's wiki.
+
+#### LMMS
+
+Two of our musicians used the versatile and modern music creation tool [LMMS][13]. It comes with a library of cool samples and effects, plus a variety of flexible plugins for generating unique sounds. The learning curve for LMMS was surprisingly low, in part due to the nice beat/bassline editor.
+
+
+
+We have one suggestion for musicians trying out LMMS: Use the plugins. For [chiptune][14]-style music, we recommend [sfxr][15], [BitInvader][16], and [FreeBoy][17]. For other styles, [ZynAddSubFX][18] is a good choice. It comes with a wide range of synthesized instruments that can be altered however you see fit.
+
+### Graphics tools
+
+#### Tiled
+
+[Tiled][19] is a popular tilemap editor in open source game development. We used it to assemble consistent, retro-looking backgrounds for our in-game scenes.
+
+
+
+Tiled can export maps as XML, JSON, or as flattened images. It is stable and cross-platform.
+
+One of Tiled's features, which we did not use during the jam, allows you to define and place arbitrary game objects, such as coins and powerups, onto the map. All you have to do is load the object's graphics as a tileset, then place them using Insert Tile.
+
+Overall, Tiled is a stellar piece of software that we recommend for any project that needs a map editor.
+
+#### Piskel
+
+[Piskel][20] is a pixel art editor whose source code is licensed under the [Apache License, Version 2.0][21]. We used Piskel for almost all our graphical assets during the jam, and we will certainly be using it in future projects as well.
+
+Two features of Piskel that helped us immensely during the jam are onion skin and spritesheet exporting.
+
+##### Onion skin
+
+The onion skin feature will make Piskel show a ghostly overlay of the previous and next frames of your animation as you edit, like this:
+
+
+
+Onion skin is handy because it serves as a drawing guide and helps you maintain consistent shapes and volumes on your characters throughout the animation process. To enable it, just click the onion-shaped icon underneath the preview window on the top-right of the screen.
+
+
+
+##### Spritesheet exporting
+
+Piskel's ability to export animations as a spritesheet was also very helpful. A spritesheet is a single raster image that contains all the frames of an animation. For example, here is a spritesheet we exported from Piskel:
+
+
+
+The spritesheet consists of two frames. One frame is in the top half of the image and the other frame is in the bottom half of the image. Spritesheets greatly simplify a game's code by enabling an entire animation to be loaded from a single file. Here is an animated version of the above spritesheet:
+
+
+
+##### Unpiskel.py
+
+There were several times during the jam when we wanted to batch convert Piskel files into PNGs. Since the Piskel file format is based on JSON, we wrote a small GPLv3-licensed Python script called [unpiskel.py][22] to do the conversion.
+
+It is invoked like this:
+```
+
+
+python unpiskel.py input.piskel
+```
+
+The script will extract the PNG data frames and layers from a Piskel file (here `input.piskel`) and store them in their own files. The files follow the pattern `NAME_XX_YY.png` where `NAME` is the truncated name of the Piskel file, `XX` is the frame number, and `YY` is the layer number.
+
+Because the script can be invoked from a shell, it can be used on a whole list of files.
+```
+for f in *.piskel; do python unpiskel.py "$f"; done
+```
+
+### Python, Pygame, and cx_Freeze
+
+#### Python and Pygame
+
+We used the [Python][23] language to make our game. It is a scripting language that is commonly used for text processing and desktop app development. It can also be used for game development, as projects like [Angry Drunken Dwarves][24] and [Ren'Py][25] have shown. Both of these projects use a Python library called [Pygame][26] to display graphics and produce sound, so we decided to use this library in Open Jam, too.
+
+Pygame turned out to be both stable and featureful, and it was great for the arcade-style game we were creating. The library's speed was fast enough at low resolutions, but its CPU-only rendering starts to slow down at higher resolutions. This is because Pygame does not use hardware-accelerated rendering. However, the infrastructure is there for developers to take full advantage of OpenGL.
+
+If you're looking for a good 2D game programming library, Pygame is one to keep your eye on. Its website has [a good tutorial][27] to get started. Be sure to check it out!
+
+#### cx_Freeze
+
+Prepping our game for distribution was interesting. We knew that Windows users were unlikely to have a Python installation, and asking them to install it would have been too much. On top of that, they would have had to also install Pygame, which is not an intuitive task on Windows.
+
+One thing was clear: We had to put our game into a more convenient form. Many of the other Open Jam participants used the proprietary game engine Unity, which enabled their games to be played in the web browser. This made them extremely convenient to play. Convenience was one thing our game didn't have even a sliver of. But, thanks to a vibrant Python ecosystem, we had options. Tools exist to help Python programmers prepare their programs for distribution on Windows. The two that we considered were [cx_Freeze][28] and [Pygame2exe][29] (which uses [py2exe][30]). We decided on cx_Freeze because it was cross-platform.
+
+In cx_Freeze, you can pack a single-script game for distribution just by running a command like this in the shell:
+```
+cxfreeze main.py --target-dir dist
+```
+
+This invocation of `cxfreeze` will take your script (here `main.py`) and the Python interpreter on your system and bundle them up into the `dist` directory. Once this is done, all you have to do is manually copy your game's data files into the `dist` directory. You will find that the `dist` directory contains an executable file that can be run to start your game.
+
+There is a more involved way to use cx_Freeze that allows you to automate the copying of data files, but we found the straightforward invocation of `cxfreeze` to be good enough for our needs. Thanks to this tool, we made our game a little more convenient to play.
+
+### Celebrating open source
+
+Open Jam is important because it celebrates the open source model of software development. This is an opportunity to analyze the current state of open source tools and what we need to work on in the future. Game jams are perhaps the best time for game devs to try to push their tools to the limit, to learn what must be improved for the good of future game devs.
+
+Open source tools enable people to explore their creativity without compromising their freedom and without investing money upfront. Although we might not become professional game developers, we were still able to get a small taste of it with our short, experimental game called [Mark My Words][5]. It is a linguistically themed game that depicts the evolution of a fictional writing system throughout its history. There were many other delightful submissions to Open Jam, and they are all worth checking out. Really, [go look][31]!
+
+Before closing, we would like to thank all the [club members who participated][32] and made this experience truly worthwhile. We would also like to thank [Michael Clayton][33], [Jared Sprague][34], and [Opensource.com][35] for hosting Open Jam. It was a blast.
+
+Now, we have some questions for readers. Are you a FOSS game developer? What are your tools of choice? Be sure to leave a comment below!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/graphics-music-tools-game-dev
+
+作者:[Charlie Murphy][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/rsg167
+[1]:http://mugeeks.org/
+[2]:https://itch.io/jam/open-jam-1
+[3]:https://opensource.com/article/17/8/open-jam-announcement
+[4]:https://opensource.com/article/17/11/open-jam
+[5]:https://mugeeksalpha.itch.io/mark-omy-words
+[6]:http://milkytracker.titandemo.org/
+[7]:https://en.wikipedia.org/wiki/Music_tracker
+[8]:https://creativecommons.org/
+[9]:https://freesound.org/
+[10]:http://ccmixter.org/view/media/home
+[11]:http://milkytracker.titandemo.org/documentation/
+[12]:https://github.com/milkytracker/MilkyTracker/wiki/MilkyTracker-Guide
+[13]:https://lmms.io/
+[14]:https://en.wikipedia.org/wiki/Chiptune
+[15]:https://github.com/grimfang4/sfxr
+[16]:https://lmms.io/wiki/index.php?title=BitInvader
+[17]:https://lmms.io/wiki/index.php?title=FreeBoy
+[18]:http://zynaddsubfx.sourceforge.net/
+[19]:http://www.mapeditor.org/
+[20]:https://www.piskelapp.com/
+[21]:https://github.com/piskelapp/piskel/blob/master/LICENSE
+[22]:https://raw.githubusercontent.com/MUGeeksandGadgets/MarkMyWords/master/tools/unpiskel.py
+[23]:https://www.python.org/
+[24]:https://www.sacredchao.net/~piman/angrydd/
+[25]:https://renpy.org/
+[26]:https://www.Pygame.org/
+[27]:http://Pygame.org/docs/tut/PygameIntro.html
+[28]:https://anthony-tuininga.github.io/cx_Freeze/
+[29]:https://Pygame.org/wiki/Pygame2exe
+[30]:http://www.py2exe.org/
+[31]:https://itch.io/jam/open-jam-1/entries
+[32]:https://github.com/MUGeeksandGadgets/MarkMyWords/blob/3e1e8aed12ebe13acccf0d87b06d4f3bd124b9db/README.md#credits
+[33]:https://twitter.com/mwcz
+[34]:https://twitter.com/caramelcode
+[35]:https://opensource.com/
diff --git a/sources/tech/20180130 Install AWFFull web server log analysis application on ubuntu 17.10.md b/sources/tech/20180130 Install AWFFull web server log analysis application on ubuntu 17.10.md
new file mode 100644
index 0000000000..03e15878b9
--- /dev/null
+++ b/sources/tech/20180130 Install AWFFull web server log analysis application on ubuntu 17.10.md
@@ -0,0 +1,95 @@
+Install AWFFull web server log analysis application on ubuntu 17.10
+======
+
+
+AWFFull is a web server log analysis program based on "The Webalizer".AWFFull produces usage statistics in HTML format for viewing with a browser. The results are presented in both columnar and graphical format, which facilitates interpretation. Yearly, monthly, daily and hourly usage statistics are presented, along with the ability to display usage by site, URL, referrer, user agent (browser), user name,search strings, entry/exit pages, and country (some information may not be available if not present in the log file being processed).
+
+
+
+AWFFull supports CLF (common log format) log files, as well as Combined log formats as defined by NCSA and others, and variations of these which it attempts to handle intelligently. In addition, AWFFull also supports wu-ftpd xferlog formatted log files, allowing analysis of ftp servers, and squid proxy logs. Logs may also be compressed, via gzip.
+
+AWFFull is a web server log analysis program based on "The Webalizer".AWFFull produces usage statistics in HTML format for viewing with a browser. The results are presented in both columnar and graphical format, which facilitates interpretation. Yearly, monthly, daily and hourly usage statistics are presented, along with the ability to display usage by site, URL, referrer, user agent (browser), user name,search strings, entry/exit pages, and country (some information may not be available if not present in the log file being processed).AWFFull supports CLF (common log format) log files, as well as Combined log formats as defined by NCSA and others, and variations of these which it attempts to handle intelligently. In addition, AWFFull also supports wu-ftpd xferlog formatted log files, allowing analysis of ftp servers, and squid proxy logs. Logs may also be compressed, via gzip.
+
+If a compressed log file is detected, it will be automatically uncompressed while it is read. Compressed logs must have the standard gzip extension of .gz.
+
+### Changes from Webalizer
+
+AWFFull is based on the Webalizer code and has a number of large and small changes. These include:
+
+o Beyond the raw statistics: Making use of published formulae to provide additional insights into site usage.
+
+o GeoIP IP Address look-ups for more accurate country detection.
+
+o Resizable graphs.
+
+o Integration with GNU gettext allowing for ease of translations.Currently 32 languages are supported.
+
+o Display more than 12 months of the site history on the front page.
+
+o Additional page count tracking and sort by same.
+
+o Some minor visual tweaks, including Geolizer's use of Kb, Mb etc for Volumes.
+
+o Additional Pie Charts for URL counts, Entry and Exit Pages, and Sites.
+
+o Horizontal lines on graphs that are more sensible and easier to read.
+
+o User Agent and Referral tracking is now calculated via PAGES not HITS.
+
+o GNU style long command line options are now supported (eg --help).
+
+o Can choose what is a page by excluding "what isn't" vs the original "what is" method.
+
+o Requests to the site being analysed are displayed with the matching referring URL.
+
+o A Table of 404 Errors, and the referring URL can be generated.
+
+o An external CSS file can be used with the generated html.
+
+o Manual performance optimisation of the config file is now easier with a post analysis summary output.
+
+o Specified IP's & Addresses can be assigned to a given country.
+
+o Additional Dump options for detailed analysis with other tools.
+
+o Lotus Domino v6 logs are now detected and processed.
+
+**Install awffull on ubuntu 17.10**
+
+> sudo apt-get install awffull
+
+### Configuring AWFFULL
+
+You have to edit awffull config file at /etc/awffull/awffull.conf. If you have multiple virtual websites running in the same machine, you can make several copies of the default config file.
+
+> sudo vi /etc/awffull/awffull.conf
+
+Make sure the following lines are there
+
+> LogFile /var/log/apache2/access.log.1
+> OutputDir /var/www/html/awffull
+
+Save and exit the file
+
+You can run the awffull config using the following command
+
+> awffull -c [your config file name]
+
+This will create all the required files under /var/www/html/awffull directory so you can access your webserver stats using http://serverip/awffull/
+
+You should see similar to the following screen
+
+If you have more site and you can automate the process using shell script and cron job.
+
+
+--------------------------------------------------------------------------------
+
+via: http://www.ubuntugeek.com/install-awffull-web-server-log-analysis-application-on-ubuntu-17-10.html
+
+作者:[ruchi][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://www.ubuntugeek.com/author/ubuntufix
diff --git a/sources/tech/20180130 Introduction to AWS for Data Scientists.md b/sources/tech/20180130 Introduction to AWS for Data Scientists.md
new file mode 100644
index 0000000000..ada3585745
--- /dev/null
+++ b/sources/tech/20180130 Introduction to AWS for Data Scientists.md
@@ -0,0 +1,212 @@
+Introduction to AWS for Data Scientists
+======
+![sky-690293_1920][1]
+
+These days, many businesses use cloud based services; as a result various companies have started building and providing such services. Amazon [began the trend][2], with Amazon Web Services (AWS). While AWS began in 2006 as a side business, it now makes [$14.5 billion in revenue each year][3].
+
+Other leaders in this area include:
+
+ * Google--Google Cloud Platform (GCP)
+ * Microsoft--Azure Cloud Services
+ * IBM--IBM Cloud
+
+
+
+Cloud services are useful to businesses of all sizes--small companies benefit from the low cost, as compared to buying servers. Larger companies gain reliability and productivity, with less cost, since the services run on optimum energy and maintenance.
+
+These services are also powerful tools that you can use to ease your work. Setting up a Hadoop cluster to work with Spark manually could take days if it's your first time, but AWS sets that up for you in minutes.
+
+We are going to focus on AWS here because it comes with more products relevant to data scientists. In general, we can say familiarity with AWS helps data scientists to:
+
+ 1. Prepare the infrastructure they need for their work (e.g. Hadoop clusters) with ease
+ 2. Easily set up necessary tools (e.g. Spark)
+ 3. Decrease expenses significantly--such as by paying for huge Hadoop clusters only when needed
+ 4. Spend less time on maintenance, as there's no need for tasks like manually backing up data
+ 5. Develop products and features that are ready to launch without needing help from engineers (or, at least, needing very little help)
+
+
+
+In this post, I'll give an overview of useful AWS services for data scientists -- what they are, why they're useful, and how much they cost.
+
+### Elastic Compute Cloud (EC2)
+
+Many other AWS services are built around EC2, making it a core piece of AWS. EC2s are in fact (virtual) servers that you can rent from Amazon and set up or run any program/application on it. These servers come in different operating systems and Amazon charges you based on the computing power and capacity of the server (i.e. Hard Drive capacity, CPU, Memory, etc.) and the duration the server been up.
+
+#### EC2 benefits
+
+For example, you can rent a Linux or Windows server with computation power and storage capacity that fits your specific needs and Amazon charges you based on these specifications and the duration you use the server. Note that previously AWS charged at least for one hour for each instance you run, but they recently changed their policy to [per-second billing][4].
+
+One of the good things about EC2 is its scalability--by changing memory, number of vCPUs, bandwidth, and so on, you can easily scale your system up or down. Therefore, if you think a system doesn't have enough power for running a specific task or a calculation in your project is taking too long, you can scale up to finish your work and later scale down again to reduce the cost. EC2 is also very reliable, since Amazon takes care of the maintenance.
+
+#### EC2 cost
+
+EC2 instances are relatively low-cost, and there are different types of instances for different use cases. For example, there are instances that are optimized for computation and those have relatively lower cost on CPU usage. Or those optimized for memory have lower cost on memory usage.
+
+To give you an idea on EC2 cost, a general purpose medium instance with 2 vCPUs and 4 GIG of memory (at the time of writing this article) costs $0.0464 per hour for a linux server, see [Amazon EC2 Pricing][5] for prices and more information. AWS also now has [spot instance pricing][6], which calculates the price based on supply/demand at the time and provides up to a 90% discount for short term usages depending on the time you want to use the instance. For example, the same instance above costs $0.0173 per hour on spot pricing plan.
+
+Note that you have to add storage costs to the above as well. Most EC2 instances use Elastic Block Store (EBS) systems, which cost around $0.1/GIG/month; see the prices [here][7]. [Storage optimized instances][8] use Solid State Drive (SSD) systems, which are more expensive.
+
+![Ec2cost][9]
+
+EBS acts like an external hard drive. You can attach it to an instance, de-attach it, and re-attach it to another instance. You can also stop or terminate an instance after your work is done and not pay for the instance when it is idle.
+
+If you stop an instance, AWS will still keep the EBS live and as a result the data you have on the hard drive will remain intact (it's like powering off your computer). Later you can restart stopped instances and get access to the data you generated, or even tools you installed there in the previous sessions. However, when you stop an instance instead of terminating it, Amazon will still charge you for the attached EBS (~$0.1/GIG/month). If you terminate the instance, the EBS will get cleaned so you will lose all the data on that instance, but you no longer need to pay for the EBS.
+
+If you need to keep the data on EBS for your future use (let's say you have custom tools installed on that instance and you don't want to redo your work again later) you can make a snapshot of the EBS and can later restore it in a new EBS and attach it to a new instance.
+
+Snapshots get stored on S3 (Amazon's cheap storage system; we will get to it later) so it will cost you less ($0.05 per GB-month) to keep the data in EBS like that. However, it takes time (depending on the size of the EBS) to get snapshot and restoring it. Besides, reattaching a restored EBS to EC2 instance is not that straight forward, so it only make sense to use a snapshot like that if you know you are not going to use that EBS for a while.
+
+Note that to scale an instance up or down, you have to first stop the instance and then change the instance specifications. You can't decrease the EBS size, only increase it, and it's more difficult. You have to:
+
+ 1. Stop the instance
+ 2. Make a snapshot out of the EBS
+ 3. Restore the snapshot in an EBS with the new size
+ 4. De-attach previous EBS
+ 5. Attach the new one.
+
+
+
+### Simple Storage Service (S3)
+
+S3 is AWS object (file) storage service. S3 is like Dropbox or Google drive, but way more scalable and is made particularly to work with codes and applications.
+
+S3 doesn't provide a user friendly interface since it is designed to work with online applications, not the end user. Therefore, working with S3 through APIs is easier than through its web console and there are many libraries and APIs developed (in various languages) to work with this service. For example, [Boto3][10] is a S3 library written in Python (in fact Boto3 is suitable for working with many other AWS services as well) .
+
+S3 stores files based on `bucket`s and `key`s. Buckets are similar to root folders, and keys are similar to subfolders and files. So if you store a file named `my_file.txt` on s3 like `myproject/mytextfiles/my_file.txt`, then "myproject" is the bucket you are using and then `mytextfiles/my_file.txt` is the key to that file. This is important to know since APIs will ask for the bucket and key separately when you want to retrieve your file from s3.
+
+#### S3 benefits
+
+There is no limit on the size of data you can store on S3--you just have to pay for the storage based on the size you need per month.
+
+S3 is also very reliable and "[it is designed to deliver 99.999999999% durability][11]". However, the service may not be always up. On February 28th, 2017 some of s3 servers went down for couple of hours and that disrupted many applications such as Slack, Trello, etc. see [these][12] [articles][13] for more information on this incident.
+
+#### S3 cost
+
+The cost is low, starting at $0.023 per GB per month for standard access, if you want to get access to these files regularly. It could go down even lower if you don't need to load data too frequently. See [Amazon S3 Pricing][14] for more information.
+
+AWS may charge you for other S3 related actions such as requests through APIs, but the cost for those are insignificant (less than $0.05 per 1,000 requests in most cases).
+
+### Relational Database Service (RDS)
+
+AWS RDS is a relational database service in the cloud. RDS currently supports SQL Server, MySQL, PostgreSQL, ORACLE, and a couple of other SQL-based frameworks. AWS sets up the system you need and configures the parameters so you can have a relational database up and running in minutes. RDS also handles backup, recovery, software patching, failure detection, and repairs by itself so you don't need to maintain the system.
+
+#### RDS benefits
+
+RDS is scalable, both computing power and the storage capacity can be scaled up or down easily. RDS system runs on EC2 servers (as I mentioned EC2 servers are the core of most of AWS services, including RDS service) so by computing power here we mean the computing power of the EC2 server our RDS service is running on, and you can scale up the computing power of this system up to 32 vCPUs and 244 GiB of RAM and changing the scale would not take more than few minutes.
+
+Scaling the storage requirements up or down is also possible. [Amazon Aurora][15] is a version of MySQL and PostgreSQL with some additional features, and can automatically scale up when more storage space is needed (you can define the maximum). The MySQL, MariaDB, Oracle, and PostgreSQL engines allow you to scale up on the fly without downtime.
+
+#### RDS cost
+
+The [cost of RDS servers][16] is based on three factors: computational power, storage, and data transfer.
+
+![RDSpricing][17]
+
+For example, a PostgreSQL system with medium computational power (2 vCPUs and 8 gig of memory) costs $0.182 per hour; you can pay less if you go under a one- or three-year contract.
+
+For storage, there are a [variety of options and prices][18]. If you choose single availability zone General Purpose SSD Storage (gp2), a good option for data scientists, the cost for a server in north Virginia at the time of writing this article is $0.115 per GB-month, and you can select from 5 GB to 16 TB of SSD.
+
+For data transfer, the cost varies a little based on the source and destination of data (one of which is RDS). For example, all data transferred from the internet into RDS is free. The first gig of data transferred from RDS to the internet is free as well, and for the next 10 terabytes of data in a month it costs $0.09 per GB; the cost decreases for transfering more data than that.
+
+### Redshift
+
+Redshift is Amazon's data warehouse service; it is a distributed system (something like the Hadoop framework) which lets you store huge amounts of data and get queries. The difference between this service and RDS is its high capacity and ability to work with big data (terabytes and petabytes). You can use simple SQL queries on Redshift as well.
+
+Redshift works on a distributed framework--data is distributed on different nodes (servers) connected on a cluster. Simply put, queries on a distributed system run in parallel on all the nodes and then the results get collected from each node and get summarized.
+
+#### Redshift benefits
+
+Redshift is highly scalable, meaning in theory (depending on the query, network structure and design, service specification, etc.) the speed of getting query out of 1 terabyte of data and 1 petabyte of data can match by scaling up (adding more cluster to) the system.
+
+When you create a table on Redshift, you can choose one of three distribution styles: EVEN, KEY, or ALL.
+
+ * EVEN means the table rows will get distributed over all the nodes evenly. Then queries involving that table get distributed over the cluster and run in parallel, summarized at the end. Per Amazon's documentation, "[EVEN distribution is appropriate when a table does not participate in joins][19]".
+
+ * ALL means that on each node there will be a copy of this table, so if you query for a join on that table, the table is already there on all the nodes and there is no need for copying the required data across the network from node to node. The problem is "[ALL distribution multiplies the storage required by the number of nodes in the cluster, and so it takes much longer to load, update, or insert data into multiple tables][19]".
+
+ * In the KEY style, distribution rows of the table are distributed based on the values in one column, in an attempt to keep the rows with the same value of that column in the same node. Physically storing matching values on the same nodes make joining on that specific column faster in parallel systems, see more information [here][19].
+
+
+
+
+#### Redshift cost
+
+Redshift has two types of instances: Dense Compute or Dense Storage. Dense Compute is optimized for fast querying and it is cost effective for less than 500GB of data in size (~$5,500/TB/Year for a three-year contract with partial upfront).
+
+Dense Storage is optimized for high size storage (~$1,000/TB/Year for a three-year contract with partial upfront) and is cost effective for +500GB, but it is slower. You can find more general pricing [here][20].
+
+You can also save a large amount of data on S3 and use [Amazon Redshift Spectrum][21] to run SQL query on that data. For Redshift Spectrum, AWS charges you by the number of bytes scanned by Redshift Spectrum per query; and $5 per terabyte of data scanned (10 megabyte minimum per query).
+
+### Elastic MapReduce (EMR)
+
+EMR is suitable for setting up Hadoop clusters with Spark and other distributed type applications. A Hadoop cluster can be used as a compute engine or a (distributed) storage system. However, if the data is so big that you need a distributed system to handle it, Redshift is more suitable and way cheaper than storing in EMR.
+
+There are three types of [nodes][22] on a cluster:
+
+ * The master node (you only have one) is responsible for managing the cluster. It distributes the workloads to the core and task nodes, tracks the status of tasks, and monitors the health of the cluster.
+ * Core nodes run tasks and store the data.
+ * Task nodes can only run tasks.
+
+
+
+#### EMR benefits
+
+Since you can set EMR to install Apache Spark, this service is good for for cleaning, reformatting, and analyzing big data. You can use EMR on-demand, meaning you can set it to grab the code and data from a source (e.g. S3 for the code, and S3 or RDS for the data), run the task on the cluster, and store the results somewhere (again s3, RDS, or Redshift) and terminate the cluster.
+
+By using the service in such a way, you can reduce the cost of your cluster significantly. In my opinion, EMR is one of the most useful AWS services for data scientists.
+
+To setup an EMR cluster, you need to first configure applications you want to have on the cluster. Note that different versions of EMR come with different versions of the applications. For example, if you configure EMR version 5.10.0 to install Spark, the default version of the Spark for this version is 2.2.0. So if your code works only on Spark 1.6, you need to run EMR on the 4.x version. EMR will set up the network and configures all the nodes on the cluster along with needed tools.
+
+An EMR cluster comes with one master instance and a number of core nodes (slave instances). You can choose the number of core nodes, and can even select to have no core node and only use the master server for your work. Like other services, you can choose the computational power of the servers and the storage size available on each node. You can use autoscale option for your core nodes, meaning you can add rules to the system to add/remove core node (up to a maximum number you choose) if needed while running your code. See [Using Automatic Scaling in Amazon EMR][23] for more information on auto scaling.
+
+#### EMR pricing
+
+EMR pricing is based on the computational power you choose for different instances (master, core and task nodes). Basically, it is the cost of the EC2 servers plus the cost of EMR. You can find detailed pricing [here][24].
+
+![EMRpricing][25]
+
+### Conclusion
+
+I have developed many end-to-end data-driven products (including reporting, machine learning models, and product health checking systems) for our company using Python and Spark on AWS, which later became good sources of income for the company.
+
+Experience working with cloud services, especially a well-known one like AWS, is a huge plus in your data scientist career. Many companies depend on these services now and use them constantly, so you being familiar with these services will give them the confidence that you need less training to get on board. With more and more people moving into data science, you want your resume to stand out as much as possible.
+
+Do you have cloud tips to add? [Let us know][26].
+
+--------------------------------------------------------------------------------
+
+via: https://www.dataquest.io/blog/introduction-to-aws-for-data-scientists/
+
+作者:[Read More][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.dataquest.io/blog/author/armin/
+[1]:/blog/content/images/2018/01/sky-690293_1920.jpg
+[2]:http://www.computerweekly.com/feature/A-history-of-cloud-computing
+[3]:https://www.forbes.com/sites/bobevans1/2017/07/28/ibm-beats-amazon-in-12-month-cloud-revenue-15-1-billion-to-14-5-billion/#53c3e14c39d6
+[4]:https://aws.amazon.com/blogs/aws/new-per-second-billing-for-ec2-instances-and-ebs-volumes/
+[5]:https://aws.amazon.com/ec2/pricing/on-demand/
+[6]:https://aws.amazon.com/ec2/spot/pricing/
+[7]:https://aws.amazon.com/ebs/pricing/
+[8]:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/storage-optimized-instances.html
+[9]:/blog/content/images/2018/01/Ec2cost.png
+[10]:https://boto3.readthedocs.io
+[11]:https://aws.amazon.com/s3/
+[12]:https://aws.amazon.com/message/41926/
+[13]:https://venturebeat.com/2017/02/28/aws-is-investigating-s3-issues-affecting-quora-slack-trello/
+[14]:https://aws.amazon.com/s3/pricing/
+[15]:https://aws.amazon.com/rds/aurora/
+[16]:https://aws.amazon.com/rds/postgresql/pricing/
+[17]:/blog/content/images/2018/01/RDSpricing.png
+[18]:https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html
+[19]:http://docs.aws.amazon.com/redshift/latest/dg/c_choosing_dist_sort.html
+[20]:https://aws.amazon.com/redshift/pricing/
+[21]:https://aws.amazon.com/redshift/spectrum/
+[22]:http://docs.aws.amazon.com/emr/latest/DeveloperGuide/emr-nodes.html
+[23]:https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-automatic-scaling.html
+[24]:https://aws.amazon.com/emr/pricing/
+[25]:/blog/content/images/2018/01/EMRpricing.png
+[26]:https://twitter.com/dataquestio
diff --git a/sources/tech/20180130 Linux Kernel 4.15 An Unusual Release Cycle.md b/sources/tech/20180130 Linux Kernel 4.15 An Unusual Release Cycle.md
new file mode 100644
index 0000000000..062cd3c3ca
--- /dev/null
+++ b/sources/tech/20180130 Linux Kernel 4.15 An Unusual Release Cycle.md
@@ -0,0 +1,62 @@
+Linux Kernel 4.15: 'An Unusual Release Cycle'
+============================================================
+
+
+
+Linus Torvalds released version 4.15 of the Linux Kernel on Sunday, a week later than originally scheduled. Learn about key updates in this latest release.[Creative Commons Zero][1]Pixabay
+
+Linus Torvalds [released version 4.15 of the Linux Kernel][7] on Sunday, again, and for a second version in a row, a week later than scheduled. The culprits for the late release were the Meltdown and Spectre bugs, as these two vulnerabilities forced developers to submit major patches well into what should have been the last cycle. Torvalds was not comfortable rushing the release, so he gave it another week.
+
+Unsurprisingly, the first big bunch of patches worth mentioning were those designed to sidestep [Meltdown and Spectre][8]. To avoid Meltdown, a problem that affects Intel chips, [developers have implemented _Page Table Isolation_ (PTI)][9] for the x86 architecture. If for any reason you want to turn this off, you can use the `pti=off` kernel boot option.
+
+Spectre v2 affects both Intel and AMD chips and, to avoid it, [the kernel now comes with the _retpoline_ mechanism][10]. Retpoline requires a version of GCC that supports the `-mindirect-branch=thunk-extern` functionality. As with PTI, the Spectre-inhibiting mechanism can be turned of. To do so, use the `spectre_v2=off` option at boot time. Although developers are working to address Spectre v1, at the moment of writing there is still not a solution, so there is no patch for this bug in 4.15.
+
+The solution for Meltdown on ARM has also been pushed to the next development cycle, but there is [a remedy for the bug on PowerPC with the _RFI flush of L1-D cache_ feature][11] included in this release.
+
+An interesting side affect of all of the above is that new kernels now come with a _/sys/devices/system/cpu/vulnerabilities/_ virtual directory. This directory shows the vulnerabilities affecting your CPU and the remedies being currently applied.
+
+The issues with buggy chips (and the manufacturers that keep things like this secret) has revived the call for the development of viable open source alternatives. This brings us to the partial support for [RISC-V][12] chips that has now been merged into the mainline kernel. RISC-V is an open instruction set architecture that allows manufacturers to create their own implementation of RISC-V chips, and it has resulted in several open sourced chips. While RISC-V chips are currently used mainly in embedded devices, powering things like smart hard disks or Arduino-like development boards, RISC-V proponents argue that the architecture is also well-suited for use on personal computers and even in multi-node supercomputers.
+
+[The support for RISC-V][13], as mentioned above, is still incomplete, and includes the architecture code but no device drivers. This means that, although a Linux kernel will run on RISC-V, there is no significant way to actually interact with the underlying hardware. That said, RISC-V is not vulnerable to any of the bugs that have dogged other closed architectures, and development for its support is progressing at a brisk pace, as [the RISC-V Foundation has the support of some of the industries biggest heavyweights][14].
+
+### Other stuff that's new in kernel 4.15
+
+Torvalds has often declared he likes things boring. Fortunately for him, he says, apart from the Spectre and Meltdown messes, most of the other things that happened in 4.15 were very much run of the mill, such as incremental improvements for drivers, support for new devices, and so on. However, there were a few more things worth pointing out:
+
+* [AMD got support for Secure Encrypted Virtualization][3]. This allows the kernel to fence off the memory a virtual machine is using by encrypting it. The encrypted memory can only be decrypted by the virtual machine that is using it. Not even the hypervisor can see inside it. This means that data being worked on by VMs in the cloud, for example, is safe from being spied on by any other process outside the VM.
+
+* AMD GPUs get a substantial boost thanks to [the inclusion of _display code_][4] . This gives mainline support to Radeon RX Vega and Raven Ridge cards and also implements HDMI/DP audio for AMD cards.
+
+* Raspberry Pi aficionados will be glad to know that [the 7'' touchscreen is now natively supported][5], which is guaranteed to lead to hundreds of fun projects.
+
+To find out more, you can check out the write-ups at [Kernel Newbies][15] and [Phoronix][16].
+
+ _Learn more about Linux through the free ["Introduction to Linux" ][6]course from The Linux Foundation and edX._
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/blog/intro-to-linux/2018/1/linux-kernel-415-unusual-release-cycle
+
+作者:[PAUL BROWN ][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/bro66
+[1]:https://www.linux.com/licenses/category/creative-commons-zero
+[2]:https://www.linux.com/files/images/background-penguinpng
+[3]:https://git.kernel.org/linus/33e63acc119d15c2fac3e3775f32d1ce7a01021b
+[4]:https://git.kernel.org/torvalds/c/f6705bf959efac87bca76d40050d342f1d212587
+[5]:https://git.kernel.org/linus/2f733d6194bd58b26b705698f96b0f0bd9225369
+[6]:https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
+[7]:https://lkml.org/lkml/2018/1/28/173
+[8]:https://meltdownattack.com/
+[9]:https://git.kernel.org/linus/5aa90a84589282b87666f92b6c3c917c8080a9bf
+[10]:https://git.kernel.org/linus/76b043848fd22dbf7f8bf3a1452f8c70d557b860
+[11]:https://git.kernel.org/linus/aa8a5e0062ac940f7659394f4817c948dc8c0667
+[12]:https://riscv.org/
+[13]:https://git.kernel.org/torvalds/c/b293fca43be544483b6488d33ad4b3ed55881064
+[14]:https://riscv.org/membership/
+[15]:https://kernelnewbies.org/Linux_4.15
+[16]:https://www.phoronix.com/scan.php?page=search&q=Linux+4.15
\ No newline at end of file
diff --git a/sources/tech/20180130 Mitigating known security risks in open source libraries.md b/sources/tech/20180130 Mitigating known security risks in open source libraries.md
new file mode 100644
index 0000000000..adb1491e7d
--- /dev/null
+++ b/sources/tech/20180130 Mitigating known security risks in open source libraries.md
@@ -0,0 +1,249 @@
+Mitigating known security risks in open source libraries
+============================================================
+
+>Fixing vulnerable open source packages.
+
+
+
+
+Machine (source: [Skitterphoto][9])
+
+
+This is an excerpt from [Securing Open Source Libraries][13], by Guy Podjarny.
+[Read the preceding chapter][14] or [view the full report][15].
+
+
+### Fixing Vulnerable Packages
+
+Finding out if you’re using vulnerable packages is an important step, but it’s not the real goal. The real goal is to fix those issues!
+
+This chapter focuses on all you should know about fixing vulnerable packages, including remediation options, tooling, and various nuances. Note that SCA tools traditionally focused on finding or preventing vulnerabilities, and most put little emphasis on fix beyond providing advisory information or logging an issue. Therefore, you may need to implement some of these remediations yourself, at least until more SCA solutions expand to include them.
+
+There are several ways to fix vulnerable packages, but upgrading is the best choice. If that is not possible, patching offers a good alternative. The following sections discuss each of these options, and we will later take a look at what you can do in situations where neither of these solutions is possible.
+
+### Upgrading
+
+As I’ve previously stated, a vulnerability is a type of bug, and the best way to address a bug is to use a newer version where it is fixed. And so, the best way to fix a vulnerable dependency is to upgrade to a newer version. Statistically, most disclosed vulnerabilities are eventually fixed. In npm, 59% of reported vulnerabilities have a fix. In Maven, 90% are remediable, while that portion is 85% in RubyGems.[1][4] In other words, more often than not, there is a version of your library where the vulnerability is fixed.
+
+Finding a vulnerable package requires knowledge of which versions are vulnerable. This means that, at the very least, every tool that finds issues can tell which versions are vulnerable, allowing you to look for newer versions of the library and upgrade. Most tools also take the minor extra step of determining the minimal fixed version, and noting it in the advisory.
+
+Upgrading is therefore the best way to make a vulnerability go away. It’s technically easy (update a manifest or lock file), and it’s something dev teams are very accustomed to doing. That said, upgrading still holds some complexity.
+
+### Major Upgrades
+
+While most issues are fixed, very often the fix is only applied to the latest and greatest version of the library. If you’re still using an older version of the library, upgrading may mean switching to a new major version. Major upgrades are typically not backward compatible, introducing more risk and requiring more dev effort.
+
+Another reason for fixing an issue only in the next major version is that sometimes fixing a vulnerability means reducing functionality. For instance, fixing a certain [XSS vulnerability in a jQuery 2.x codebase][5] requires a change to the way certain selectors are interpreted. The jQuery team determined too many people are relying on this functionality to deem this a non-breaking change, and so only fixed the vulnerability in their 3.x stream.
+
+For these reasons, a major upgrade can often be difficult, but if you can accept it, it’s still the best way to fix a vulnerability.
+
+### Indirect Dependency Upgrade
+
+If you’re consuming a dependency directly, upgrading is relatively straightforward. But what happens when one of your dependencies is the one who pulled in the vulnerable package? Most dependencies are in fact indirect dependencies (a.k.a. transitive dependencies), making upgrades a bit more complex.
+
+The cleanest way to perform an indirect upgrade is through a direct one. If your app uses `A@1`, which uses a vulnerable `B@1`, it’s possible that upgrading to `A@2` will trigger a downstream upgrade to `B@2` and fix the issue. Applying such an upgrade is easy (it’s essentially a direct upgrade), but discovering _which_ upgrade to do (and whether one even exists) is time consuming. While not common, some SCA tools can determine and advise on the _direct_ upgrades you need to make to fix an _indirect_ vulnerability. If your tooling doesn’t support it, you’ll need to do the searching manually.
+
+Old vulnerabilities in indirect libraries can often be fixed with a direct upgrade, but such upgrades are frequently unavailable for new issues. When a new vulnerability is disclosed, even if the offending package releases a fix right away, it takes a while for the dependency chain to catch up. If you can’t find a path to an indirect upgrade for a newly disclosed flaw, be sure to recheck frequently as one may show up soon. Once again, some SCA tools will do this monitoring for you and alert you when new remediations are available.
+
+
+
+Figure 1-1. The direct vulnerable EJS can be upgraded, but indirect instance cannot currently be upgraded
+
+### Conflicts
+
+Another potential obstacle to upgrading is a conflict. Many languages, such as Ruby and Python, require dependencies to be global, and clients such as Ruby’s bundler and Python’s pip determine the mix of library versions that can co-exist. As a result, upgrading one library may trigger a conflict with another. While developers are adept at handling such conflicts, there are times when such issues simply cannot be resolved.
+
+On the positive side, global dependency managers, such as Ruby’s bundler, allow the parent app to add a constraint. For instance, if a downstream `B@1` gem is vulnerable, you can add `B@^2` to your Gemfile, and have bundler sort out the surrounding impact. Adding such constraints is a safe and legitimate solution, as long as your ecosystem tooling can figure out a conflict-free combination of libraries.
+
+### Is a Newer Version Always Safer?
+
+The conversation about upgrading begs a question: can a vulnerability also be fixed by downgrading?
+
+For the most part, the answer is no. Vulnerabilities are bugs, and bugs are typically fixed in a newer version, not an older one. In general, maintaining a good upgrade cadence and keeping your dependencies up to date is a good preventative measure to reduce the risk of vulnerabilities.
+
+However, in certain cases, code changes or (more often) new features are the ones that trigger a vulnerability. In those cases, it’s indeed possible that downgrading will fix the discovered flaw. The advisory should give you the information you need about which versions are affected by the vulnerability. That said, note that downgrading a package puts you at higher risk of being exposed to new issues, and can make it harder to upgrade when that happens. I suggest you see downgrading as a temporary and rarely used remediation path.
+
+### There Is No Fixed Version
+
+Last on the list of reasons preventing you from upgrading to a safe version is such a version not existing in the first place!
+
+While most vulnerabilities are fixed, many remain unfixed. This is sometimes a temporary situation—for instance, when a vulnerability was made public without waiting for a fix to be released. Other times, it may be a more long-term scenario, as many repositories fall into a poor maintenance state, and don’t fix reported issues nor accept community patches.
+
+In the following sections I’ll discuss some options for when you cannot upgrade a vulnerability away.
+
+### Patching
+
+Despite all the complexity it may involve, upgrading is the best way to fix an issue. However, if you cannot upgrade, patching the vulnerability is the next best option.
+
+Patching means taking a library as is, including its vulnerabilities, and then modifying it to fix a vulnerability it holds. Patching should apply the minimal set of changes to the library, so as to keep its functionality unharmed and only address the issue at hand.
+
+Patching inevitably holds a certain amount of risk. When you use a package downloaded millions of time a month, you have some assurance that bugs in it will be discovered, reported, and often fixed. When you download that package and modify it, your version of the code will not be quite as battle tested.
+
+Patching is therefore an exercise in risk management. What presents a greater risk: having the vulnerability, or applying the patch? For well-managed patches, especially for ones small in scope, I believe it’s almost always better to have a patch than a vulnerability.
+
+It’s worth noting that patching application dependencies is a relatively new concept, but an old hat in the operating system world. When dealing with operating system dependencies, we’re accustomed to consuming a feed of fixes by running `apt-get upgrade` or an equivalent command, often remaining unaware of which issues we fixed. What most don’t know is that many of the fixes you pull down are in fact back-ported versions of the original OS author code changes, created and tested by Canonical, RedHat, and the like. A safe registry that feeds you the non-vulnerable variants of your dependencies doesn’t exist yet in the application libraries world, but patching is sometimes doable in other ways.
+
+### Sourcing Patches
+
+To create a patch, you first need to have a fix for the vulnerability! You could write one yourself, but patches are more often sourced from existing community fixes.
+
+The first place to look for a patch is a new version of the vulnerable package. Most often the vulnerability _was_ fixed by the maintainers of the library, but that fix may be in an out-of-reach indirect dependency, or perhaps was only fitted back into the latest major version. Those fixes can be extracted from the original repo and stored into their own patch file, as well as back-ported into older versions if need be.
+
+Another common source for patches are external pull requests (PRs). Open source maintenance is a complicated topic, and it’s not uncommon for repos to go inactive. In such repos, you may find community pull requests that fix a vulnerability, have been commented on and perhaps vetted by others, but are not merged and published into the main stream. Such PRs are a good starting point—if not the full solution—for creating a patch. For instance, an XSS issue in the popular JavaScript Markdown parsing library marked had an [open fix PR][6] for nearly a year before it was incorporated into a new release. During this period, you could use the fix PR code to patch the issue in your apps.
+
+Snyk maintains its own set of patches in its [open source database][7]. Most of those patches are captures or back-ports of original fixes, a few are packaged pull requests, and even fewer are written by the Snyk security research team.
+
+### Depend on GitHub Hash
+
+In very specific cases, you may be able to patch without storing any code changes. This is only possible if the vulnerable dependency is a direct dependency of your app, and the public repo holding the package has a commit that fixes the issue (often a pull request, as mentioned before).
+
+If that’s the case, most package managers allow you to change your manifest file to point to the GitHub commit instead of naming your package and version. Git hashes are immutable, so you’ll know exactly what you’re getting, even if the pull request evolved. However, the commit may be deleted, introducing certain reliability concerns.
+
+### Fork and Patch
+
+When patching a vulnerability in a direct dependency, assuming you don’t want to depend on an external commit or have none to use, you can create one of your own. Doing so typically means forking the GitHub repository to a user you control, and patching it. Once done, you can modify your manifest to point to your fixed repository.
+
+Forking is a fairly common way of fixing different bugs in dependencies, and also carries some nice reliability advantages, as the code you use is now in your own control. It has the downside of breaking off the normal version stream of the dependency, but it’s a decent short-term solution to vulnerabilities in direct dependencies. Unfortunately, forking is not a viable option for patching indirect dependencies.
+
+### Static Patching at Build Time
+
+Another opportunity to patch a dependency is during build time. This type of patching is more complicated, as it requires:
+
+1. Storing a patch in a file (often a _.patch_ file, or an alternative JAR file with the issue fixed)
+
+2. Installing the dependencies as usual
+
+3. Determining where the dependency you’d like to patch was installed
+
+4. Applying the patch by modifying or swapping out the risky code
+
+These steps are not trivial, but they’re also usually doable using package manager commands. If a vulnerability is worth fixing, and there are no easier means to fix it, this approach should be considered.
+
+This is a classic problem for tools to address, as patches can be reused and their application can be repeated. However, at the time of this writing, Snyk is the only SCA tool that maintains patches in its DB and lets you apply them in your pipeline. I predict over time more and more tools will adopt this approach.
+
+### Dynamic Patching at Boot Time
+
+In certain programming languages, classes can also be modified at runtime, a technique often referred to as "monkey patching." Monkey patching can be used to fix vulnerabilities, though that practice has not become the norm in any ecosystem. The most prevalent use of monkey patching to fix vulnerabilities is in Ruby on Rails, where the Rails team has often released patches for vulnerabilities in the libraries it maintains.
+
+### Other Remediation Paths
+
+So far, I’ve stated upgrades are the best way to address a vulnerability, and patching the second best. However, what should you do when you cannot (or will not) upgrade nor patch?
+
+In those cases, you have no choice but to dig deeper. You need to understand the vulnerability better, and how it plays into your application. If it indeed puts your application at notable risk, there are a few steps you can take.
+
+### Removal
+
+Removing a dependency is a very effective way of fixing its vulnerabilities. Unfortunately, you’ll be losing its functionality at the same time.
+
+Dropping a dependency is often hard, as it by definition requires changes to your actual code. That said, such removal may turn out to be easy—for instance, when a dependency was used for convenience and can be rewritten instead, or when a comparable alternative exists in the ecosystem.
+
+Easy or hard, removing a dependency should always be considered an option, and weighed against the risk of keeping it.
+
+### External Mitigation
+
+If you can’t fix the vulnerable code, you can try to block attacks that attempt to exploit it instead. Introducing a rule in a web app firewall, modifying the parts of your app that accept related user input, or even blocking a port are all potential ways to mitigate a vulnerability.
+
+Whether you can mitigate and how to do so depends on the specific vulnerability and application, and in many cases such protection is impossible or high risk. That said, the most trivially exploited vulnerabilities, such as the March 2017 Struts2 RCE and ImageTragick, are often the ones most easily identified and blocked, so this approach is definitely worth exploring.
+
+###### Tip
+
+### Protecting Against Unknown Vulnerabilities
+
+Once you’re aware of a known vulnerability, your best move is to fix it, and external mitigation is a last resort. However, security controls that protect against unknown vulnerabilities, ranging from web app firewalls to sandboxed processes to ensuring least privilege, can often protect you from known vulnerabilities as well.
+
+### Log Issue
+
+Last but not least, even if you choose not to remediate the issue, the least you can do is create an issue for it. Beyond its risk management advantages, logging the issue will remind you to re-examine the remediation options over time—for instance, looking for newly available upgrades or patches that can help.
+
+If you have a security operations team, make sure to make them aware of vulnerabilities you are not solving right now. This information can prove useful when they triage suspicious behavior on the network, as such behavior may come down to this security hole being exploited.
+
+### Remediation Process
+
+Beyond the specific techniques, there are few broader guidelines when it comes to remediating issues.
+
+### Ignoring Issues
+
+If you choose not to fix an issue, or to fix it through a custom path, you’ll need to tell your SCA tool you did. Otherwise, the tool will continue to indicate this problem.
+
+All OSS security tools support ignoring a vulnerability, but have slightly different capabilities. You should consider the following, and try to note that in your tool of choice:
+
+* Are you ignoring the issue because it doesn’t affect you (perhaps you’ve mitigated it another way) or because you’ve accepted the risk? This may reflect differently in your top-level reports.
+
+* Do you want to mute the issue indefinitely, or just "snooze" it? Ignoring temporarily is common for low-severity issues that don’t yet have an upgrade, where you’re comfortable taking the risk for a bit and anticipate an upgrade will show up soon.
+
+* Do you want to ignore all instances of this known vulnerability (perhaps it doesn’t apply to your system), or only certain vulnerable paths (which, after a careful vetting process, you’ve determined to be non-exploitable)?
+
+Properly tagging the reason for muting an alert helps manage these vulnerabilities over time and across projects, and reduces the chance of an issue being wrongfully ignored and slipping through the cracks.
+
+### Fix All Vulnerable Paths
+
+For all the issues you’re not ignoring, remember that remediation has to be done for _every vulnerable path_ .
+
+This is especially true for upgrades, as every path must be assessed for upgrade separately, but also applies to patches in many ecosystems.
+
+### Track Remediations Over Time
+
+As already mentioned, a fix is typically issued for the vulnerable package first, and only later propagates through the dependency chain as other libraries upgrade to use the newer (and safer) version. Similarly, community or author code contributions are created constantly, addressing issues that weren’t previously fixable.
+
+Therefore, it’s worth tracking remediation options over time. For ignored issues, periodically check if an easy fix is now available. For patched issues, track potential updates you can switch to. Certain SCA tools automate this tracking and notify you (or open automated pull requests) when such new remediations are available.
+
+### Invest in Making Fixing Easy
+
+The unfortunate reality is that new vulnerabilities in libraries are discovered all the time. This is a fact of life—code will have bugs, some of those bugs are security bugs (vulnerabilities), and some of those are disclosed. Therefore, you and your team should expect to get a constant stream of vulnerability notifications, which you need to act on.
+
+If fixing these vulnerabilities isn’t easy, your team will not do it. Fixing these issues competes with many priorities, and its oh-so-easy to put off this invisible risk. If each alert requires a lot of time to triage and determine a fix for, the ensuing behavior would likely be to either put it off or try to convince yourself it’s not a real problem.
+
+In the world of operating systems, fixing has become the default action. In fact, "patching your servers" means taking in a feed of fixes, often without ever knowing which vulnerabilities we fix. We should strive to achieve at least this level of simplicity when dealing with vulnerable app dependencies too.
+
+Part of this effort is on tooling providers. SCA tools should let you fix vulnerabilities with a click or proactive pull requests, or patch them with a single command like `apt-get upgrade` does on servers. The other part of the effort is on you. Consider it a high priority to make vulnerability remediation easy, choose priority, choose your tools accordingly, and put in the effort to enrich or adapt those tools to fit your workflow.
+
+### Summary
+
+You should always keep in mind that finding these vulnerabilities isn’t the goal—fixing them is. Because fixing vulnerabilities is something your team will need to do often, defining the processes and tools to get that done is critical.
+
+A great way to get started with remediation is to find vulnerabilities that can be fixed with a non-breaking upgrade, and get those upgrades done. While not entirely risk-free, these upgrades should be backward compatible, and getting these security holes fixed gets you off to a very good start.
+
+[1][8]Stats based on vulnerabilities curated in the Snyk vulnerability DB.
+
+
+This is an excerpt from [Securing Open Source Libraries][16], by Guy Podjarny.
+[Read the preceding chapter][17] or [view the full report][18].
+
+
+
+-------------------------------------
+
+作者简介:
+
+Guy Podjarny (Guypo) is a web performance researcher/evangelist and Akamai's Web CTO, focusing primarily on Mobile and Front-End performance. As a researcher, Guy frequently runs large scale tests, exploring performance in the real world and matching it to how browsers behave, and was one of the first to highlight the performance implications of Responsive Web Design. Guy is also the author of Mobitest, a free mobile measurement tool, and contributes to various open source tools. Guy was previously the co-founder and CTO of blaze.io, ac...
+
+--------------------------------------------------------------------------------
+
+via: https://www.oreilly.com/ideas/mitigating-known-security-risks-in-open-source-libraries
+
+作者:[ Guy Podjarny][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.oreilly.com/people/4dda0-guy-podjarny
+[1]:https://www.safaribooksonline.com/home/?utm_source=newsite&utm_medium=content&utm_campaign=lgen&utm_content=security-post-safari-right-rail-cta
+[2]:https://www.safaribooksonline.com/home/?utm_source=newsite&utm_medium=content&utm_campaign=lgen&utm_content=security-post-safari-right-rail-cta
+[3]:https://www.safaribooksonline.com/home/?utm_source=newsite&utm_medium=content&utm_campaign=lgen&utm_content=security-post-safari-right-rail-cta
+[4]:https://www.oreilly.com/ideas/mitigating-known-security-risks-in-open-source-libraries#id-xJ0u4SBFphz
+[5]:https://snyk.io/vuln/npm:jquery:20150627
+[6]:https://github.com/chjj/marked/pull/592
+[7]:https://github.com/snyk/vulnerabilitydb
+[8]:https://www.oreilly.com/ideas/mitigating-known-security-risks-in-open-source-libraries#id-xJ0u4SBFphz-marker
+[9]:https://pixabay.com/en/machine-mill-industry-steam-2881186/
+[10]:https://www.oreilly.com/ideas/mitigating-known-security-risks-in-open-source-libraries
+[11]:https://www.oreilly.com/people/4dda0-guy-podjarny
+[12]:https://www.oreilly.com/people/4dda0-guy-podjarny
+[13]:https://www.safaribooksonline.com/library/view/securing-open-source/9781491996980/?utm_source=oreilly&utm_medium=newsite&utm_campaign=fixing-vulnerable-open-source-packages
+[14]:https://www.oreilly.com/ideas/finding-vulnerable-open-source-packages?utm_source=oreilly&utm_medium=newsite&utm_campaign=fixing-vulnerable-open-source-packages
+[15]:https://www.safaribooksonline.com/library/view/securing-open-source/9781491996980/?utm_source=oreilly&utm_medium=newsite&utm_campaign=fixing-vulnerable-open-source-packages
+[16]:https://www.safaribooksonline.com/library/view/securing-open-source/9781491996980/?utm_source=oreilly&utm_medium=newsite&utm_campaign=fixing-vulnerable-open-source-packages
+[17]:https://www.oreilly.com/ideas/finding-vulnerable-open-source-packages?utm_source=oreilly&utm_medium=newsite&utm_campaign=fixing-vulnerable-open-source-packages
+[18]:https://www.safaribooksonline.com/library/view/securing-open-source/9781491996980/?utm_source=oreilly&utm_medium=newsite&utm_campaign=fixing-vulnerable-open-source-packages
+[19]:https://pixabay.com/en/machine-mill-industry-steam-2881186/
\ No newline at end of file
diff --git a/sources/tech/20180130 Python - Memcached- Efficient Caching in Distributed Applications - Real Python.md b/sources/tech/20180130 Python - Memcached- Efficient Caching in Distributed Applications - Real Python.md
new file mode 100644
index 0000000000..647a5968e6
--- /dev/null
+++ b/sources/tech/20180130 Python - Memcached- Efficient Caching in Distributed Applications - Real Python.md
@@ -0,0 +1,239 @@
+Python + Memcached: Efficient Caching in Distributed Applications – Real Python
+======
+
+When writing Python applications, caching is important. Using a cache to avoid recomputing data or accessing a slow database can provide you with a great performance boost.
+
+Python offers built-in possibilities for caching, from a simple dictionary to a more complete data structure such as [`functools.lru_cache`][2]. The latter can cache any item using a [Least-Recently Used algorithm][3] to limit the cache size.
+
+Those data structures are, however, by definition local to your Python process. When several copies of your application run across a large platform, using a in-memory data structure disallows sharing the cached content. This can be a problem for large-scale and distributed applications.
+
+
+
+Therefore, when a system is distributed across a network, it also needs a cache that is distributed across a network. Nowadays, there are plenty of network servers that offer caching capability—we already covered [how to use Redis for caching with Django][4].
+
+As you’re going to see in this tutorial, [memcached][5] is another great option for distributed caching. After a quick introduction to basic memcached usage, you’ll learn about advanced patterns such as “cache and set” and using fallback caches to avoid cold cache performance issues.
+
+### Installing memcached
+
+Memcached is [available for many platforms][6]:
+
+ * If you run **Linux** , you can install it using `apt-get install memcached` or `yum install memcached`. This will install memcached from a pre-built package but you can alse build memcached from source, [as explained here][6].
+ * For **macOS** , using [Homebrew][7] is the simplest option. Just run `brew install memcached` after you’ve installed the Homebrew package manager.
+ * On **Windows** , you would have to compile memcached yourself or find [pre-compiled binaries][8].
+
+
+
+Once installed, memcached can simply be launched by calling the `memcached` command:
+```
+$ memcached
+
+```
+
+Before you can interact with memcached from Python-land you’ll need to install a memcached client library. You’ll see how to do this in the next section, along with some basic cache access operations.
+
+### Storing and Retrieving Cached Values Using Python
+
+If you never used memcached, it is pretty easy to understand. It basically provides a giant network-available dictionary. This dictionary has a few properties that are different from a classical Python dictionnary, mainly:
+
+ * Keys and values have to be bytes
+ * Keys and values are automatically deleted after an expiration time
+
+
+
+Therefore, the two basic operations for interacting with memcached are `set` and `get`. As you might have guessed, they’re used to assign a value to a key or to get a value from a key, respectively.
+
+My preferred Python library for interacting with memcached is [`pymemcache`][9]—I recommend using it. You can simply [install it using pip][10]:
+```
+$ pip install pymemcache
+
+```
+
+The following code shows how you can connect to memcached and use it as a network-distributed cache in your Python applications:
+```
+>>> from pymemcache.client import base
+
+# Don't forget to run `memcached' before running this next line:
+>>> client = base.Client(('localhost', 11211))
+
+# Once the client is instantiated, you can access the cache:
+>>> client.set('some_key', 'some value')
+
+# Retrieve previously set data again:
+>>> client.get('some_key')
+'some value'
+
+```
+
+memcached network protocol is really simple an its implementation extremely fast, which makes it useful to store data that would be otherwise slow to retrieve from the canonical source of data or to compute again:
+
+While straightforward enough, this example allows storing key/value tuples across the network and accessing them through multiple, distributed, running copies of your application. This is simplistic, yet powerful. And it’s a great first step towards optimizing your application.
+
+### Automatically Expiring Cached Data
+
+When storing data into memcached, you can set an expiration time—a maximum number of seconds for memcached to keep the key and value around. After that delay, memcached automatically removes the key from its cache.
+
+What should you set this cache time to? There is no magic number for this delay, and it will entirely depend on the type of data and application that you are working with. It could be a few seconds, or it might be a few hours.
+
+Cache invalidation, which defines when to remove the cache because it is out of sync with the current data, is also something that your application will have to handle. Especially if presenting data that is too old or or stale is to be avoided.
+
+Here again, there is no magical recipe; it depends on the type of application you are building. However, there are several outlying cases that should be handled—which we haven’t yet covered in the above example.
+
+A caching server cannot grow infinitely—memory is a finite resource. Therefore, keys will be flushed out by the caching server as soon as it needs more space to store other things.
+
+Some keys might also be expired because they reached their expiration time (also sometimes called the “time-to-live” or TTL.) In those cases the data is lost, and the canonical data source must be queried again.
+
+This sounds more complicated than it really is. You can generally work with the following pattern when working with memcached in Python:
+```
+from pymemcache.client import base
+
+
+def do_some_query():
+ # Replace with actual querying code to a database,
+ # a remote REST API, etc.
+ return 42
+
+
+# Don't forget to run `memcached' before running this code
+client = base.Client(('localhost', 11211))
+result = client.get('some_key')
+
+if result is None:
+ # The cache is empty, need to get the value
+ # from the canonical source:
+ result = do_some_query()
+
+ # Cache the result for next time:
+ client.set('some_key', result)
+
+# Whether we needed to update the cache or not,
+# at this point you can work with the data
+# stored in the `result` variable:
+print(result)
+
+```
+
+> **Note:** Handling missing keys is mandatory because of normal flush-out operations. It is also obligatory to handle the cold cache scenario, i.e. when memcached has just been started. In that case, the cache will be entirely empty and the cache needs to be fully repopulated, one request at a time.
+
+This means you should view any cached data as ephemeral. And you should never expect the cache to contain a value you previously wrote to it.
+
+### Warming Up a Cold Cache
+
+Some of the cold cache scenarios cannot be prevented, for example a memcached crash. But some can, for example migrating to a new memcached server.
+
+When it is possible to predict that a cold cache scenario will happen, it is better to avoid it. A cache that needs to be refilled means that all of the sudden, the canonical storage of the cached data will be massively hit by all cache users who lack a cache data (also known as the [thundering herd problem][11].)
+
+pymemcache provides a class named `FallbackClient` that helps in implementing this scenario as demonstrated here:
+```
+from pymemcache.client import base
+from pymemcache import fallback
+
+
+def do_some_query():
+ # Replace with actual querying code to a database,
+ # a remote REST API, etc.
+ return 42
+
+
+# Set `ignore_exc=True` so it is possible to shut down
+# the old cache before removing its usage from
+# the program, if ever necessary.
+old_cache = base.Client(('localhost', 11211), ignore_exc=True)
+new_cache = base.Client(('localhost', 11212))
+
+client = fallback.FallbackClient((new_cache, old_cache))
+
+result = client.get('some_key')
+
+if result is None:
+ # The cache is empty, need to get the value
+ # from the canonical source:
+ result = do_some_query()
+
+ # Cache the result for next time:
+ client.set('some_key', result)
+
+print(result)
+
+```
+
+The `FallbackClient` queries the old cache passed to its constructor, respecting the order. In this case, the new cache server will always be queried first, and in case of a cache miss, the old one will be queried—avoiding a possible return-trip to the primary source of data.
+
+If any key is set, it will only be set to the new cache. After some time, the old cache can be decommissioned and the `FallbackClient` can be replaced directed with the `new_cache` client.
+
+### Check And Set
+
+When communicating with a remote cache, the usual concurrency problem comes back: there might be several clients trying to access the same key at the same time. memcached provides a check and set operation, shortened to CAS, which helps to solve this problem.
+
+The simplest example is an application that wants to count the number of users it has. Each time a visitor connects, a counter is incremented by 1. Using memcached, a simple implementation would be:
+```
+def on_visit(client):
+ result = client.get('visitors')
+ if result is None:
+ result = 1
+ else:
+ result += 1
+ client.set('visitors', result)
+
+```
+
+However, what happens if two instances of the application try to update this counter at the same time?
+
+The first call `client.get('visitors')` will return the same number of visitors for both of them, let’s say it’s 42. Then both will add 1, compute 43, and set the number of visitors to 43. That number is wrong, and the result should be 44, i.e. 42 + 1 + 1.
+
+To solve this concurrency issue, the CAS operation of memcached is handy. The following snippet implements a correct solution:
+```
+def on_visit(client):
+ while True:
+ result, cas = client.gets('visitors')
+ if result is None:
+ result = 1
+ else:
+ result += 1
+ if client.cas('visitors', result, cas):
+ break
+
+```
+
+The `gets` method returns the value, just like the `get` method, but it also returns a CAS value.
+
+What is in this value is not relevant, but it is used for the next method `cas` call. This method is equivalent to the `set` operation, except that it fails if the value has changed since the `gets` operation. In case of success, the loop is broken. Otherwise, the operation is restarted from the beginning.
+
+In the scenario where two instances of the application try to update the counter at the same time, only one succeeds to move the counter from 42 to 43. The second instance gets a `False` value returned by the `client.cas` call, and have to retry the loop. It will retrieve 43 as value this time, will increment it to 44, and its `cas` call will succeed, thus solving our problem.
+
+Incrementing a counter is interesting as an example to explain how CAS works because it is simplistic. However, memcached also provides the `incr` and `decr` methods to increment or decrement an integer in a single request, rather than doing multiple `gets`/`cas` calls. In real-world applications `gets` and `cas` are used for more complex data type or operations
+
+Most remote caching server and data store provide such a mechanism to prevent concurrency issues. It is critical to be aware of those cases to make proper use of their features.
+
+### Beyond Caching
+
+The simple techniques illustrated in this article showed you how easy it is to leverage memcached to speed up the performances of your Python application.
+
+Just by using the two basic “set” and “get” operations you can often accelerate data retrieval or avoid recomputing results over and over again. With memcached you can share the cache accross a large number of distributed nodes.
+
+Other, more advanced patterns you saw in this tutorial, like the Check And Set (CAS) operation allow you to update data stored in the cache concurrently across multiple Python threads or processes while avoiding data corruption.
+
+If you are interested into learning more about advanced techniques to write faster and more scalable Python applications, check out [Scaling Python][12]. It covers many advanced topics such as network distribution, queuing systems, distributed hashing, and code profiling.
+
+--------------------------------------------------------------------------------
+
+via: https://realpython.com/blog/python/python-memcache-efficient-caching/
+
+作者:[Julien Danjou][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://realpython.com/team/jdanjou/
+[1]:https://realpython.com/blog/categories/python/
+[2]:https://docs.python.org/3/library/functools.html#functools.lru_cache
+[3]:https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_(LRU)
+[4]:https://realpython.com/blog/python/caching-in-django-with-redis/
+[5]:http://memcached.org
+[6]:https://github.com/memcached/memcached/wiki/Install
+[7]:https://brew.sh/
+[8]:https://commaster.net/content/installing-memcached-windows
+[9]:https://pypi.python.org/pypi/pymemcache
+[10]:https://realpython.com/learn/python-first-steps/#11-pythons-power-packagesmodules
+[11]:https://en.wikipedia.org/wiki/Thundering_herd_problem
+[12]:https://scaling-python.com
diff --git a/sources/tech/20180130 Quick Look at the Arch Based Indie Linux Distribution- MagpieOS.md b/sources/tech/20180130 Quick Look at the Arch Based Indie Linux Distribution- MagpieOS.md
new file mode 100644
index 0000000000..a850a8fd33
--- /dev/null
+++ b/sources/tech/20180130 Quick Look at the Arch Based Indie Linux Distribution- MagpieOS.md
@@ -0,0 +1,78 @@
+Quick Look at the Arch Based Indie Linux Distribution: MagpieOS
+======
+Most of the Linux distros that are in use today are either created and developed in the US or Europe. A young developer from Bangladesh wants to change all that.
+
+### Who is Rizwan?
+
+[Rizwan][1] is a computer science student from Bangladesh. He is currently studying to become a profession Python programmer. He started using Linux back in 2015. Working with Linux inspired him to create this own Linux distribution. He also wants to let the rest of the world know that Bangladesh is upgrading to Linux.
+
+He has also worked on creating a [live version of Linux From Scratch][2].
+
+## ![MagpieOS Linux][3]
+
+### What is MagpieOS?
+
+Rizwan's new distro is named MagpieOS. [MagpieOS][4] is very simple. It is basically Arch with the GNOME3 desktop environment. MagpieOS also includes a custom repo with icons and themes (claimed to be) not available on other Arch-based distros or AUR.
+
+Here is a list of the software included with MagpieOS: Firefox, LibreOffice, Uget, Bleachbit, Notepadqq, SUSE Studio Image Writer, Pamac Package Manager, Gparted, Gimp, Rhythmbox, Simple Screen Recorder, all default GNOME software including Totem Video Player, and a new set of custom wallpaper.
+
+Currently, MagpieOS only supported the GNOME desktop environment. Rizwan picked it because it is his favorite. However, he plans to add more desktop environments in the future.
+
+Unfortunately, MagpieOS does not support the Bangla language or any other local languages. It supports GNOME's default language like English, Hindi etc.
+
+Rizwan named his distro MagpieOS because the [magpie][5] is the official bird of Bangladesh.
+
+## ![MagpieOS Linux][6]
+
+### Why Arch?
+
+Like most people, Rizwan started his Linux journey by using [Ubuntu][7]. In the beginning, he was happy with it. However, sometimes the software he wanted to install was not available in the repos and he had to hunt through Google looking for the correct PPA. He decided to switch to [Arch][8] because Arch has many packages that were not available on Ubuntu. Rizwan also liked the fact that Arch is a rolling release and would always be up-to-date.
+
+The problem with Arch is that it is complicated and time-consuming to install. So, Rizwan tried out several Arch-based distros and was not happy with any of them. He didn't like [Manjaro][9] because they did not have permission to use Arch's repos. Also, Arch repo mirrors are faster than Manjaro's and have more software. He liked [Antergos][10], but to install you need a constant internet connection. If your connection fails during installation, you have to start over.
+
+Because of these issues, Rizwan decided to create a simple distro that would give him and others an Arch install without all the hassle. He also hopes to get developers from his home country to switch from Ubuntu to Arch by using his distro.
+
+### How to Help Rizwan with MagpieOS
+
+If you are interested in helping Rizwan develop MagpieOS, you can contact him via the [MagpieOS website][4]. You can also check out the project's [GitHub page][11]. Rizwan said that he is not looking for financial support at the moment.
+
+## ![MagpieOS Linux][12]
+
+### Final Thoughts
+
+I installed MagpieOS to give it a quick once-over. It uses the [Calamares installer][13], which means installing it was relatively quick and painless. After I rebooted, I was greeted by an audio message welcoming me to MagpieOS.
+
+To be honest, it was the first time I have heard a post-install greeting. (Windows 10 might have one, but I'm not sure.) There was also a Mac OS-esque application dock at the bottom of the screen. Other than that, it felt like any other GNOME 3 desktop I have used.
+
+Considering that it's an indie project at the nascent stage, I won't recommend it using as your main OS. But if you are a distrohopper, you can surely give it a try.
+
+That being said, this is a good first try for a student seeking to put his country on the technological map. All the best, Rizwan.
+
+Have you already heard of MagpieOS? What is your favorite region or locally made Linux distro? Please let us know in the comments below.
+
+If you found this article interesting, please take a minute to share it on social media.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/magpieos/
+
+作者:[John Paul][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://twitter.com/Linux_Saikat
+[2]:https://itsfoss.com/linux-from-scratch-live-cd/
+[3]:https://itsfoss.com/wp-content/uploads/2018/01/magpieos1.jpg
+[4]:http://www.magpieos.net
+[5]:https://en.wikipedia.org/wiki/Magpie
+[6]:https://itsfoss.com/wp-content/uploads/2018/01/magpieos2.jpg
+[7]:https://www.ubuntu.com
+[8]:https://www.archlinux.org
+[9]:http://manjaro.org
+[10]:https://antergos.com
+[11]:https://github.com/Rizwan-Hasan/MagpieOS
+[12]:https://itsfoss.com/wp-content/uploads/2018/01/magpieos3.png
+[13]:https://calamares.io
diff --git a/sources/tech/20180130 Reckoning The Spectre And Meltdown Performance Hit.md b/sources/tech/20180130 Reckoning The Spectre And Meltdown Performance Hit.md
new file mode 100644
index 0000000000..d7140a21cf
--- /dev/null
+++ b/sources/tech/20180130 Reckoning The Spectre And Meltdown Performance Hit.md
@@ -0,0 +1,85 @@
+Reckoning The Spectre And Meltdown Performance Hit For HPC
+============================================================
+
+
+
+While no one has yet created an exploit to take advantage of the Spectre and Meltdown speculative execution vulnerabilities that were exposed by Google six months ago and that were revealed in early January, it is only a matter of time. The [patching frenzy has not settled down yet][2], and a big concern is not just whether these patches fill the security gaps, but at what cost they do so in terms of application performance.
+
+To try to ascertain the performance impact of the Spectre and Meltdown patches, most people have relied on comments from Google on the negligible nature of the performance hit on its own applications and some tests done by Red Hat on a variety of workloads, [which we profiled in our initial story on the vulnerabilities][3]. This is a good starting point, but what companies really need to do is profile the performance of their applications before and after applying the patches – and in such a fine-grained way that they can use the data to debug the performance hit and see if there is any remediation they can take to alleviate the impact.
+
+In the meantime, we are relying on researchers and vendors to figure out the performance impacts. Networking chip maker Mellanox Technologies, always eager to promote the benefits of the offload model of its switch and network interface chips, has run some tests to show the effects of the Spectre and Meltdown patches on high performance networking for various workloads and using various networking technologies, including its own Ethernet and InfiniBand devices and Intel’s OmniPath. Some HPC researchers at the University of Buffalo have also done some preliminary benchmarking of selected HPC workloads to see the effect on compute and network performance. This is a good starting point, but is far from a complete picture of the impact that might be seen on HPC workloads after organization deploy the Spectre and Meltdown patches to their systems.
+
+To recap, here is what Red Hat found out when it tested the initial Spectre and Meltdown patches running its Enterprise Linux 7 release on servers using Intel’s “Haswell” Xeon E5 v3, “Broadwell” Xeon E5 v4, and “Skylake” Xeon SP processors:
+
+* **Measurable, 8 percent to 19 percent:** Highly cached random memory, with buffered I/O, OLTP database workloads, and benchmarks with high kernel-to-user space transitions are impacted between 8 percent and 19 percent. Examples include OLTP Workloads (TPC), sysbench, pgbench, netperf (< 256 byte), and fio (random I/O to NvME).
+
+* **Modest, 3 percent to 7 percent:** Database analytics, Decision Support System (DSS), and Java VMs are impacted less than the Measurable category. These applications may have significant sequential disk or network traffic, but kernel/device drivers are able to aggregate requests to moderate level of kernel-to-user transitions. Examples include SPECjbb2005, Queries/Hour and overall analytic timing (sec).
+
+* **Small, 2 percent to 5 percent:** HPC CPU-intensive workloads are affected the least with only 2 percent to 5 percent performance impact because jobs run mostly in user space and are scheduled using CPU pinning or NUMA control. Examples include Linpack NxN on X86 and SPECcpu2006.
+
+* **Minimal impact:** Linux accelerator technologies that generally bypass the kernel in favor of user direct access are the least affected, with less than 2% overhead measured. Examples tested include DPDK (VsPERF at 64 byte) and OpenOnload (STAC-N). Userspace accesses to VDSO like get-time-of-day are not impacted. We expect similar minimal impact for other offloads.
+
+And just to remind you, according to Red Hat containerized applications running atop Linux do not incur an extra Spectre or Meltdown penalty compared to applications running on bare metal because they are implemented as generic Linux processes themselves. But applications running inside virtual machines running atop hypervisors, Red Hat does expect that, thanks to the increase in the frequency of user-to-kernel transitions, the performance hit will be higher. (How much has not yet been revealed.)
+
+Gilad Shainer, the vice president of marketing for the InfiniBand side of the Mellanox house, shared some initial performance data from the company’s labs with regard to the Spectre and Meltdown patches. ([The presentation is available online here.][4])
+
+In general, Shainer tells _The Next Platform_ , the offload model that Mellanox employs in its InfiniBand switches (RDMA is a big component of this) and in its Ethernet (The RoCE clone of RDMA is used here) are a very big deal given the fact that the network drivers bypass the operating system kernels. The exploits take advantage, in one of three forms, of the porous barrier between the kernel and user spaces in the operating systems, so anything that is kernel heavy will be adversely affected. This, says Shainer, includes the TCP/IP protocol that underpins Ethernet as well as the OmniPath protocol, which by its nature tries to have the CPUs in the system do a lot of the network processing. Intel and others who have used an onload model have contended that this allows for networks to be more scalable, and clearly there are very scalable InfiniBand and OmniPath networks, with many thousands of nodes, so both approaches seem to work in production.
+
+Here are the feeds and speeds on the systems that Mellanox tested on two sets of networking tests. For the comparison of Ethernet with RoCE added and standard TCP over Ethernet, the hardware was a two-socket server using Intel’s Xeon E5-2697A v4 running at 2.60 GHz. This machine was configured with Red Hat Enterprise Linux 7.4, with kernel versions 3.10.0-693.11.6.el7.x86_64 and 3.10.0-693.el7.x86_64\. (Those numbers _are_ different – there is an _11.6_ in the middle of the second one.) The machines were equipped with ConnectX-5 server adapters with firmware 16.22.0170 and the MLNX_OFED_LINUX-4.3-0.0.5.0 driver. The workload that was tested was not a specific HPC application, but rather a very low level, homegrown interconnect benchmark that is used to stress switch chips and NICs to see their peak _sustained_ performance, as distinct from peak _theoretical_ performance, which is the absolute ceiling. This particular test was run on a two-node cluster, passing data from one machine to the other.
+
+Here is how the performance stacked up before and after the Spectre and Meltdown patches were added to the systems:
+
+ [][5]
+
+As you can see, at this very low level, there is no impact on network performance between two machines supporting RoCE on Ethernet, but running plain vanilla TCP without an offload on top of Ethernet, there are some big performance hits. Interestingly, on this low-level test, the impact was greatest on small message sizes in the TCP stack and then disappeared as the message sizes got larger.
+
+On a separate round of tests pitting InfiniBand from Mellanox against OmniPath from Intel, the server nodes were configured with a pair of Intel Xeon SP Gold 6138 processors running at 2 GHz, also with Red Hat Enterprise Linux 7.4 with the 3.10.0-693.el7.x86_64 and 3.10.0-693.11.6.el7.x86_64 kernel versions. The OmniPath adapter uses the IntelOPA-IFS.RHEL74-x86_64.10.6.1.0.2 driver and the Mellanox ConnectX-5 adapter uses the MLNX_OFED 4.2 driver.
+
+Here is how the InfiniBand and OmniPath protocols did on the tests before and after the patches:
+
+ [][6]
+
+Again, thanks to the offload model and the fact that this was a low level benchmark that did not hit the kernel very much (and some HPC applications might cross that boundary and therefore invoke the Spectre and Meltdown performance penalties), there was no real effect on the two-node cluster running InfiniBand. With the OmniPath system, the impact was around 10 percent for small message sizes, and then grew to 25 percent or so once the message sizes transmitted reached 512 bytes.
+
+We have no idea what the performance implications are for clusters of more than two machines using the Mellanox approach. It would be interesting to see if the degradation compounds or doesn’t.
+
+### Early HPC Performance Tests
+
+While such low level benchmarks provide some initial guidance on what the effect might be of the Spectre and Meltdown patches on HPC performance, what you really need is a benchmark run of real HPC applications running on clusters of various sizes, both before and after the Spectre and Meltdown patches are applied to the Linux nodes. A team of researchers led by Nikolay Simakov at the Center For Computational Research at SUNY Buffalo fired up some HPC benchmarks and a performance monitoring tool derived from the National Science Foundation’s Extreme Digital (XSEDE) program to see the effect of the Spectre and Meltdown patches on how much work they could get done as gauged by wall clock time to get that work done.
+
+The paper that Simakov and his team put together on the initial results [is found here][7]. The tool that was used to monitor the performance of the systems was called XD Metrics on Demand, or XDMoD, and it was open sourced and is available for anyone to use. (You might consider [Open XDMoD][8] for your own metrics to determine the performance implications of the Spectre and Meltdown patches.) The benchmarks tested by the SUNY Buffalo researchers included the NAMD molecular dynamics and NWChem computational chemistry applications, as well as the HPC Challenge suite, which itself includes the STREAM memory bandwidth test and the NASA Parallel Benchmarks (NPB), the Interconnect MPI Benchmarks (IMB). The researchers also tested the IOR file reading and the MDTest metadata benchmark tests from Lawrence Livermore National Laboratory. The IOR and MDTest benchmarks were run in local mode and in conjunction with a GPFS parallel file system running on an external 3 PB storage cluster. (The tests with a “.local” suffix in the table are run on storage in the server nodes themselves.)
+
+SUNY Buffalo has an experimental cluster with two-socket machines based on Intel “Nehalem” Xeon L5520 processors, which have eight cores and which are, by our reckoning, very long in the tooth indeed in that they are nearly nine years old. Each node has 24 GB of main memory and has 40 Gb/sec QDR InfiniBand links cross connecting them together. The systems are running the latest CentOS 7.4.1708 release, without and then with the patches applied. (The same kernel patches outlined above in the Mellanox test.) Simakov and his team ran each benchmark on a single node configuration and then ran the benchmark on a two node configuration, and it shows the difference between running a low-level benchmark and actual applications when doing tests. Take a look at the table of results:
+
+ [][9]
+
+The before runs of each application tested were done on around 20 runs, and the after was done on around 50 runs. For the core HPC applications – NAMD, NWChem, and the elements of HPCC – the performance degradation was between 2 percent and 3 percent, consistent with what Red Hat told people to expect back in the first week that the Spectre and Meltdown vulnerabilities were revealed and the initial patches were available. However, moving on to two-node configurations, where network overhead was taken into account, the performance impact ranged from 5 percent to 11 percent. This is more than you would expect based on the low level benchmarks that Mellanox has done. Just to make things interesting, on the IOR and MDTest benchmarks, moving from one to two nodes actually lessened the performance impact; running the IOR test on the local disks resulted in a smaller performance hit then over the network for a single node, but was not as low as for a two-node cluster running out to the GPFS file system.
+
+There is a lot of food for thought in this data, to say the least.
+
+What we want to know – and what the SUNY Buffalo researchers are working on – is what happens to performance on these HPC applications when the cluster is scaled out.
+
+“We will know that answer soon,” Simakov tells _The Next Platform_ . “But there are only two scenarios that are possible. Either it is going to get worse or it is going to stay about the same as a two-node cluster. We think that it will most likely stay the same, because all of the MPI communication happens through the shared memory on a single node, and when you get to two nodes, you get it into the network fabric and at that point, you are probably paying all of the extra performance penalties.”
+
+We will update this story with data on larger scale clusters as soon as Simakov and his team provide the data.
+
+--------------------------------------------------------------------------------
+
+via: https://www.nextplatform.com/2018/01/30/reckoning-spectre-meltdown-performance-hit-hpc/
+
+作者:[Timothy Prickett Morgan][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:https://www.nextplatform.com/author/tpmn/
+[1]:https://www.nextplatform.com/author/tpmn/
+[2]:https://www.nextplatform.com/2018/01/18/datacenters-brace-spectre-meltdown-impact/
+[3]:https://www.nextplatform.com/2018/01/08/cost-spectre-meltdown-server-taxes/
+[4]:http://www.mellanox.com/related-docs/presentations/2018/performance/Spectre-and-Meltdown-Performance.pdf?homepage
+[5]:https://3s81si1s5ygj3mzby34dq6qf-wpengine.netdna-ssl.com/wp-content/uploads/2018/01/mellanox-spectre-meltdown-roce-versus-tcp.jpg
+[6]:https://3s81si1s5ygj3mzby34dq6qf-wpengine.netdna-ssl.com/wp-content/uploads/2018/01/mellanox-spectre-meltdown-infiniband-versus-omnipath.jpg
+[7]:https://arxiv.org/pdf/1801.04329.pdf
+[8]:http://open.xdmod.org/7.0/index.html
+[9]:https://3s81si1s5ygj3mzby34dq6qf-wpengine.netdna-ssl.com/wp-content/uploads/2018/01/suny-buffalo-spectre-meltdown-test-table.jpg
\ No newline at end of file
diff --git a/sources/tech/20180130 Refreshing old computers with Linux.md b/sources/tech/20180130 Refreshing old computers with Linux.md
new file mode 100644
index 0000000000..0a9f49c1d4
--- /dev/null
+++ b/sources/tech/20180130 Refreshing old computers with Linux.md
@@ -0,0 +1,104 @@
+Refreshing old computers with Linux
+============================================================
+
+### A middle school's Tech Stewardship program is now an elective class for science and technology students.
+
+
+
+Image by : opensource.com
+
+It's nearly impossible to enter a school these days without seeing an abundance of technology. Despite this influx of computers into education, funding inequity forces school systems to make difficult choices. Some educators see things as they are and wonder, "Why?" while others see problems as opportunities and think, "Why not?"
+
+[Andrew Dobbie ][31]is one of those visionaries who saw his love of Linux and computer reimaging as a unique learning opportunity for his students.
+
+Andrew teaches sixth grade at Centennial Senior Public School in Brampton, Ontario, Canada, and is a[Google Certified Innovator][16]. Andrew said, "Centennial Senior Public School hosts a special regional science & technology program that invites students from throughout the region to spend three years learning Ontario curriculum through the lens of science and technology." However, the school's students were in danger of falling prey to the digital divide that's exacerbated by hardware and software product lifecycles and inadequate funding.
+
+
+
+Image courtesy of [Affordable Tech for All][6]
+
+Although there was a school-wide need for access to computers in the classrooms, Andrew and his students discovered that dozens of old computers were being shipped out of the school because they were too old and slow to keep up with the latest proprietary operating systems or function on the school's network.
+
+Andrew saw this problem as a unique learning opportunity for his students and created the [Tech Stewardship][17] program. He works in partnership with two other teachers, Mike Doiu and Neil Lyons, and some students, who "began experimenting with open source operating systems like [Lubuntu][18] and [CubLinux][19] to help develop a solution to our in-class computer problem," he says.
+
+The sixth-grade students deployed the reimaged computers into classrooms throughout the school. When they exhausted the school's supply of surplus computers, they sourced more free computers from a local nonprofit organization called [Renewed Computer Technology Ontario][20]. In all, the Tech Stewardship program has provided more than 200 reimaged computers for students to use in classrooms throughout the school.
+
+
+
+
+Image courtesy of [Affordable Tech for All][7]
+
+The Tech Stewardship program is now an elective class for the school's science and technology students in grades six, seven, and eight. Not only are the students learning about computer reimaging, they're also giving back to their local communities through this open source outreach program.
+
+### A broad impact
+
+The Tech Stewardship program is linked directly to the school's curriculum, especially in social studies by teaching the [United Nations' Sustainable Development Goals][21] (SDGs). The program is a member of [Teach SDGs][22], and Andrew serves as a Teach SDGs ambassador. Also, as a Google Certified Innovator, Andrew partners with Google and the [EdTechTeam][23], and Tech Stewardship has participated in Ontario's [Bring it Together][24] conference for educational technology.
+
+Andrew's students also serve as mentors to their fellow students. In one instance, a group of girls taught a grade 3 class about effective use of Google Drive and helped these younger students to make the best use of their Linux computers. Andrew said, "outreach and extension of learning beyond the classroom at Centennial is a major goal of the Tech Stewardship program."
+
+### What the students say
+
+Linux and open source are an integral part of the program. A girl named Ashna says, "In grade 6, Mr. Dobbie had shown us how to reimage a computer into Linux to use it for educational purposes. Since then, we have been learning more and growing." Student Shradhaa says, "At the very beginning, we didn't even know how to reimage with Linux. Mr. Dobbie told us to write steps for how to reimage Linux devices, and using those steps we are trying to reimage the computers."
+
+
+
+
+Image courtesy of [Affordable Tech for All][8]
+
+The students were quick to add that Tech Stewardship has become a portal for discussion about being advocates for the change they want to see in the world. Through their hands-on activity, students learn to support the United Nations Sustainable Development goals. They also learn lessons far beyond the curriculum itself. For example, a student named Areez says he has learned how to find other resources, including donations, that allow the project to expand, since the class work upfitting older computers doesn't produce an income stream.
+
+Another student, Harini, thinks the Tech Stewardship program has demonstrated to other students what is possible and how one small initiative can change the world. After learning about the program, 40 other schools and individuals are reimaging computers with Linux. Harini says, "The more people who use them for educational purposes, the more outstanding the future will become since those educated people will lead out new, amazing lives with jobs."
+
+Joshua, another student in the program, sees it this way: "I thought of it as just a fun experience, but as it went on, we continued learning and understanding how what we were doing was making such a big impact on the world!" Later, he says, "a school reached out to us and asked us if we could reimage some computers for them. We went and completed the task. Then it continued to grow, as people from Europe came to see how we were fixing broken computers and started doing it when they went back."
+
+Andrew Dobbie is keen to share his experience with schools and interested individuals. You can contact him on [Twitter][25] or through his [website][26].
+
+
+### About the author
+
+ [][27] Don Watkins - Educator, education technology specialist, entrepreneur, open source advocate. M.A. in Educational Psychology, MSED in Educational Leadership, Linux system administrator, CCNA, virtualization using Virtual Box. Follow me at [@Don_Watkins .][13][More about me][14]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/18/1/new-linux-computers-classroom
+
+作者:[Don Watkins ][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/don-watkins
+[1]:https://opensource.com/resources/what-is-linux?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[2]:https://opensource.com/resources/what-are-linux-containers?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[3]:https://developers.redhat.com/promotions/linux-cheatsheet/?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[4]:https://developers.redhat.com/cheat-sheet/advanced-linux-commands-cheatsheet?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[5]:https://opensource.com/tags/linux?intcmp=70160000000h1jYAAQ&utm_source=intcallout&utm_campaign=linuxcontent
+[6]:https://photos.google.com/share/AF1QipPnm-q9OIQnrzDD4n7oWIBBIE7RQ6BI9lv486RaU5lKBrs88pq3gPKM8VAgY0prkw?key=cS1RdEZ3ZHdXLWp0bUwzMEk3UnFQRkUwbWl1dWhn
+[7]:https://photos.google.com/share/AF1QipPnm-q9OIQnrzDD4n7oWIBBIE7RQ6BI9lv486RaU5lKBrs88pq3gPKM8VAgY0prkw?key=cS1RdEZ3ZHdXLWp0bUwzMEk3UnFQRkUwbWl1dWhn
+[8]:https://photos.google.com/share/AF1QipPnm-q9OIQnrzDD4n7oWIBBIE7RQ6BI9lv486RaU5lKBrs88pq3gPKM8VAgY0prkw?key=cS1RdEZ3ZHdXLWp0bUwzMEk3UnFQRkUwbWl1dWhn
+[9]:https://opensource.com/file/384581
+[10]:https://opensource.com/file/384591
+[11]:https://opensource.com/file/384586
+[12]:https://opensource.com/article/18/1/new-linux-computers-classroom?rate=bK5X7pRc5y9TyY6jzOZeLDW6ehlWmNPXuP38DYsQ-6I
+[13]:https://twitter.com/Don_Watkins
+[14]:https://opensource.com/users/don-watkins
+[15]:https://opensource.com/user/15542/feed
+[16]:https://edutrainingcenter.withgoogle.com/certification_innovator
+[17]:https://sites.google.com/view/mrdobbie/tech-stewardship
+[18]:https://lubuntu.net/
+[19]:https://en.wikipedia.org/wiki/Cub_Linux
+[20]:http://www.rcto.ca/
+[21]:http://www.un.org/sustainabledevelopment/sustainable-development-goals/
+[22]:http://www.teachsdgs.org/
+[23]:https://www.edtechteam.com/team/
+[24]:http://bringittogether.ca/
+[25]:https://twitter.com/A_Dobbie11
+[26]:http://bit.ly/linuxresources
+[27]:https://opensource.com/users/don-watkins
+[28]:https://opensource.com/users/don-watkins
+[29]:https://opensource.com/users/don-watkins
+[30]:https://opensource.com/article/18/1/new-linux-computers-classroom#comments
+[31]:https://twitter.com/A_Dobbie11
+[32]:https://opensource.com/tags/education
+[33]:https://opensource.com/tags/linux
\ No newline at end of file
diff --git a/sources/tech/20180130 Trying Other Go Versions.md b/sources/tech/20180130 Trying Other Go Versions.md
new file mode 100644
index 0000000000..731747d19a
--- /dev/null
+++ b/sources/tech/20180130 Trying Other Go Versions.md
@@ -0,0 +1,112 @@
+Trying Other Go Versions
+============================================================
+
+While I generally use the current release of Go, sometimes I need to try a different version. For example, I need to check that all the examples in my [Guide to JSON][2] work with [both the supported releases of Go][3](1.8.6 and 1.9.3 at time of writing) along with go1.10rc1.
+
+I primarily use the current version of Go, updating it when new versions are released. I try out other versions as needed following the methods described in this article.
+
+### Trying Betas and Release Candidates[¶][4]
+
+When [go1.8beta2 was released][5], a new tool for trying the beta and release candidates was also released that allowed you to `go get` the beta. It allowed you to easily run the beta alongside your Go installation by getting the beta with:
+
+```
+go get golang.org/x/build/version/go1.8beta2
+```
+
+This downloads and builds a small program that will act like the `go` tool for that specific version. The full release can then be downloaded and installed with:
+
+```
+go1.8beta2 download
+```
+
+This downloads the release from [https://golang.org/dl][6] and installs it into `$HOME/sdk` or `%USERPROFILE%\sdk`.
+
+Now you can use `go1.8beta2` as if it were the normal Go command.
+
+This method works for [all the beta and release candidates][7] released after go1.8beta2.
+
+### Trying a Specific Release[¶][8]
+
+While only beta and release candidates are provided, they can easily be adapted to work with any released version. For example, to use go1.9.2:
+
+```
+package main
+
+import (
+ "golang.org/x/build/version"
+)
+
+func main() {
+ version.Run("go1.9.2")
+}
+```
+
+Replace `go1.9.2` with the release you want to run and build/install as usual.
+
+Since the program I use to build my [Guide to JSON][9] calls `go` itself (for each example), I build this as `go` and prepend the directory to my `PATH` so it will use this one instead of my normal version.
+
+### Trying Any Release[¶][10]
+
+This small program can be extended so you can specify the release to use instead of having to maintain binaries for each version.
+
+```
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "golang.org/x/build/version"
+)
+
+func main() {
+ if len(os.Args) < 2 {
+ fmt.Printf("USAGE: %v [commands as normal]\n",
+ os.Args[0])
+ os.Exit(1)
+ }
+
+ v := os.Args[1]
+ os.Args = append(os.Args[0:1], os.Args[2:]...)
+
+ version.Run("go" + v)
+}
+```
+
+I have this installed as `gov` and run it like `gov 1.8.6 version`, using the version I want to run.
+
+### Trying a Source Build (e.g., tip)[¶][11]
+
+I also use this same infrastructure to manage source builds of Go, such as tip. There’s just a little trick to it:
+
+* use the directory `$HOME/sdk/go` (e.g., `$HOME/sdk/gotip`)
+
+* [build as normal][1]
+
+* `touch $HOME/sdk/go/.unpacked-success` This is an empty file used as a sentinel to indicate the download and unpacking was successful.
+
+(On Windows, replace `$HOME/sdk` with `%USERPROFILE%\sdk`)
+
+
+--------------------------------------------------------------------------------
+
+via: https://pocketgophers.com/trying-other-versions/
+
+作者:[Nathan Kerr ][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:nathan@pocketgophers.com
+[1]:https://golang.org/doc/install/source
+[2]:https://pocketgophers.com/guide-to-json/
+[3]:https://pocketgophers.com/when-should-you-upgrade-go/
+[4]:https://pocketgophers.com/trying-other-versions/#trying-betas-and-release-candidates
+[5]:https://groups.google.com/forum/#!topic/golang-announce/LvfYP-Wk1s0
+[6]:https://golang.org/dl
+[7]:https://godoc.org/golang.org/x/build/version#pkg-subdirectories
+[8]:https://pocketgophers.com/trying-other-versions/#trying-a-specific-release
+[9]:https://pocketgophers.com/guide-to-json/
+[10]:https://pocketgophers.com/trying-other-versions/#trying-any-release
+[11]:https://pocketgophers.com/trying-other-versions/#trying-a-source-build-e-g-tip
\ No newline at end of file
diff --git a/sources/tech/20180130 Use of du - df commands (with examples).md b/sources/tech/20180130 Use of du - df commands (with examples).md
new file mode 100644
index 0000000000..ac284b0025
--- /dev/null
+++ b/sources/tech/20180130 Use of du - df commands (with examples).md
@@ -0,0 +1,112 @@
+translating---geekpi
+
+Use of du & df commands (with examples)
+======
+In this article I will discuss du & df commands. Both du & df commands are important utilities of Linux system & shows disk usage of Linux filesystem. Here we will share usage of both commands with some examples.
+
+**(Recommended Read:[Files transfer using scp & rsync commands][1])**
+
+ **(Also Read:[Cloning Disks using dd & cat commands for Linux systems][2])**
+
+### du COMMAND
+
+du command (short for disk usage) is useful command which is used to find disk usage for files & directories. du command when used with various options provides results in many formats.
+
+Some of the examples are mentioned below:-
+
+ **1- To find out summary of disk usage for a directory with all its sub-directories**
+
+```
+ $ du /home
+```
+
+![du command][4]
+
+Output of the command shows all the files & directories in /home with block size.
+
+**2- Disk usage with file/directory sizes in human readable format I.e. in kb, mb etc**
+
+```
+ $ du -h /home
+```
+
+![du command][6]
+
+**3- Total disk size of a directory**
+
+```
+ $ du -s /home
+```
+
+![du command][8]
+
+It will total size of /home directory.
+
+### df COMMAND
+
+df command (short for disk filesystem) is used to show disk utilization for a Linux system.
+
+Some examples are shared below.
+
+ **1- To display information of device name, total blocks, total disk space, used disk space, available disk space and mount points on a file system.**
+
+```
+ $ df
+```
+
+
+![df command][10]
+
+**2- Information in human readable format**
+
+```
+ $ df -h
+```
+
+![df command][12]
+
+Above command displays information in human readable format.
+
+**3- Display information of a particular partition**
+
+```
+ $ df -hT /etc
+```
+
+![df command][14]
+
+Using -hT with a target directory will show information of /etc/ in human readable format.
+
+Though there are many more options that can be used with du & df commands, but these should get you started. If you don't find what you are looking for here then you can always refer to man pages for the concerned command.
+
+Also, read my other posts [**HERE**][15] where i have shared some other important & frequently used Linux.
+
+And as always your comments/queries are really appreciated, so please leave your comments/queries down below & I will get back to you.
+
+
+--------------------------------------------------------------------------------
+
+via: http://linuxtechlab.com/du-df-commands-examples/
+
+作者:[SHUSAIN][a]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]:http://linuxtechlab.com/author/shsuain/
+[1]:http://linuxtechlab.com/files-transfer-scp-rsync-commands/
+[2]:http://linuxtechlab.com/linux-cloning-disks-using-dd-cat-commands/
+[3]:https://i1.wp.com/linuxtechlab.com/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif?resize=453%2C162
+[4]:https://i2.wp.com/linuxtechlab.com/wp-content/uploads/2017/02/du1.jpg?resize=453%2C162
+[5]:https://i1.wp.com/linuxtechlab.com/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif?resize=491%2C163
+[6]:https://i1.wp.com/linuxtechlab.com/wp-content/uploads/2017/02/du2.jpg?resize=491%2C163
+[7]:https://i1.wp.com/linuxtechlab.com/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif?resize=584%2C61
+[8]:https://i0.wp.com/linuxtechlab.com/wp-content/uploads/2017/02/du3.jpg?resize=584%2C61
+[9]:https://i1.wp.com/linuxtechlab.com/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif?resize=638%2C157
+[10]:https://i0.wp.com/linuxtechlab.com/wp-content/uploads/2017/02/df1.jpg?resize=638%2C157
+[11]:https://i1.wp.com/linuxtechlab.com/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif?resize=641%2C149
+[12]:https://i0.wp.com/linuxtechlab.com/wp-content/uploads/2017/02/df2.jpg?resize=641%2C149
+[13]:https://i1.wp.com/linuxtechlab.com/wp-content/plugins/a3-lazy-load/assets/images/lazy_placeholder.gif?resize=638%2C62
+[14]:https://i0.wp.com/linuxtechlab.com/wp-content/uploads/2017/02/df3-1.jpg?resize=638%2C62
+[15]:http://linuxtechlab.com/tips-tricks/
diff --git a/sources/tech/20180130 tmux - A Powerful Terminal Multiplexer For Heavy Command-Line Linux User.md b/sources/tech/20180130 tmux - A Powerful Terminal Multiplexer For Heavy Command-Line Linux User.md
new file mode 100644
index 0000000000..4adaa7a2bc
--- /dev/null
+++ b/sources/tech/20180130 tmux - A Powerful Terminal Multiplexer For Heavy Command-Line Linux User.md
@@ -0,0 +1,259 @@
+tmux – A Powerful Terminal Multiplexer For Heavy Command-Line Linux User
+======
+tmux stands for terminal multiplexer, it allows users to create/enable multiple terminals (vertical & horizontal) in single window, this can be accessed and controlled easily from single window when you are working with different issues.
+
+It uses a client-server model, which allows you to share sessions between users, also you can attach terminals to a tmux session back. We can easily move or rearrange the virtual console as per the need. Terminal sessions can freely rebound from one virtual console to another.
+
+tmux depends on libevent and ncurses libraries. tmux offers status-line at the bottom of the screen which display information about your current tmux session suc[]h as current window number, window name, username, hostname, current time, and current date.
+
+When tmux is started it creates a new session with a single window and displays it on screen. It allows users to create Any number of windows in the same session.
+
+Many of us says it's similar to screen but i'm not since this offers wide range of configuration options.
+
+**Make a note:** `Ctrl+b` is the default prefix in tmux so, to perform any action in tumx, you have to type the prefix first then required options.
+
+**Suggested Read :** [List Of Terminal Emulator For Linux][1]
+
+### tmux Features
+
+ * Create any number of windows
+ * Create any number of panes in the single window
+ * It allows vertical and horizontal splits
+ * Detach and Re-attach window
+ * Server-client architecture which allows users to share sessions between users
+ * tmux offers wide range of configuration hacks
+
+
+
+**Suggested Read :**
+**(#)** [tmate - Instantly Share Your Terminal Session To Anyone In Seconds][2]
+**(#)** [Teleconsole - A Tool To Share Your Terminal Session Instantly To Anyone In Seconds][3]
+
+### How to Install tmux Command
+
+tmux command is pre-installed by default in most of the Linux systems. If no, follow the below procedure to get installed.
+
+For **`Debian/Ubuntu`** , use [APT-GET Command][4] or [APT Command][5] to install tmux.
+```
+$ sudo apt install tmux
+
+```
+
+For **`RHEL/CentOS`** , use [YUM Command][6] to install tmux.
+```
+$ sudo yum install tmux
+
+```
+
+For **`Fedora`** , use [DNF Command][7] to install tmux.
+```
+$ sudo dnf install tmux
+
+```
+
+For **`Arch Linux`** , use [Pacman Command][8] to install tmux.
+```
+$ sudo pacman -S tmux
+
+```
+
+For **`openSUSE`** , use [Zypper Command][9] to install tmux.
+```
+$ sudo zypper in tmux
+
+```
+
+### How to Use tmux
+
+kick start the tmux session by running following command on terminal. When tmux is started it creates a new session with a single window and will automatically login to your default shell with your user account.
+```
+$ tmux
+
+```
+
+[![][10]![][10]][11]
+
+You will get similar to above screenshot like us. tmux comes with status bar which display an information's about current sessions details, date, time, etc.,.
+
+The status bar information's are below:
+
+ * **`0 :`** It is indicating the session number which was created by the tmux server. By default it starts with 0.
+ * **`0:username@host: :`** 0 is indicating the session number. Username and Hostname which is holding the current window.
+ * **`~ :`** It is indicating the current directory (We are in the Home directory)
+ * **`* :`** This indicate that the window is active now.
+ * **`Hostname :`** This shows fully qualified hostname of the server
+ * **`Date& Time:`** It shows current date and time
+
+
+
+### How to Split Window
+
+tmux allows users to split window vertically and horizontally. Let 's see how to do that.
+
+Press `**(Ctrl+b), %**` to split the pane vertically.
+[![][10]![][10]][13]
+
+Press `**(Ctrl+b), "**` to split the pane horizontally.
+[![][10]![][10]][14]
+
+### How to Move Between Panes
+
+Lets say, we have created few panes and want to move between them. How to do that? If you don 't know how to do, then there is no purpose to use tmux. Use the following control keys to perform the actions. There are many ways to move between panes.
+
+Press `(Ctrl+b), Left arrow` - To Move Left
+
+Press `(Ctrl+b), Right arrow` - To Move Right
+
+Press `(Ctrl+b), Up arrow` - To Move Up
+
+Press `(Ctrl+b), Down arrow` - To Move Down
+
+Press `(Ctrl+b), {` - To Move Left
+
+Press `(Ctrl+b), }` - To Move Right
+
+Press `(Ctrl+b), o` - Switch to next pane (left-to-right, top-down)
+
+Press `(Ctrl+b), ;` - Move to the previously active pane.
+
+For testing purpose, we are going to move between panes. Now, we are in the `pane2` which shows `lsb_release -a` command output.
+[![][10]![][10]][15]
+
+And we are going to move to `pane0` which shows `uname -a` command output.
+[![][10]![][10]][16]
+
+### How to Open/Create New Window
+
+You can open any number of windows within one terminal. Terminal window can be split vertically & horizontally which is called `panes`. Each pane will contain its own, independently running terminal instance.
+
+Press `(Ctrl+b), c` to create a new window.
+
+Press `(Ctrl+b), n` move to the next window.
+
+Press `(Ctrl+b), p` to move to the previous window.
+
+Press `(Ctrl+b), (0-9)` to immediately move to a specific window.
+
+Press `(Ctrl+b), l` Move to the previously selected window.
+
+I have two windows, first window has three panes which contains operating system distribution information, top command output & kernal information.
+[![][10]![][10]][17]
+
+And second window has two panes which contains Linux distributions logo information. Use the following commands perform the action.
+[![][10]![][10]][18]
+
+Press `(Ctrl+b), w` Choose the current window interactively.
+[![][10]![][10]][19]
+
+### How to Zoom Panes
+
+You are working in some pane which is very small and you want to zoom it out for further work. To do use the following key binds.
+
+Currently we have three panes and i'm working in `pane1` which shows system activity using **Top** command and am going to zoom that.
+[![][10]![][10]][17]
+
+When you zoom a pane, it will hide all other panes and display only the zoomed pane in the window.
+[![][10]![][10]][20]
+
+Press `(Ctrl+b), z` to zoom the pane and press it again, to bring the zoomed pane back.
+
+### Display Pane Information
+
+To know about pane number and it's size, run the following command.
+
+Press `(Ctrl+b), q` to briefly display pane indexes.
+[![][10]![][10]][21]
+
+### Display Window Information
+
+To know about window number, layout size, number of panes associated with the window and it's size, etc., run the following command.
+
+Just run `tmux list-windows` to view window information.
+[![][10]![][10]][22]
+
+### How to Resize Panes
+
+You may want to resize the panes to fit your requirement. You have to press `(Ctrl+b), :` then type the following details on the `yellow` color bar in the bottom of the page.
+[![][10]![][10]][23]
+
+In the previous section we have print pane index which shows panes size as well. To test this we are going to increase `10 cells UPward`. See the following output that has increased the pane1 & pane2 size from `55x21` to `55x31`.
+[![][10]![][10]][24]
+
+**Syntax:** `(Ctrl+b), :` then type `resize-pane [options] [cells size]`
+
+`(Ctrl+b), :` then type `resize-pane -D 10` to resize the current pane Down for 10 cells.
+
+`(Ctrl+b), :` then type `resize-pane -U 10` to resize the current pane UPward for 10 cells.
+
+`(Ctrl+b), :` then type `resize-pane -L 10` to resize the current pane Left for 10 cells.
+
+`(Ctrl+b), :` then type `resize-pane -R 10` to resize the current pane Right for 10 cells.
+
+### Detaching and Re-attaching tmux Session
+
+One of the most powerful features of tmux is the ability to detach and reattach session whenever you need.
+
+Run a long running process and press `Ctrl+b` followed by `d` to detach your tmux session safely by leaving the running process.
+
+**Suggested Read :** [How To Keep A Process/Command Running After Disconnecting SSH Session][25]
+
+Now, run a long running process. For demonstration purpose, we are going to move this server backup to another remote server for disaster recovery (DR) purpose.
+
+You will get similar output like below after detached tmux session.
+```
+[detached (from session 0)]
+
+```
+
+Run the following command to list the available tmux sessions.
+```
+$ tmux ls
+0: 3 windows (created Tue Jan 30 06:17:47 2018) [109x45]
+
+```
+
+Now, re-attach the tmux session using an appropriate session ID as follow.
+```
+$ tmux attach -t 0
+
+```
+
+### How to Close Panes & Window
+
+Just type `exit` or hit `Ctrl-d` in the corresponding pane to close it. It's similar to terminal close. To close window, press `(Ctrl+b), &`.
+
+--------------------------------------------------------------------------------
+
+via: https://www.2daygeek.com/tmux-a-powerful-terminal-multiplexer-emulator-for-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/category/terminal-emulator/
+[2]:https://www.2daygeek.com/tmate-instantly-share-your-terminal-session-to-anyone-in-seconds/
+[3]:https://www.2daygeek.com/teleconsole-share-terminal-session-instantly-to-anyone-in-seconds/
+[4]:https://www.2daygeek.com/apt-get-apt-cache-command-examples-manage-packages-debian-ubuntu-systems/
+[5]:https://www.2daygeek.com/apt-command-examples-manage-packages-debian-ubuntu-systems/
+[6]:https://www.2daygeek.com/yum-command-examples-manage-packages-rhel-centos-systems/
+[7]:https://www.2daygeek.com/dnf-command-examples-manage-packages-fedora-system/
+[8]:https://www.2daygeek.com/pacman-command-examples-manage-packages-arch-linux-system/
+[9]:https://www.2daygeek.com/zypper-command-examples-manage-packages-opensuse-system/
+[10]:data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
+[11]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-1.png
+[13]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-2.png
+[14]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-3.png
+[15]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-4.png
+[16]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-5.png
+[17]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-8.png
+[18]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-6.png
+[19]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-7.png
+[20]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-9.png
+[21]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-10.png
+[22]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-14.png
+[23]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-11.png
+[24]:https://www.2daygeek.com/wp-content/uploads/2018/01/tmux-a-powerful-terminal-multiplexer-emulator-for-linux-13.png
+[25]:https://www.2daygeek.com/how-to-keep-a-process-command-running-after-disconnecting-ssh-session/
diff --git a/sources/tech/20180131 10 things I love about Vue.md b/sources/tech/20180131 10 things I love about Vue.md
new file mode 100644
index 0000000000..55b9007ce1
--- /dev/null
+++ b/sources/tech/20180131 10 things I love about Vue.md
@@ -0,0 +1,128 @@
+10 things I love about Vue
+============================================================
+
+
+
+I love Vue. When I first looked at it in 2016, perhaps I was coming from a perspective of JavaScript framework fatigue. I’d already had experience with Backbone, Angular, React, among others and I wasn’t overly enthusiastic to try a new framework. It wasn’t until I read a comment on hacker news describing Vue as the ‘new jquery’ of JavaScript, that my curiosity was piqued. Until that point, I had been relatively content with React — it is a good framework based on solid design principles centred around view templates, virtual DOM and reacting to state, and Vue also provides these great things. In this blog post, I aim to explore why Vue is the framework for me. I choose it above any other that I have tried. Perhaps you will agree with some of my points, but at the very least I hope to give you some insight into what it is like to develop modern JavaScript applications with Vue.
+
+1\. Minimal Template Syntax
+
+The template syntax which you are given by default from Vue is minimal, succinct and extendable. Like many parts of Vue, it’s easy to not use the standard template syntax and instead use something like JSX (there is even an official page of documentation about how to do this), but I don’t know why you would want to do that to be honest. For all that is good about JSX, there are some valid criticisms: by blurring the line between JavaScript and HTML, it makes it a bit too easy to start writing complex code in your template which should instead be separated out and written elsewhere in your JavaScript view code.
+
+Vue instead uses standard HTML to write your templates, with a minimal template syntax for simple things such as iteratively creating elements based on the view data.
+
+```
+
+
+
+
{{ number }}
+
+
+
+
+
+
+
+
+```
+
+
+I also like the short-bindings provided by Vue, ‘:’ for binding data variables into your template and ‘@’ for binding to events. It’s a small thing, but it feels nice to type and keeps your components succinct.
+
+2\. Single File Components
+
+When most people write Vue, they do so using ‘single file components’. Essentially it is a file with the suffix .vue containing up to 3 parts (the css, html and javascript) for each component.
+
+This coupling of technologies feels right. It makes it easy to understand each component in a single place. It also has the nice side effect of encouraging you to keep your code short for each component. If the JavaScript, CSS and HTML for your component is taking up too many lines then it might be time to modularise further.
+
+When it comes to the .
+
+* Linked stylesheet: We write styles of all the elements in a separate file with .css extension. This file is called Stylesheet.
+
+Let’s have a look at how we defined the inline style of the “div” until now:
+
+```
+
+```
+
+We can write this same style inside `` like this:
+
+```
+div{
+ width:550px;
+}
+```
+
+In embedded styling, the styles we write are separate from the elements. So we need a way to relate the element and its style. The first word “div” does exactly that. It lets the browser know that whatever style is inside the curly braces `{…}` belongs to the “div” element. Since this phrase determines which element to apply the style to, it’s called a selector.
+
+The way we write style remains same: property(width) and value(550px) separated by a colon(:) and ended by a semicolon(;).
+
+Let’s remove inline style from our “div” and “img” element and write it inside the `
+```
+
+```
+
+
Bat Letter
+
+
+ After all the battles we faught together, after all the difficult times we saw together, after all the good and bad moments we've been through, I think it's time I let you know how I feel about you.
+
+```
+
+```
+
You are the light of my life
+
+ You complete my darkness with your light. I love:
+
+
+
the way you see good in the worse
+
the way you handle emotionally difficult situations
+
the way you look at Justice
+
+
+ I have learned a lot from you. You have occupied a special place in my heart over the time.
+
+
I have a confession to make
+
+ It feels like my chest does have a heart. You make my heart beat. Your smile brings smile on my face, your pain brings pain to my heart.
+
+
+ I don't show my emotions, but I think this man behind the mask is falling for you.
+
+
I love you Superman.
+
+ Your not-so-secret-lover,
+ Batman
+
+
+```
+
+Save and refresh, and the result should remain the same.
+
+There is one big problem though — what if there is more than one “div” and “img” element in our HTML file? The styles that we defined for div and img inside the “style” element will apply to every div and img on the page.
+
+If you add another div in your code in the future, then that div will also become 550px wide. We don’t want that.
+
+We want to apply our styles to the specific div and img that we are using right now. To do this, we need to give our div and img element unique ids. Here’s how you can give an id to an element using its “id” attribute:
+
+```
+
+```
+
+and here’s how to use this id in our embedded style as a selector:
+
+```
+#letter-container{
+ ...
+}
+```
+
+Notice the “#” symbol. It indicates that it is an id, and the styles inside {…} should apply to the element with that specific id only.
+
+Let’s apply this to our code:
+
+```
+
+```
+
+```
+
+
Bat Letter
+
+
+ After all the battles we faught together, after all the difficult times we saw together, after all the good and bad moments we've been through, I think it's time I let you know how I feel about you.
+
+```
+
+```
+
You are the light of my life
+
+ You complete my darkness with your light. I love:
+
+
+
the way you see good in the worse
+
the way you handle emotionally difficult situations
+
the way you look at Justice
+
+
+ I have learned a lot from you. You have occupied a special place in my heart over the time.
+
+
I have a confession to make
+
+ It feels like my chest does have a heart. You make my heart beat. Your smile brings smile on my face, your pain brings pain to my heart.
+
+
+ I don't show my emotions, but I think this man behind the mask is falling for you.
+
+
I love you Superman.
+
+ Your not-so-secret-lover,
+ Batman
+
+
+```
+
+Our HTML is ready with embedded styling.
+
+However, you can see that as we include more styles, the will get bigger. This can quickly clutter our main html file. So let’s go one step further and use linked styling by copying the content inside our style tag to a new file.
+
+Create a new file in the project root directory and save it as style.css:
+
+```
+#letter-container{
+ width:550px;
+}
+#header-bat-logo{
+ width:100%;
+}
+```
+
+We don’t need to write `` in our CSS file.
+
+We need to link our newly created CSS file to our HTML file using the ``tag in our html file. Here’s how we can do that:
+
+```
+
+```
+
+We use the link element to include external resources inside your HTML document. It is mostly used to link Stylesheets. The three attributes that we are using are:
+
+* rel: Relation. What relationship the linked file has to the document. The file with the .css extension is called a stylesheet, and so we keep rel=“stylesheet”.
+
+* type: the Type of the linked file; it’s “text/css” for a CSS file.
+
+* href: Hypertext Reference. Location of the linked file.
+
+There is no at the end of the link element. So, is also a self-closing tag.
+
+```
+
+```
+
+If only getting a Girlfriend was so easy :D
+
+Nah, that’s not gonna happen, let’s move on.
+
+Here’s the content of our loveletter.html:
+
+```
+
+
+
Bat Letter
+
+
+ After all the battles we faught together, after all the difficult times we saw together, after all the good and bad moments we've been through, I think it's time I let you know how I feel about you.
+
+
You are the light of my life
+
+ You complete my darkness with your light. I love:
+
+
+
the way you see good in the worse
+
the way you handle emotionally difficult situations
+
the way you look at Justice
+
+
+ I have learned a lot from you. You have occupied a special place in my heart over the time.
+
+
I have a confession to make
+
+ It feels like my chest does have a heart. You make my heart beat. Your smile brings smile on my face, your pain brings pain to my heart.
+
+
+ I don't show my emotions, but I think this man behind the mask is falling for you.
+
+
I love you Superman.
+
+ Your not-so-secret-lover,
+ Batman
+
+
+```
+
+and our style.css:
+
+```
+#letter-container{
+ width:550px;
+}
+#header-bat-logo{
+ width:100%;
+}
+```
+
+Save both the files and refresh, and your output in the browser should remain the same.
+
+### A Few Formalities
+
+Our love letter is almost ready to deliver to Batman, but there are a few formal pieces remaining.
+
+Like any other programming language, HTML has also gone through many versions since its birth year(1990). The current version of HTML is HTML5.
+
+So, how would the browser know which version of HTML you are using to code your page? To tell the browser that you are using HTML5, you need to include `` at top of the page. For older versions of HTML, this line used to be different, but you don’t need to learn that because we don’t use them anymore.
+
+Also, in previous HTML versions, we used to encapsulate the entire document inside `` tag. The entire file was divided into two major sections: Head, inside ``, and Body, inside ``. This is not required in HTML5, but we still do this for compatibility reasons. Let’s update our code with ``, ``, `` and ``:
+
+```
+
+
+
+
+
+
+
+
Bat Letter
+
+
+ After all the battles we faught together, after all the difficult times we saw together, after all the good and bad moments we've been through, I think it's time I let you know how I feel about you.
+
+
You are the light of my life
+
+ You complete my darkness with your light. I love:
+
+
+
the way you see good in the worse
+
the way you handle emotionally difficult situations
+
the way you look at Justice
+
+
+ I have learned a lot from you. You have occupied a special place in my heart over the time.
+
+
I have a confession to make
+
+ It feels like my chest does have a heart. You make my heart beat. Your smile brings smile on my face, your pain brings pain to my heart.
+
+
+ I don't show my emotions, but I think this man behind the mask is falling for you.
+
+
I love you Superman.
+
+ Your not-so-secret-lover,
+ Batman
+
+
+
+
+```
+
+The main content goes inside `` and meta information goes inside ``. So we keep the div inside `` and load the stylesheets inside ``.
+
+Save and refresh, and your HTML page should display the same as earlier.
+
+### Title in HTML
+
+This is the last change. I promise.
+
+You might have noticed that the title of the tab is displaying the path of the HTML file:
+
+
+
+
+We can use `` tag to define a title for our HTML file. The title tag also, like the link tag, goes inside head. Let’s put “Bat Letter” in our title:
+
+```
+
+
+
+ Bat Letter
+
+
+
+
+
Bat Letter
+
+
+ After all the battles we faught together, after all the difficult times we saw together, after all the good and bad moments we've been through, I think it's time I let you know how I feel about you.
+
+
You are the light of my life
+
+ You complete my darkness with your light. I love:
+
+
+
the way you see good in the worse
+
the way you handle emotionally difficult situations
+
the way you look at Justice
+
+
+ I have learned a lot from you. You have occupied a special place in my heart over the time.
+
+
I have a confession to make
+
+ It feels like my chest does have a heart. You make my heart beat. Your smile brings smile on my face, your pain brings pain to my heart.
+
+
+ I don't show my emotions, but I think this man behind the mask is falling for you.
+
+
I love you Superman.
+
+ Your not-so-secret-lover,
+ Batman
+
+
+
+
+```
+
+Save and refresh, and you will see that instead of the file path, “Bat Letter” is now displayed on the tab.
+
+Batman’s Love Letter is now complete.
+
+Congratulations! You made Batman’s Love Letter in HTML.
+
+
+
+
+### What we learned
+
+We learned the following new concepts:
+
+* The structure of an HTML document
+
+* How to write elements in HTML ()
+
+* How to write styles inside the element using the style attribute (this is called inline styling, avoid this as much as you can)
+
+* How to write styles of an element inside (this is called embedded styling)
+
+* How to write styles in a separate file and link to it in HTML using (this is called a linked stylesheet)
+
+* What is a tag name, attribute, opening tag, and closing tag
+
+* How to give an id to an element using id attribute
+
+* Tag selectors and id selectors in CSS
+
+We learned the following HTML tags:
+
+*
: for paragraphs
+
+* : for line breaks
+
+*
,
: to display lists
+
+*
: for grouping elements of our letter
+
+*
,
: for heading and sub heading
+
+* : to insert an image
+
+* , : for bold and italic text styling
+
+*