+ {{ range .List }}
+ {{ template "list_element" . }}
+ {{ end }}
+
+```
+
+You’re now rendering the `list_element` template with the list element from `.List`. But what if you want to also pass the current user `.User`? Unfortunately, you can only pass one argument from one template to another. If you have two arguments you want to pass to another template, with the standard library, you’re out of luck.
+
+The [whtmpl][65] package adds three helper functions to aid you here, `makepair`, `makemap`, and `makeslice` (more docs under the [whtmpl.Collection][66] type). `makepair` is the simplest. It takes two arguments and constructs a [whtmpl.Pair][67]. Fixing our example above would look like this now:
+
+```
+
+```
+
+The second thing [whtmpl][65] does is make defining lots of templates easy, by optionally automatically naming templates after the name of the file the template is defined in.
+
+For example, say you have three files.
+
+Here’s `pkg.go`:
+
+```
+package views
+
+import "gopkg.in/webhelp.v1/whtmpl"
+
+var Templates = whtmpl.NewCollection()
+```
+
+Here’s `landing.go`:
+
+```
+package views
+
+var _ = Templates.MustParse(`{{ template "header" . }}
+
+
Landing!
`)
+```
+
+And here’s `header.go`:
+
+```
+package views
+
+var _ = Templates.MustParse(`My website!`)
+```
+
+Now, you can import your new `views` package and render the `landing` template this easily:
+
+```
+func handler(w http.ResponseWriter, req *http.Request) {
+ views.Templates.Render(w, req, "landing", map[string]interface{}{})
+}
+```
+
+### User authentication
+
+I’ve written two Webhelp-style authentication libraries that I end up using frequently.
+
+The first is an OAuth2 library, [whoauth2][68]. I’ve written up [an example application that authenticates with Google, Facebook, and Github][69].
+
+The second, [whgoth][70], is a wrapper around [markbates/goth][71]. My portion isn’t quite complete yet (some fixes are still necessary for optional App Engine support), but will support more non-OAuth2 authentication sources (like Twitter) when it is done.
+
+### Route listing
+
+Surprise! If you’ve used [webhelp][27] based handlers and middleware for your whole app, you automatically get route listing for free, via the [whroute][72] package.
+
+My web serving code’s `main` method often has a form like this:
+
+```
+switch flag.Arg(0) {
+case "serve":
+ panic(whlog.ListenAndServe(*listenAddr, routes))
+case "routes":
+ whroute.PrintRoutes(os.Stdout, routes)
+default:
+ fmt.Printf("Usage: %s \n", os.Args[0])
+}
+```
+
+Here’s some example output:
+
+```
+GET /auth/_cb/
+GET /auth/login/
+GET /auth/logout/
+GET /
+GET /account/apikeys/
+POST /account/apikeys/
+GET /project//
+GET /project//control//
+POST /project//control//sample/
+GET /project//control/
+ Redirect: f(req)
+POST /project//control/
+POST /project//control_named//sample/
+GET /project//control_named/
+ Redirect: f(req)
+GET /project//sample//
+GET /project//sample//similar[/<*>]
+GET /project//sample/
+ Redirect: f(req)
+POST /project//search/
+GET /project/
+ Redirect: /
+POST /project/
+```
+
+### Other little things
+
+[webhelp][27] has a number of other subpackages:
+
+ * [whparse][73] assists in parsing optional request arguments.
+ * [whredir][74] provides some handlers and helper methods for doing redirects in various cases.
+ * [whcache][75] creates request-specific mutable storage for caching various computations and database loaded data. Mutability helps helper functions that aren’t used as middleware share data.
+ * [whfatal][76] uses panics to simplify early request handling termination. Probably avoid this package unless you want to anger other Go developers.
+
+
+
+### Summary
+
+Designing your web project as a collection of composable middlewares goes quite a long way to simplify your code design, eliminate cross-cutting concerns, and create a more flexible development environment. Use my [webhelp][27] package if it helps you.
+
+Or don’t! Whatever! It’s still a free country last I checked.
+
+#### Update
+
+Peter Kieltyka points me to his [Chi framework][77], which actually does seem to do the right things with respect to middleware, handlers, and contexts - certainly much more so than all the other frameworks I’ve seen. So, shoutout to Peter and the team at Pressly!
+
+--------------------------------------------------------------------------------
+
+via: https://www.jtolio.com/2017/01/writing-advanced-web-applications-with-go
+
+作者:[jtolio.com][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.jtolio.com/
+[b]: https://github.com/lujun9972
+[1]: https://www.ruby-lang.org/
+[2]: http://rubyonrails.org/
+[3]: http://www.sinatrarb.com/
+[4]: https://www.python.org/
+[5]: https://www.djangoproject.com/
+[6]: http://flask.pocoo.org/
+[7]: https://golang.org/
+[8]: https://groups.google.com/d/forum/golang-nuts
+[9]: https://www.reddit.com/r/golang/
+[10]: https://revel.github.io/
+[11]: https://gin-gonic.github.io/gin/
+[12]: http://iris-go.com/
+[13]: https://beego.me/
+[14]: https://go-macaron.com/
+[15]: https://github.com/go-martini/martini
+[16]: https://github.com/gocraft/web
+[17]: https://github.com/urfave/negroni
+[18]: https://godoc.org/goji.io
+[19]: https://echo.labstack.com/
+[20]: https://medium.com/code-zen/why-i-don-t-use-go-web-frameworks-1087e1facfa4
+[21]: https://groups.google.com/forum/#!topic/golang-nuts/R_lqsTTBh6I
+[22]: https://www.reddit.com/r/golang/comments/1yh6gm/new_to_go_trying_to_select_web_framework/
+[23]: https://golang.org/pkg/net/http/#Handler
+[24]: https://golang.org/pkg/net/http/#Request
+[25]: https://golang.org/pkg/net/http/#Request.Context
+[26]: https://golang.org/pkg/net/http/#Request.WithContext
+[27]: https://godoc.org/gopkg.in/webhelp.v1
+[28]: https://golang.org/doc/articles/wiki/
+[29]: https://expressjs.com/
+[30]: https://nodejs.org/en/
+[31]: https://en.wikipedia.org/wiki/Cross-cutting_concern
+[32]: https://github.com/gorilla/mux
+[33]: https://github.com/gorilla/
+[34]: https://golang.org/pkg/net/http/#ServeMux
+[35]: https://swtch.com/~rsc/
+[36]: https://github.com/rsc/tiddly
+[37]: https://github.com/rsc/tiddly/blob/8f9145ac183e374eb95d90a73be4d5f38534ec47/tiddly.go#L201
+[38]: https://godoc.org/gopkg.in/webhelp.v1/whmux#Dir
+[39]: https://godoc.org/gopkg.in/webhelp.v1/whmux
+[40]: https://godoc.org/gopkg.in/webhelp.v1/whmux#IntArg
+[41]: https://godoc.org/gopkg.in/webhelp.v1/whmux#StringArg
+[42]: https://golang.org/pkg/context/
+[43]: https://blog.golang.org/context
+[44]: https://godoc.org/golang.org/x/net/context
+[45]: https://godoc.org/gopkg.in/webhelp.v1#GenSym
+[46]: https://godoc.org/gopkg.in/webhelp.v1/whcompat
+[47]: https://godoc.org/gopkg.in/webhelp.v1/whcompat#DoneNotify
+[48]: https://godoc.org/gopkg.in/webhelp.v1/whcompat#CloseNotify
+[49]: https://godoc.org/gopkg.in/webhelp.v1/wherr
+[50]: https://godoc.org/gopkg.in/webhelp.v1/wherr#Handle
+[51]: https://godoc.org/gopkg.in/webhelp.v1/wherr#pkg-variables
+[52]: https://godoc.org/github.com/spacemonkeygo/errors
+[53]: https://godoc.org/github.com/spacemonkeygo/errors/errhttp
+[54]: https://github.com/zeebo/errs
+[55]: https://godoc.org/gopkg.in/webhelp.v1/whsess
+[56]: https://godoc.org/golang.org/x/crypto/nacl/secretbox
+[57]: https://godoc.org/gopkg.in/webhelp.v1/whlog
+[58]: https://godoc.org/gopkg.in/webhelp.v1/whlog#LogRequests
+[59]: https://godoc.org/gopkg.in/webhelp.v1/whlog#LogResponses
+[60]: https://godoc.org/gopkg.in/webhelp.v1/whlog#ListenAndServe
+[61]: https://godoc.org/gopkg.in/webhelp.v1/whmon
+[62]: https://godoc.org/gopkg.in/webhelp.v1/whgls
+[63]: https://godoc.org/github.com/jtolds/gls
+[64]: https://golang.org/pkg/html/template/
+[65]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl
+[66]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl#Collection
+[67]: https://godoc.org/gopkg.in/webhelp.v1/whtmpl#Pair
+[68]: https://godoc.org/gopkg.in/go-webhelp/whoauth2.v1
+[69]: https://github.com/go-webhelp/whoauth2/blob/v1/examples/group/main.go
+[70]: https://godoc.org/gopkg.in/go-webhelp/whgoth.v1
+[71]: https://github.com/markbates/goth
+[72]: https://godoc.org/gopkg.in/webhelp.v1/whroute
+[73]: https://godoc.org/gopkg.in/webhelp.v1/whparse
+[74]: https://godoc.org/gopkg.in/webhelp.v1/whredir
+[75]: https://godoc.org/gopkg.in/webhelp.v1/whcache
+[76]: https://godoc.org/gopkg.in/webhelp.v1/whfatal
+[77]: https://github.com/pressly/chi
diff --git a/sources/tech/20180425 An introduction to the GNU Core Utilities - Opensource.com.md b/sources/tech/20180425 An introduction to the GNU Core Utilities - Opensource.com.md
deleted file mode 100644
index aaa5a6ca00..0000000000
--- a/sources/tech/20180425 An introduction to the GNU Core Utilities - Opensource.com.md
+++ /dev/null
@@ -1,146 +0,0 @@
-An introduction to the GNU Core Utilities
-======
-
-
-
-Image credits :
-
-[Bella67][1] via Pixabay. [CC0][2].
-
-Two sets of utilities—the [GNU Core Utilities][3] and util-linux—comprise many of the Linux system administrator's most basic and regularly used tools. Their basic functions allow sysadmins to perform many of the tasks required to administer a Linux computer, including management and manipulation of text files, directories, data streams, storage media, process controls, filesystems, and much more.
-
-These tools are indispensable because, without them, it is impossible to accomplish any useful work on a Unix or Linux computer. Given their importance, let's examine them.
-
-### GNU coreutils
-
-The Linux Terminal
-
-* [Top 7 terminal emulators for Linux][4]
-* [10 command-line tools for data analysis in Linux][5]
-* [Download Now: SSH cheat sheet][6]
-* [Advanced Linux commands cheat sheet][7]
-
-To understand the origins of the GNU Core Utilities, we need to take a short trip in the Wayback machine to the early days of Unix at Bell Labs. [Unix was written][8] so Ken Thompson, Dennis Ritchie, Doug McIlroy, and Joe Ossanna could continue with something they had started while working on a large multi-tasking and multi-user computer project called [Multics][9]. That little something was a game called Space Travel. As remains true today, it always seems to be the gamers who drive forward the technology of computing. This new operating system was much more limited than Multics, as only two users could log in at a time, so it was called Unics. This name was later changed to Unix.
-
-Over time, Unix turned out to be such a success that Bell Labs began essentially giving it away it to universities and later to companies for the cost of the media and shipping. Back in those days, system-level software was shared between organizations and programmers as they worked to achieve common goals within the context of system administration.
-
-Eventually, the [PHBs][10] at AT&T decided they should make money on Unix and started using more restrictive—and expensive—licensing. This was taking place at a time when software was becoming more proprietary, restricted, and closed. It was becoming impossible to share software with other users and organizations.
-
-Some people did not like this and fought it with free software. Richard M. Stallman, aka RMS, led a group of rebels who were trying to write an open and freely available operating system they called the GNU Operating System. This group created the GNU Utilities but didn't produce a viable kernel.
-
-When Linus Torvalds first wrote and compiled the Linux kernel, he needed a set of very basic system utilities to even begin to perform marginally useful work. The kernel does not provide commands or any type of command shell such as Bash. It is useless by itself. So, Linus used the freely available GNU Core Utilities and recompiled them for Linux. This gave him a complete, if quite basic, operating system.
-
-You can learn about all the individual programs that comprise the GNU Utilities by entering the command info coreutils at a terminal command line. The following list of the core utilities is part of that info page. The utilities are grouped by function to make specific ones easier to find; in the terminal, highlight the group you want more information on and press the Enter key.
-
-```
-* Output of entire files:: cat tac nl od base32 base64
-* Formatting file contents:: fmt pr fold
-* Output of parts of files:: head tail split csplit
-* Summarizing files:: wc sum cksum b2sum md5sum sha1sum sha2
-* Operating on sorted files:: sort shuf uniq comm ptx tsort
-* Operating on fields:: cut paste join
-* Operating on characters:: tr expand unexpand
-* Directory listing:: ls dir vdir dircolors
-* Basic operations:: cp dd install mv rm shred
-* Special file types:: mkdir rmdir unlink mkfifo mknod ln link readlink
-* Changing file attributes:: chgrp chmod chown touch
-* Disk usage:: df du stat sync truncate
-* Printing text:: echo printf yes
-* Conditions:: false true test expr
-* Redirection:: tee
-* File name manipulation:: dirname basename pathchk mktemp realpath
-* Working context:: pwd stty printenv tty
-* User information:: id logname whoami groups users who
-* System context:: date arch nproc uname hostname hostid uptime
-* SELinux context:: chcon runcon
-* Modified command invocation:: chroot env nice nohup stdbuf timeout
-* Process control:: kill
-* Delaying:: sleep
-* Numeric operations:: factor numfmt seq
-```
-
-There are 102 utilities on this list. It covers many of the functions necessary to perform basic tasks on a Unix or Linux host. However, many basic utilities are missing. For example, the mount and umount commands are not in this list. Those and many of the other commands that are not in the GNU coreutils can be found in the util-linux collection.
-
-### util-linux
-
-The util-linix package of utilities contains many of the other common commands that sysadmins use. These utilities are distributed by the Linux Kernel Organization, and virtually every one of these 107 commands were originally three separate collections—fileutils, shellutils, and textutils—which were [combined into the single package][11] util-linux in 2003.
-
-```
-agetty fsck.minix mkfs.bfs setpriv
-blkdiscard fsfreeze mkfs.cramfs setsid
-blkid fstab mkfs.minix setterm
-blockdev fstrim mkswap sfdisk
-cal getopt more su
-cfdisk hexdump mount sulogin
-chcpu hwclock mountpoint swaplabel
-chfn ionice namei swapoff
-chrt ipcmk newgrp swapon
-chsh ipcrm nologin switch_root
-colcrt ipcs nsenter tailf
-col isosize partx taskset
-colrm kill pg tunelp
-column last pivot_root ul
-ctrlaltdel ldattach prlimit umount
-ddpart line raw unshare
-delpart logger readprofile utmpdump
-dmesg login rename uuidd
-eject look renice uuidgen
-fallocate losetup reset vipw
-fdformat lsblk resizepart wall
-fdisk lscpu rev wdctl
-findfs lslocks RTC Alarm whereis
-findmnt lslogins runuser wipefs
-flock mcookie script write
-fsck mesg scriptreplay zramctl
-fsck.cramfs mkfs setarch
-```
-
-Some of these utilities have been deprecated and will likely fall out of the collection at some point in the future. You should check [Wikipedia's util-linux page][12] for information on many of the utilities, and the man pages also provide details on the commands.
-
-### Summary
-
-These two collections of Linux utilities, the GNU Core Utilities and util-linux, together provide the basic utilities required to administer a Linux system. As I researched this article, I found several interesting utilities I never knew about. Many of these commands are seldom needed, but when you need them, they are indispensable.
-
-Between these two collections, there are over 200 Linux utilities. While Linux has many more commands, these are the ones needed to manage the basic functions of a typical Linux host.
-
-### About the author
-
-[][13]
-
-David Both \- David Both is a Linux and Open Source advocate who resides in Raleigh, North Carolina. He has been in the IT industry for over forty years and taught OS/2 for IBM where he worked for over 20 years. While at IBM, he wrote the first training course for the original IBM PC in 1981. He has taught RHCE classes for Red Hat and has worked at MCI Worldcom, Cisco, and the State of North Carolina. He has been working with Linux and Open Source Software for almost 20 years. David has written articles for... [more about David Both][14]
-
-[More about me][15]
-
-* [Learn how you can contribute][16]
-
----
-
-via: [https://opensource.com/article/18/4/gnu-core-utilities][17]
-
-作者: [David Both][18] 选题者: [@lujun9972][19] 译者: [译者ID][20] 校对: [校对者ID][21]
-
-本文由 [LCTT][22] 原创编译,[Linux中国][23] 荣誉推出
-
-[1]: https://pixabay.com/en/tiny-people-core-apple-apple-half-700921/
-[2]: https://creativecommons.org/publicdomain/zero/1.0/
-[3]: https://www.gnu.org/software/coreutils/coreutils.html
-[4]: https://opensource.com/life/17/10/top-terminal-emulators?intcmp=7016000000127cYAAQ
-[5]: https://opensource.com/article/17/2/command-line-tools-data-analysis-linux?intcmp=7016000000127cYAAQ
-[6]: https://opensource.com/downloads/advanced-ssh-cheat-sheet?intcmp=7016000000127cYAAQ
-[7]: https://developers.redhat.com/cheat-sheet/advanced-linux-commands-cheatsheet?intcmp=7016000000127cYAAQ
-[8]: https://en.wikipedia.org/wiki/History_of_Unix
-[9]: https://en.wikipedia.org/wiki/Multics
-[10]: https://en.wikipedia.org/wiki/Pointy-haired_Boss
-[11]: https://en.wikipedia.org/wiki/GNU_Core_Utilities
-[12]: https://en.wikipedia.org/wiki/Util-linux
-[13]: https://opensource.com/users/dboth
-[14]: https://opensource.com/users/dboth
-[15]: https://opensource.com/users/dboth
-[16]: https://opensource.com/participate
-[17]: https://opensource.com/article/18/4/gnu-core-utilities
-[18]: https://opensource.com/users/dboth
-[19]: https://github.com/lujun9972
-[20]: https://github.com/译者ID
-[21]: https://github.com/校对者ID
-[22]: https://github.com/LCTT/TranslateProject
-[23]: https://linux.cn/
diff --git a/sources/tech/20180612 Systemd Services- Reacting to Change.md b/sources/tech/20180612 Systemd Services- Reacting to Change.md
deleted file mode 100644
index a004f123c8..0000000000
--- a/sources/tech/20180612 Systemd Services- Reacting to Change.md
+++ /dev/null
@@ -1,275 +0,0 @@
-Systemd Services: Reacting to Change
-======
-
-
-
-[I have one of these Compute Sticks][1] (Figure 1) and use it as an all-purpose server. It is inconspicuous and silent and, as it is built around an x86 architecture, I don't have problems getting it to work with drivers for my printer, and that’s what it does most days: it interfaces with the shared printer and scanner in my living room.
-
-![ComputeStick][3]
-
-An Intel ComputeStick. Euro coin for size.
-
-[Used with permission][4]
-
-Most of the time it is idle, especially when we are out, so I thought it would be good idea to use it as a surveillance system. The device doesn't come with its own camera, and it wouldn't need to be spying all the time. I also didn't want to have to start the image capturing by hand because this would mean having to log into the Stick using SSH and fire up the process by writing commands in the shell before rushing out the door.
-
-So I thought that the thing to do would be to grab a USB webcam and have the surveillance system fire up automatically just by plugging it in. Bonus points if the surveillance system fired up also after the Stick rebooted, and it found that the camera was connected.
-
-In prior installments, we saw that [systemd services can be started or stopped by hand][5] or [when certain conditions are met][6]. Those conditions are not limited to when the OS reaches a certain state in the boot up or powerdown sequence but can also be when you plug in new hardware or when things change in the filesystem. You do that by combining a Udev rule with a systemd service.
-
-### Hotplugging with Udev
-
-Udev rules live in the _/etc/udev/rules_ directory and are usually a single line containing _conditions_ and _assignments_ that lead to an _action_.
-
-That was a bit cryptic. Let's try again:
-
-Typically, in a Udev rule, you tell systemd what to look for when a device is connected. For example, you may want to check if the make and model of a device you just plugged in correspond to the make and model of the device you are telling Udev to wait for. Those are the _conditions_ mentioned earlier.
-
-Then you may want to change some stuff so you can use the device easily later. An example of that would be to change the read and write permissions to a device: if you plug in a USB printer, you're going to want users to be able to read information from the printer (the user's printing app would want to know the model, make, and whether it is ready to receive print jobs or not) and write to it, that is, send stuff to print. Changing the read and write permissions for a device is done using one of the _assignments_ you read about earlier.
-
-Finally, you will probably want the system to do something when the conditions mentioned above are met, like start a backup application to copy important files when a certain external hard disk drive is plugged in. That is an example of an _action_ mentioned above.
-
-With that in mind, ponder this:
-
-```
-ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="e207",
-SYMLINK+="mywebcam", TAG+="systemd", MODE="0666", ENV{SYSTEMD_WANTS}="webcam.service"
-```
-
-The first part of the rule,
-
-```
-ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="03f0",
-ATTRS{idProduct}=="e207" [etc... ]
-```
-
-shows the conditions that the device has to meet before doing any of the other stuff you want the system to do. The device has to be added (`ACTION=="add"`) to the machine, it has to be integrated into the `video4linux` subsystem. To make sure the rule is applied only when the correct device is plugged in, you have to make sure Udev correctly identifies the manufacturer (`ATTRS{idVendor}=="03f0"`) and a model (`ATTRS{idProduct}=="e207"`) of the device.
-
-In this case, we're talking about this device (Figure 2):
-
-![webcam][8]
-
-The HP webcam used in this experiment.
-
-[Used with permission][4]
-
-Notice how you use `==` to indicate that these are a logical operation. You would read the above snippet of the rule like this:
-
-```
-if the device is added and the device controlled by the video4linux subsystem
-and the manufacturer of the device is 03f0 and the model is e207, then...
-```
-
-But where do you get all this information? Where do you find the action that triggers the event, the manufacturer, model, and so on? You will probably have to use several sources. The `IdVendor` and `idProduct` you can get by plugging the webcam into your machine and running `lsusb`:
-
-```
-lsusb
-Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
-Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
-Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
-Bus 003 Device 003: ID 03f0:e207 Hewlett-Packard
-Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
-Bus 001 Device 003: ID 04f2:b1bb Chicony Electronics Co., Ltd
-Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
-Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
-```
-
-The webcam I’m using is made by HP, and you can only see one HP device in the list above. The `ID` gives you the manufacturer and the model numbers separated by a colon (`:`). If you have more than one device by the same manufacturer and not sure which is which, unplug the webcam, run `lsusb` again and check what's missing.
-
-OR...
-
-Unplug the webcam, wait a few seconds, run the command `udevadmin monitor --environment` and then plug the webcam back in again. When you do that with the HP webcam, you get:
-
-```
-udevadmin monitor --environment
-UDEV [35776.495221] add /devices/pci0000:00/0000:00:1c.3/0000:04:00.0
- /usb3/3-1/3-1:1.0/input/input21/event11 (input)
-.MM_USBIFNUM=00
-ACTION=add
-BACKSPACE=guess
-DEVLINKS=/dev/input/by-path/pci-0000:04:00.0-usb-0:1:1.0-event
- /dev/input/by-id/usb-Hewlett_Packard_HP_Webcam_HD_2300-event-if00
-DEVNAME=/dev/input/event11
-DEVPATH=/devices/pci0000:00/0000:00:1c.3/0000:04:00.0/
- usb3/3-1/3-1:1.0/input/input21/event11
-ID_BUS=usb
-ID_INPUT=1
-ID_INPUT_KEY=1
-ID_MODEL=HP_Webcam_HD_2300
-ID_MODEL_ENC=HP\x20Webcam\x20HD\x202300
-ID_MODEL_ID=e207
-ID_PATH=pci-0000:04:00.0-usb-0:1:1.0
-ID_PATH_TAG=pci-0000_04_00_0-usb-0_1_1_0
-ID_REVISION=1020
-ID_SERIAL=Hewlett_Packard_HP_Webcam_HD_2300
-ID_TYPE=video
-ID_USB_DRIVER=uvcvideo
-ID_USB_INTERFACES=:0e0100:0e0200:010100:010200:030000:
-ID_USB_INTERFACE_NUM=00
-ID_VENDOR=Hewlett_Packard
-ID_VENDOR_ENC=Hewlett\x20Packard
-ID_VENDOR_ID=03f0
-LIBINPUT_DEVICE_GROUP=3/3f0/e207:usb-0000:04:00.0-1/button
-MAJOR=13
-MINOR=75
-SEQNUM=3162
-SUBSYSTEM=input
-USEC_INITIALIZED=35776495065
-XKBLAYOUT=es
-XKBMODEL=pc105
-XKBOPTIONS=
-XKBVARIANT=
-```
-
-That may look like a lot to process, but, check this out: the `ACTION` field early in the list tells you what event just happened, i.e., that a device got added to the system. You can also see the name of the device spelled out on several of the lines, so you can be pretty sure that it is the device you are looking for. The output also shows the manufacturer's ID number (`ID_VENDOR_ID=03f0`) and the model number (`ID_VENDOR_ID=03f0`).
-
-This gives you three of the four values the condition part of the rule needs. You may be tempted to think that it a gives you the fourth, too, because there is also a line that says:
-
-```
-SUBSYSTEM=input
-```
-
-Be careful! Although it is true that a USB webcam is a device that provides input (as does a keyboard and a mouse), it is also belongs to the _usb_ subsystem, and several others. This means that your webcam gets added to several subsystems and looks like several devices. If you pick the wrong subsystem, your rule may not work as you want it to, or, indeed, at all.
-
-So, the third thing you have to check is all the subsystems the webcam has got added to and pick the correct one. To do that, unplug your webcam again and run:
-
-```
-ls /dev/video*
-```
-
-This will show you all the video devices connected to the machine. If you are using a laptop, most come with a built-in webcam and it will probably show up as `/dev/video0`. Plug your webcam back in and run `ls /dev/video*` again.
-
-Now you should see one more video device (probably `/dev/video1`).
-
-Now you can find out all the subsystems it belongs to by running `udevadm info -a /dev/video1`:
-
-```
-udevadm info -a /dev/video1
-
-Udevadm info starts with the device specified by the devpath and then
-walks up the chain of parent devices. It prints for every device
-found, all possible attributes in the udev rules key format.
-A rule to match, can be composed by the attributes of the device
-and the attributes from one single parent device.
-
- looking at device '/devices/pci0000:00/0000:00:1c.3/0000:04:00.0
- /usb3/3-1/3-1:1.0/video4linux/video1':
- KERNEL=="video1"
- SUBSYSTEM=="video4linux"
- DRIVER==""
- ATTR{dev_debug}=="0"
- ATTR{index}=="0"
- ATTR{name}=="HP Webcam HD 2300: HP Webcam HD"
-
-[etc...]
-```
-
-The output goes on for quite a while, but what you're interested is right at the beginning: `SUBSYSTEM=="video4linux"`. This is a line you can literally copy and paste right into your rule. The rest of the output (not shown for brevity) gives you a couple more nuggets, like the manufacturer and mode IDs, again in a format you can copy and paste into your rule.
-
-Now you have a way of identifying the device and what event should trigger the action univocally, it is time to tinker with the device.
-
-The next section in the rule, `SYMLINK+="mywebcam", TAG+="systemd", MODE="0666"` tells Udev to do three things: First, you want to create symbolic link from the device to (e.g. _/dev/video1_ ) to _/dev/mywebcam_. This is because you cannot predict what the system is going to call the device by default. When you have an in-built webcam and you hotplug a new one, the in-built webcam will usually be _/dev/video0_ while the external one will become _/dev/video1_. However, if you boot your computer with the external USB webcam plugged in, that could be reversed and the internal webcam can become _/dev/video1_ and the external one _/dev/video0_. What this is telling you is that, although your image-capturing script (which you will see later on) always needs to point to the external webcam device, you can't rely on it being _/dev/video0_ or _/dev/video1_. To solve this problem, you tell Udev to create a symbolic link which will never change in the moment the device is added to the _video4linux_ subsystem and you will make your script point to that.
-
-The second thing you do is add `"systemd"` to the list of Udev tags associated with this rule. This tells Udev that the action that the rule will trigger will be managed by systemd, that is, it will be some sort of systemd service.
-
-Notice how in both cases you use `+=` operator. This adds the value to a list, which means you can add more than one value to `SYMLINK` and `TAG`.
-
-The `MODE` values, on the other hand, can only contain one value (hence you use the simple `=` assignment operator). What `MODE` does is tell Udev who can read from or write to the device. If you are familiar with `chmod` (and, if you are reading this, you should be), you will also be familiar of [how you can express permissions using numbers][9]. That is what this is: `0666` means " _give read and write privileges to the device to everybody_ ".
-
-At last, `ENV{SYSTEMD_WANTS}="webcam.service"` tells Udev what systemd service to run.
-
-Save this rule into file called _90-webcam.rules_ (or something like that) in _/etc/udev/rules.d_ and you can load it either by rebooting your machine, or by running:
-
-```
-sudo udevadm control --reload-rules && udevadm trigger
-```
-
-## Service at Last
-
-The service the Udev rule triggers is ridiculously simple:
-
-```
-# webcam.service
-
-[Service]
-Type=simple
-ExecStart=/home/[user name]/bin/checkimage.sh
-```
-
-Basically, it just runs the _checkimage.sh_ script stored in your personal _bin/_ and pushes it the background. [This is something you saw how to do in prior installments][5]. It may seem something little, but just because it is called by a Udev rule, you have just created a special kind of systemd unit called a _device_ unit. Congratulations.
-
-As for the _checkimage.sh_ script _webcam.service_ calls, there are several ways of grabbing an image from a webcam and comparing it to a prior one to check for changes (which is what _checkimage.sh_ does), but this is how I did it:
-
-```
-#!/bin/bash
-# This is the checkimage.sh script
-
-mplayer -vo png -frames 1 tv:// -tv driver=v4l2:width=640:height=480:device=
- /dev/mywebcam &>/dev/null
-mv 00000001.png /home/[user name]/monitor/monitor.png
-
-while true
-do
- mplayer -vo png -frames 1 tv:// -tv driver=v4l2:width=640:height=480:device=/dev/mywebcam &>/dev/null
- mv 00000001.png /home/[user name]/monitor/temp.png
-
- imagediff=`compare -metric mae /home/[user name]/monitor/monitor.png /home/[user name]
- /monitor/temp.png /home/[user name]/monitor/diff.png 2>&1 > /dev/null | cut -f 1 -d " "`
- if [ `echo "$imagediff > 700.0" | bc` -eq 1 ]
- then
- mv /home/[user name]/monitor/temp.png /home/[user name]/monitor/monitor.png
- fi
-
- sleep 0.5
-done
-```
-
-Start by using [MPlayer][10] to grab a frame ( _00000001.png_ ) from the webcam. Notice how we point `mplayer` to the `mywebcam` symbolic link we created in our Udev rule, instead of to `video0` or `video1`. Then you transfer the image to the _monitor/_ directory in your home directory. Then run an infinite loop that does the same thing again and again, but also uses [Image Magick's _compare_ tool][11] to see if there any differences between the last image captured and the one that is already in the _monitor/_ directory.
-
-If the images are different, it means something has moved within the webcam's frame. The script overwrites the original image with the new image and continues comparing waiting for some more movement.
-
-### Plugged
-
-With all the bits and pieces in place, when you plug your webcam in, your Udev rule will be triggered and will start the _webcam.service_. The _webcam.service_ will execute _checkimage.sh_ in the background, and _checkimage.sh_ will start taking pictures every half a second. You will know because your webcam's LED will start flashing indicating every time it takes a snap.
-
-As always, if something goes wrong, run
-
-```
-systemctl status webcam.service
-```
-
-to check what your service and script are up to.
-
-### Coming up
-
-You may be wondering: Why overwrite the original image? Surely you would want to see what's going on if the system detects any movement, right? You would be right, but as you will see in the next installment, leaving things as they are and processing the images using yet another type of systemd unit makes things nice, clean and easy.
-
-Just wait and see.
-
-Learn more about Linux through the free ["Introduction to Linux" ][12]course from The Linux Foundation and edX.
-
---------------------------------------------------------------------------------
-
-via: https://www.linux.com/blog/intro-to-linux/2018/6/systemd-services-reacting-change
-
-作者:[Paul Brown][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.linux.com/users/bro66
-[b]: https://github.com/lujun9972
-[1]: https://www.intel.com/content/www/us/en/products/boards-kits/compute-stick/stk1a32sc.html
-[2]: https://www.linux.com/files/images/fig01png
-[3]: https://www.linux.com/sites/lcom/files/styles/floated_images/public/fig01.png?itok=cfEHN5f1 (ComputeStick)
-[4]: https://www.linux.com/licenses/category/used-permission
-[5]: https://www.linux.com/blog/learn/intro-to-linux/2018/5/writing-systemd-services-fun-and-profit
-[6]: https://www.linux.com/blog/learn/2018/5/systemd-services-beyond-starting-and-stopping
-[7]: https://www.linux.com/files/images/fig02png
-[8]: https://www.linux.com/sites/lcom/files/styles/floated_images/public/fig02.png?itok=esFv4BdM (webcam)
-[9]: https://chmod-calculator.com/
-[10]: https://mplayerhq.hu/design7/news.html
-[11]: https://www.imagemagick.org/script/compare.php
-[12]: https://training.linuxfoundation.org/linux-courses/system-administration-training/introduction-to-linux
diff --git a/sources/tech/20180730 50 Best Ubuntu Apps You Should Be Using Right Now.md b/sources/tech/20180730 50 Best Ubuntu Apps You Should Be Using Right Now.md
deleted file mode 100644
index d305b716d6..0000000000
--- a/sources/tech/20180730 50 Best Ubuntu Apps You Should Be Using Right Now.md
+++ /dev/null
@@ -1,499 +0,0 @@
-50 Best Ubuntu Apps You Should Be Using Right Now
-======
-**Brief: A comprehensive list of best Ubuntu apps for all kind of users. These software will help you in getting a better experience with your Linux desktop.**
-
-I have written about [things to do after installing Ubuntu][1] several times in the past. Each time I suggest installing the essential applications in Ubuntu.
-
-But the question arises, what are the essential Ubuntu applications? There is no set answer here. It depends on your need and the kind of work you do on your Ubuntu desktop.
-
-Still, I have been asked to suggest some good Ubuntu apps by a number of readers. This is the reason I have created this comprehensive list of Ubuntu applications you can use regularly.
-
-The list has been divided into respective categories for ease of reading and ease of comprehension.
-
-### Best Ubuntu apps for a better Ubuntu experience
-
-![Best Ubuntu Apps][2]
-
-Of course, you don’t have to use all of these applications. Just go through this list of essential Ubuntu software, read the description and then install the ones you need or are inclined to use. Just keep this page bookmarked for future reference or simply search on Google with term ‘best ubuntu apps itsfoss’.
-
-The best Ubuntu application list is intended for average Ubuntu user. Therefore not all the applications here are open source. I have also marked the slightly complicated applications that might not be suitable for a beginner. The list should be valid for Ubuntu 16.04,18.04 and other versions.
-
-Unless exclusively mentioned, the software listed here are available in Ubuntu Software Center.
-
-If you don’t find any application in the software center or if it is missing installation instruction, let me know and I’ll add the installation procedure.
-
-Enough talk! Let’s see what are the best apps for Ubuntu.
-
-#### Web Browser
-
-Ubuntu comes with Firefox as the default web browser. Since the Quantum release, Firefox has improved drastically. Personally, I always use more than one web browser for the sake of distinguishing between different type of works.
-
-##### Google Chrome
-
-![Google Chrome Logo][3]
-
-Google Chrome is the most used web browser on the internet for a reason. With your Google account, it allows you seamless syncing across devices. Plenty of extensions and apps further enhance its capabilities. You can [download Chrome in Ubuntu from its website][4].
-
-##### Brave
-
-![brave browser][5]
-
-Google Chrome might be the most used web browser but it’s a privacy invader. An [alternative browser][6] is [Brave][7] that blocks ads and tracking scripts by default. This provides you with a faster and secure web browsing experience.
-
-#### Music applications
-
-![best music apps ubuntu][8]
-
-Ubuntu has Rhythmbox as the default music player which is not at all a bad choice for the default music player. However, you can definitely install a better music player.
-
-##### Sayonara
-
-[Sayonara][9] is a small, lightweight music player with a nice dark user interface. It comes with all the essential features you would expect in a standard music player. It integrates well with the Ubuntu desktop environment and doesn’t eat up your RAM.
-
-##### Audacity
-
-[Audacity][10] is more of an audio editor than an audio player. You can record and edit audio with this free and open source tool. It is available for Linux, Windows and macOS. You can install it from the Software Center.
-
-##### MusicBrainz Picard
-
-[Picard][11] is not a music player, it is a music tagger. If you have tons of local music files, Picard allows you to automatically update the music files with correct tracks, album, artist info and album cover art.
-
-#### Streaming Music Applications
-
-![Streaming Music app Ubuntu][12]
-
-In this age of the internet, music listening habit has surely changed. People these days rely more on streaming music players rather than storing hundreds of local music files. Let’s see some apps you can use for streaming music.
-
-##### Spotify
-
-[Spotify][13] is the king of streaming music. And the good thing is that it has a native Linux app. The [Spotify app on Ubuntu][14] integrates well with the media key and sound menu along with the desktop notification. Do note that Spotify may or may not be available in your country.
-
-##### Nuvola music player
-
-[Nuvola][15] is not a streaming music service like Spotify. It is a desktop music player that allows you to use several streaming music services in one application. You can use Spotify, Deezer, Google Play Music, Amazon Cloud Player and many more such services.
-
-#### Video Players
-
-![Video players for Linux][16]
-
-Ubuntu has the default GNOME video player (previously known as Totem) which is okay but it doesn’t support various media codecs. There are certainly other video players better than the GNOME video player.
-
-##### VLC
-
-The free and open source software [VLC][17] is the king of video players. It supports almost all possible media codecs. It also allows you to increase the volume up to 200%. It can also resume playing from the last known position. There are so many [VLC tricks][18] you can use to get the most of it.
-
-##### MPV
-
-[MPV][19] is a video player that deserves more attention. A sleek minimalist GUI and plenty of features, MPV has everything you would expect from a good video player. You can even use it in the command line. If you are not happy with VLC, you should surely give MPV a try.
-
-#### Cloud Storage Service
-
-Local backups are fine but cloud storage gives an additional degree of freedom. You don’t have to carry a USB key with you all the time or worry about a hard disk crash with cloud services.
-
-##### Dropbox
-
-![Dropbox logo][20]
-
-[Dropbox][21] is one of the most popular Cloud service providers. You get 2GB of free storage with the option to get more by referring others. Dropbox provides a native Linux client and you can download it from its website. It creates a local folder on your system that is synced with the cloud servers.
-
-##### pCloud
-
-![pCloud icon][22]
-
-[pCloud][23] is another good cloud storage service for Linux. It also has a native Linux client that you can download from its website. You get up to 20GB of free storage and if you need more, the pricing is better than Dropbox. pCloud is based in Switzerland, a country renowned for strict data privacy laws.
-
-#### Image Editors
-
-I am sure that you would need a photo editor at some point in time. Here are some of the best Ubuntu apps for editing images.
-
-##### GIMP
-
-![gimp icon][24]
-
-[GIMP][25] is a free and open source image editor available for Linux, Windows and macOS. It’s the best alternative for Adobe Photoshop in Linux. You can use it for all kind of image editing. There are plenty of resources available on the internet to help you with Gimp.
-
-##### Inkscape
-
-![inkscape icon][26]
-
-[Inkscape][27] is also a free and open source image editor specifically focusing on vector graphics. You can design vector arts and logo on it. You can compare it to Adobe Illustrator. Like Gimp, Inkscape too has plenty of tutorials available online.
-
-#### Paint applications
-
-Painting applications are not the same as image editors though their functionalities overlap at times. Here are some paint apps you can use in Ubuntu.
-![Painting apps for Ubuntu Linux][28]
-
-##### Krita
-
-[Krita][29] is a free and open source digital painting application. You can create digital art, comics and animation with it. It’s a professional grade software and is even used as the primary software in art schools.
-
-##### Pinta
-
-[Pinta][30] might not be as feature rich as Krita but that’s deliberate. You can think of Pinta as Microsoft Paint for Linux. You can draw, paint, add text and do other such small tasks you do in a paint application.
-
-#### Photography applications
-
-Amateur photographer or a professional? You have plenty of [photography tools][31] at your disposal. Here are some recommended applications.
-
-##### digiKam
-
-![digikam][32]
-
-With open source software [digiKam][33], you can handle your high-end camera images in a professional manner. digiKam provides all the tools required for viewing, managing, editing, enhancing, organizing, tagging and sharing photographs.
-
-##### Darktable
-
-![Darktable icon][34]
-
-[darktable][35] is an open source photography workflow application with a special focus on raw image development. This is the best alternative you can get for Adobe Lightroom. It is also available for Windows and macOS.
-
-#### Video editors
-
-![Video editors Ubuntu][36]
-
-There is no dearth of [video editors for Linux][37] but I won’t go in detail here. Take a look at some of the feature-rich yet relatively simple to use video editors for Ubuntu.
-
-##### Kdenlive
-
-[Kdenlive][38] is the best all-purpose video editor for Linux. It has enough features that compare it to iMovie or Movie Maker.
-
-##### Shotcut
-
-[Shotcut][39] is another good choice for a video editor. It is an open source software with all the features you can expect in a standard video editor.
-
-#### Image and video converter
-
-If you need to [convert the file format][40] of your images and videos, here are some of my recommendations.
-
-##### Xnconvert
-
-![xnconvert logo][41]
-
-[Xnconvert][42] is an excellent batch image conversion tool. You can bulk resize images, convert the file type and rename them.
-
-##### Handbrake
-
-![Handbrake Logo][43]
-
-[HandBrake][44] is an easy to use open source tool for converting videos from a number of formats to a few modern, popular formats.
-
-#### Screenshot and screen recording tools
-
-![Screenshot and recorders Ubuntu][45]
-
-Here are the best Ubuntu apps for taking screenshots and recording your screen.
-
-##### Shutter
-
-[Shutter][46] is my go-to tool for taking screenshots. You can also do some quick editing to those screenshots such as adding arrows, text or resizing the images. The screenshots you see on It’s FOSS have been edited with Shutter. Definitely one of the best apps for Ubuntu.
-
-##### Kazam
-
-[Kazam][47] is my favorite [screen recorder for Linux][48]. It’s a tiny tool that allows you to record the entire window, an application window or a selected area. You can also use shortcuts to pause or resume recording. The tutorials on [It’s FOSS YouTube channel][49] have been recorded with Kazam.
-
-#### Office suites
-
-I cannot imagine that you could use a computer without a document editor. And why restrict yourself to just one document editor? Go for a complete office suite.
-
-##### LibreOffice
-
-![LibreOffice logo][50]
-
-[LibreOffice][51] comes preinstalled on Ubuntu and it is undoubtedly the [best open source office software][52]. It’s a complete package comprising of a document editor, spreadsheet tool, presentation software, maths tool and a graphics tool. You can even edit some PDF files with LibreOffice.
-
-##### WPS Office
-
-![WPS Office logo][53]
-
-[WPS Office][54] has gained popularity for being a Microsoft Office clone. It has an interface identical to Microsoft Office and it claims to be more compatible with MS Office. If you are looking for something similar to the Microsoft Office, WPS Office is a good choice.
-
-#### Downloading tools
-
-![Downloading software Ubuntu][55]
-
-If you often download videos or other big files from the internet, these tools will help you.
-
-##### youtube-dl
-
-This is one of the rare Ubuntu application on the list that is command line based. If you want to download videos from YouTube, DailyMotion or other video websites, youtube-dl is an excellent choice. It provides plenty of [advanced option for video downloading][56].
-
-##### uGet
-
-[uGet][57] is a feature rich [download manager for Linux][58]. It allows you to pause and resume your downloads, schedule your downloads, monitor clipboard for downloadable content. A perfect tool if you have a slow, inconsistent internet or daily data limit.
-
-#### Code Editors
-
-![Coding apps for Ubuntu][59]
-
-If you are into programming, the default Gedit text editor might not be sufficient for your coding needs. Here are some of the better code editors for you.
-
-##### Atom
-
-[Atom][60] is a free and [open source code editor][61] from GitHub. Even before it was launched its first stable version, it became a hot favorite among coders for its UI, features and vast range of plugins.
-
-##### Visual Studio Code
-
-[VS Code][62] is an open source code editor from Microsoft. Don’t worry about Microsoft, VS Code is an awesome editor for web development. It also supports a number of other programming languages.
-
-#### PDF and eBooks related applications
-
-![eBook Management tools in Ubuntu][63]
-
-In this digital age, you cannot only rely on the real paper books especially when there are plenty of free eBooks available. Here are some Ubuntu apps for managing PDFs and eBooks.
-
-##### Calibre
-
-If you are a bibliophile and collect eBooks, you should use [Calibre][64]. It is an eBook manager with all the necessary software for [creating eBooks][65], converting eBook formats and managing an eBook library.
-
-##### Okular
-
-Okular is mostly a PDF viewer with options for editing PDF files. You can do some basic [PDF editing on Linux][66] with Okular such as adding pop-ups notes, inline notes, freehand line drawing, highlighter, stamp etc.
-
-#### Messaging applications
-
-![Messaging apps for Ubuntu][67]
-
-I believe you use at least one [messaging app on Linux][68]. Here are my recommendations.
-
-##### Skype
-
-[Skype][69] is the most popular video chatting application. It is also used by many companies and businesses for interviews and meetings. This makes Skype one of the must-have applications for Ubuntu.
-
-##### Rambox
-
-[Rambox][70] is not a messaging application on its own. But it allows you to use Skype, Viber, Facebook Messanger, WhatsApp, Slack and a number of other messaging applications from a single application window.
-
-#### Notes and To-do List applications
-
-Need a to-do list app or simple an app for taking notes? Have a look at these:
-
-##### Simplenote
-
-![Simplenote logo][71]
-
-[Simplenote][72] is a free and open source note taking application from WordPress creators [Automattic][73]. It is available for Windows, Linux, macOS, iOS and Android. Your notes are synced to a cloud server and you can access them on any device. You can download the DEB file from its website.
-
-##### Remember The Milk
-
-![Remember The Milk logo][74]
-
-[Remember The Milk][75] is a popular to-do list application. It is available for Windows, Linux, macOS, iOS and Android. Your to-do list is accessible on all the devices you own. You can also access it from a web browser. It also has an official native application for Linux that you can download from its website.
-
-#### Password protection and encryption
-
-![Encryption software Ubuntu][76]
-
-If there are other people regularly using your computer perhaps you would like to add an extra layer of security by password protecting files and folders.
-
-##### EncryptPad
-
-[EncryptPad][77] is an open source text editor that allows you to lock your files with a password. You can choose the type of encryption. There is also a command line version of this tool.
-
-##### Gnome Encfs Manager
-
-Gnome Encfs Manager allows you to [lock folders with a password in Linux][78]. You can keep whatever files you want in a secret folder and then lock it with a password.
-
-#### Gaming
-
-![Gaming on Ubuntu][79]
-
-[Gaming on Linux][80] is a lot better than what it used to be a few years ago. You can enjoy plenty of games on Linux without going back to Windows.
-
-##### Steam
-
-[Steam][81] is a digital distribution platform that allows you to purchase (if required) games. Steam has over 1500 [games for Linux][82]. You can download the Steam client from the Software Center.
-
-##### PlayOnLinux
-
-[PlayOnLinux][83] allows you to run Windows games on Linux over WINE compatibility layer. Don’t expect too much out of it because not every game will run flawlessly with PlayOnLinux.
-
-#### Package Managers [Intermediate to advanced users]
-
-![Package Management tools Ubuntu][84]
-
-Ubuntu Software Center is more than enough for an average Ubuntu user’s software needs but you can have more control on it using these applications.
-
-##### Gdebi
-
-Gedbi is a tiny packagae manager that you can use for installing DEB files. It is faster than the Software Center and it also handles dependency issues.
-
-##### Synaptic
-
-Synaptic was the default GUI package manager for most Linux distributions a decade ago. It still is in some Linux distributions. This powerful package manager is particularly helpful in [finding installed applications and removing them][85].
-
-#### Backup and Recovery tools
-
-![Backup and data recovery tools for Ubuntu][86]
-
-Backup and recovery tools are must-have software for any system. Let’s see what softwares you must have on Ubuntu.
-
-##### Timeshift
-
-Timeshift is a tool that allows you to [take a snapshot of your system][87]. This allows you to restore your system to a previous state in case of an unfortunate incident when your system configuration is messed up. Note that it’s not the best tool for your personal data backup though. For that, you can use Ubuntu’s default Deja Dup (also known as Backups) tool.
-
-##### TestDisk [Intermediate Users]
-
-This is another command line tool on this list of best Ubuntu application. [TestDisk][88] allows you to [recover data on Linux][89]. If you accidentally deleted files, there are still chances that you can get it back using TestDisk.
-
-#### System Tweaking and Management Tools
-
-![System Maintenance apps Ubuntu][90]
-
-##### GNOME/Unity Tweak Tool
-
-These Tweak tools are a must for every Ubuntu user. They allow you to access some advanced system settings. Best of all, you can [change themes in Ubuntu][91] using these tweak tools.
-
-##### UFW Firewall
-
-[UFW][92] stands for Uncomplicated Firewall and rightly so. UFW has predefined firewall settings for Home, Work and Public networks.
-
-##### Stacer
-
-If you want to free up space on Ubuntu, try Stacer. This graphical tool allows you to [optimize your Ubuntu system][93] by removing unnecessary files and completely uninstalling software. Download Stacer from [its website][94].
-
-#### Other Utilities
-
-![Utilities Ubuntu][95]
-
-In the end, I’ll list some of my other favorite Ubuntu apps that I could not put into a certain category.
-
-##### Neofetch
-
-One more command line tool! Neofetch displays your system information such as [Ubuntu version][96], desktop environment, theme, icons, RAM etc info along with [ASCII logo of the distribution][97]. Use this command for installing Neofetch.
-```
-sudo apt install neofetch
-
-```
-
-##### Etcher
-
-Ubuntu has a live USB creator tool installed already but Etcher is a better application for this task. It is also available for Windows and macOS. You can download it [from its website][98].
-
-##### gscan2pdf
-
-I use this tiny tool for the sole purpose of [converting images into PDF][99]. You can use it for combining multiple images into one PDF file as well.
-
-##### Audio Recorder
-
-Another tiny yet essential Ubuntu application for [recording audio on Ubuntu][100]. You can use it to record sound from system microphone, from music player or from any other source.
-
-### Your suggestions for essential Ubuntu applications?
-
-I would like to conclude my list of best Ubuntu apps here. I know that you might not need or use all of them but I am certain that you would like most of the software listed here.
-
-Did you find some useful applications that you didn’t know about before? If you would have to suggest your favorite Ubuntu application, which one would it be?
-
-In the end, if you find this article useful, please share it on social media, Reddit, Hacker News or other community or forums you visit regularly. This way you help us grow :)
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/best-ubuntu-apps/
-
-作者:[Abhishek Prakash][a]
-选题:[lujun9972](https://github.com/lujun9972)
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/abhishek/
-[1]:https://itsfoss.com/things-to-do-after-installing-ubuntu-18-04/
-[2]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/best-ubuntu-apps-featured.jpeg
-[3]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/google-chrome.jpeg
-[4]:https://www.google.com/chrome/
-[5]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/brave-browser-icon.jpeg
-[6]:https://itsfoss.com/open-source-browsers-linux/
-[7]:https://brave.com/
-[8]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/music-apps-ubuntu.jpeg
-[9]:https://itsfoss.com/sayonara-music-player/
-[10]:https://www.audacityteam.org/
-[11]:https://itsfoss.com/musicbrainz-picard/
-[12]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/streaming-music-apps-ubuntu.jpeg
-[13]:https://www.spotify.com//
-[14]:https://itsfoss.com/install-spotify-ubuntu-1404/
-[15]:https://tiliado.eu/nuvolaplayer/
-[16]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/Video-Players-linux.jpg
-[17]:https://www.videolan.org/index.html
-[18]:https://itsfoss.com/vlc-pro-tricks-linux/
-[19]:https://mpv.io/
-[20]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/dropbox-icon.jpeg
-[21]:https://www.dropbox.com/
-[22]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/pcloud-icon.jpeg
-[23]:https://itsfoss.com/recommends/pcloud/
-[24]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/gimp-icon.jpeg
-[25]:https://www.gimp.org/
-[26]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/inkscape-icon.jpeg
-[27]:https://inkscape.org/en/
-[28]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/paint-apps-ubuntu.jpeg
-[29]:https://krita.org/en/
-[30]:https://pinta-project.com/pintaproject/pinta/
-[31]:https://itsfoss.com/image-applications-ubuntu-linux/
-[32]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/digikam-icon.jpeg
-[33]:https://www.digikam.org/
-[34]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/darktable-icon.jpeg
-[35]:https://www.darktable.org/
-[36]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/video-editing-apps-ubuntu.jpeg
-[37]:https://itsfoss.com/best-video-editing-software-linux/
-[38]:https://kdenlive.org/en/
-[39]:https://shotcut.org/
-[40]:https://itsfoss.com/format-factory-alternative-linux/
-[41]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/xnconvert-logo.jpeg
-[42]:https://www.xnview.com/en/xnconvert/
-[43]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/handbrake-logo.jpeg
-[44]:https://handbrake.fr/
-[45]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/screen-recording-ubuntu-apps.jpeg
-[46]:http://shutter-project.org/
-[47]:https://launchpad.net/kazam
-[48]:https://itsfoss.com/best-linux-screen-recorders/
-[49]:https://www.youtube.com/c/itsfoss?sub_confirmation=1
-[50]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/libre-office-logo.jpeg
-[51]:https://www.libreoffice.org/download/download/
-[52]:https://itsfoss.com/best-free-open-source-alternatives-microsoft-office/
-[53]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/wps-office-logo.jpeg
-[54]:http://wps-community.org/
-[55]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/download-apps-ubuntu.jpeg
-[56]:https://itsfoss.com/download-youtube-linux/
-[57]:http://ugetdm.com/
-[58]:https://itsfoss.com/4-best-download-managers-for-linux/
-[59]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/coding-apps-ubuntu.jpeg
-[60]:https://atom.io/
-[61]:https://itsfoss.com/best-modern-open-source-code-editors-for-linux/
-[62]:https://itsfoss.com/install-visual-studio-code-ubuntu/
-[63]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/pdf-management-apps-ubuntu.jpeg
-[64]:https://calibre-ebook.com/
-[65]:https://itsfoss.com/create-ebook-calibre-linux/
-[66]:https://itsfoss.com/pdf-editors-linux/
-[67]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/messaging-apps-ubuntu.jpeg
-[68]:https://itsfoss.com/best-messaging-apps-linux/
-[69]:https://www.skype.com/en/
-[70]:https://rambox.pro/
-[71]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/simplenote-logo.jpeg
-[72]:http://simplenote.com/
-[73]:https://automattic.com/
-[74]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/remember-the-milk-logo.jpeg
-[75]:https://itsfoss.com/remember-the-milk-linux/
-[76]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/encryption-apps-ubuntu.jpeg
-[77]:https://itsfoss.com/encryptpad-encrypted-text-editor-linux/
-[78]:https://itsfoss.com/password-protect-folder-linux/
-[79]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/gaming-ubuntu.jpeg
-[80]:https://itsfoss.com/linux-gaming-guide/
-[81]:https://store.steampowered.com/
-[82]:https://itsfoss.com/free-linux-games/
-[83]:https://www.playonlinux.com/en/
-[84]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/package-management-apps-ubuntu.jpeg
-[85]:https://itsfoss.com/how-to-add-remove-programs-in-ubuntu/
-[86]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/backup-recovery-tools-ubuntu.jpeg
-[87]:https://itsfoss.com/backup-restore-linux-timeshift/
-[88]:https://www.cgsecurity.org/wiki/TestDisk
-[89]:https://itsfoss.com/recover-deleted-files-linux/
-[90]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/system-maintenance-apps-ubuntu.jpeg
-[91]:https://itsfoss.com/install-themes-ubuntu/
-[92]:https://wiki.ubuntu.com/UncomplicatedFirewall
-[93]:https://itsfoss.com/optimize-ubuntu-stacer/
-[94]:https://github.com/oguzhaninan/Stacer
-[95]:https://4bds6hergc-flywheel.netdna-ssl.com/wp-content/uploads/2018/07/utilities-apps-ubuntu.jpeg
-[96]:https://itsfoss.com/how-to-know-ubuntu-unity-version/
-[97]:https://itsfoss.com/display-linux-logo-in-ascii/
-[98]:https://etcher.io/
-[99]:https://itsfoss.com/convert-multiple-images-pdf-ubuntu-1304/
-[100]:https://itsfoss.com/record-streaming-audio/
diff --git a/sources/tech/20190107 Different Ways To Update Linux Kernel For Ubuntu.md b/sources/tech/20190107 Different Ways To Update Linux Kernel For Ubuntu.md
deleted file mode 100644
index 32a6a7dd3e..0000000000
--- a/sources/tech/20190107 Different Ways To Update Linux Kernel For Ubuntu.md
+++ /dev/null
@@ -1,232 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Different Ways To Update Linux Kernel For Ubuntu)
-[#]: via: (https://www.ostechnix.com/different-ways-to-update-linux-kernel-for-ubuntu/)
-[#]: author: (SK https://www.ostechnix.com/author/sk/)
-
-Different Ways To Update Linux Kernel For Ubuntu
-======
-
-
-
-In this guide, we have given 7 different ways to update Linux kernel for Ubuntu. Among the 7 methods, five methods requires system reboot to apply the new Kernel and two methods don’t. Before updating Linux Kernel, it is **highly recommended to backup your important data!** All methods mentioned here are tested on Ubuntu OS only. We are not sure if they will work on other Ubuntu flavors (Eg. Xubuntu) and Ubuntu derivatives (Eg. Linux Mint).
-
-### Part A – Kernel Updates with reboot
-
-The following methods requires you to reboot your system to apply the new Linux Kernel. All of the following methods are recommended for personal or testing systems. Again, please backup your important data, configuration files and any other important stuff from your Ubuntu system.
-
-#### Method 1 – Update the Linux Kernel with dpkg (The manual way)
-
-This method helps you to manually download and install the latest available Linux kernel from **[kernel.ubuntu.com][1]** website. If you want to install most recent version (either stable or release candidate), this method will help. Download the Linux kernel version from the above link. As of writing this guide, the latest available version was **5.0-rc1** and latest stable version was **v4.20**.
-
-![][3]
-
-Click on the Linux Kernel version link of your choice and find the section for your architecture (‘Build for XXX’). In that section, download the two files with these patterns (where X.Y.Z is the highest version):
-
- 1. linux-image-*X.Y.Z*-generic-*.deb
- 2. linux-modules-X.Y.Z*-generic-*.deb
-
-
-
-In a terminal, change directory to where the files are and run this command to manually install the kernel:
-
-```
-$ sudo dpkg --install *.deb
-```
-
-Reboot to use the new kernel:
-
-```
-$ sudo reboot
-```
-
-Check the kernel is as expected:
-
-```
-$ uname -r
-```
-
-For step by step instructions, please check the section titled under “Install Linux Kernel 4.15 LTS On DEB based systems” in the following guide.
-
-+ [Install Linux Kernel 4.15 In RPM And DEB Based Systems](https://www.ostechnix.com/install-linux-kernel-4-15-rpm-deb-based-systems/)
-
-The above guide is specifically written for 4.15 version. However, all the steps are same for installing latest versions too.
-
-**Pros:** No internet needed (You can download the Linux Kernel from any system).
-
-**Cons:** Manual update. Reboot necessary.
-
-#### Method 2 – Update the Linux Kernel with apt-get (The recommended method)
-
-This is the recommended way to install latest Linux kernel on Ubuntu-like systems. Unlike the previous method, this method will download and install latest Kernel version from Ubuntu official repositories instead of **kernel.ubuntu.com** website..
-
-To update the whole system including the Kernel, just do:
-
-```
-$ sudo apt-get update
-
-$ sudo apt-get upgrade
-```
-
-If you want to update the Kernel only, run:
-
-```
-$ sudo apt-get upgrade linux-image-generic
-```
-
-**Pros:** Simple. Recommended method.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-Updating Kernel from official repositories will mostly work out of the box without any problems. If it is the production system, this is the recommended way to update the Kernel.
-
-Method 1 and 2 requires user intervention to update Linux Kernels. The following methods (3, 4 & 5) are mostly automated.
-
-#### Method 3 – Update the Linux Kernel with Ukuu
-
-**Ukuu** is a Gtk GUI and command line tool that downloads the latest main line Linux kernel from **kernel.ubuntu.com** , and install it automatically in your Ubuntu desktop and server editions. Ukku is not only simplifies the process of manually downloading and installing new Kernels, but also helps you to safely remove the old and unnecessary Kernels. For more details, refer the following guide.
-
-+ [Ukuu – An Easy Way To Install And Upgrade Linux Kernel In Ubuntu-based Systems](https://www.ostechnix.com/ukuu-an-easy-way-to-install-and-upgrade-linux-kernel-in-ubuntu-based-systems/)
-
-**Pros:** Easy to install and use. Automatically installs main line Kernel.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-#### Method 4 – Update the Linux Kernel with UKTools
-
-Just like Ukuu, the **UKTools** also fetches the latest stable Kernel from from **kernel.ubuntu.com** site and installs it automatically on Ubuntu and its derivatives like Linux Mint. More details about UKTools can be found in the link given below.
-
-+ [UKTools – Upgrade Latest Linux Kernel In Ubuntu And Derivatives](https://www.ostechnix.com/uktools-upgrade-latest-linux-kernel-in-ubuntu-and-derivatives/)
-
-**Pros:** Simple. Automated.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-#### Method 5 – Update the Linux Kernel with Linux Kernel Utilities
-
-**Linux Kernel Utilities** is yet another program that makes the process of updating Linux kernel easy in Ubuntu-like systems. It is actually a set of BASH shell scripts used to compile and/or update latest Linux kernels for Debian and derivatives. It consists of three utilities, one for manually compiling and installing Kernel from source from [**http://www.kernel.org**][4] website, another for downloading and installing pre-compiled Kernels from from **** website. and third script is for removing the old kernels. For more details, please have a look at the following link.
-
-+ [Linux Kernel Utilities – Scripts To Compile And Update Latest Linux Kernel For Debian And Derivatives](https://www.ostechnix.com/linux-kernel-utilities-scripts-compile-update-latest-linux-kernel-debian-derivatives/)
-
-**Pros:** Simple. Automated.
-
-**Cons:** Internet necessary. Reboot necessary.
-
-
-### Part B – Kernel Updates without reboot
-
-As I already said, all of above methods need you to reboot the server before the new kernel is active. If they are personal systems or testing machines, you could simply reboot and start using the new Kernel. But, what if they are production systems that requires zero downtime? No problem. This is where **Livepatching** comes in handy!
-
-The **livepatching** (or hot patching) allows you to install Linux updates or patches without rebooting, keeping your server at the latest security level, without any downtime. This is attractive for ‘always-on’ servers, such as web hosts, gaming servers, in fact, any situation where the server needs to stay on all the time. Linux vendors maintain patches only for security fixes, so this approach is best when security is your main concern.
-
-The following two methods doesn’t require system reboot and useful for updating Linux Kernel on production and mission-critical Ubuntu servers.
-
-#### Method 6 – Update the Linux Kernel Canonical Livepatch Service
-
-![][5]
-
-[**Canonical Livepatch Service**][6] applies Kernel updates, patches and security hotfixes automatically without rebooting the Ubuntu systems. It reduces the Ubuntu systems downtime and keep them secure. Canonical Livepatch Service can be set up either during or after installation. If you are using desktop Ubuntu, the Software Updater will automatically check for kernel patches and notify you. In a console-based system, it is up to you to run apt-get update regularly. It will install kernel security patches only when you run the command “apt-get upgrade”, hence is semi-automatic.
-
-Livepatch is free for three systems. If you have more than three, you need to upgrade to enterprise support solution named **Ubuntu Advantage** suite. This suite includes **Kernel Livepatching** and other services such as,
-
- * Extended Security Maintenance – critical security updates after Ubuntu end-of-life.
- * Landscape – the systems management tool for using Ubuntu at scale.
- * Knowledge Base – A private collection of articles and tutorials written by Ubuntu experts.
- * Phone and web-based support.
-
-
-
-**Cost**
-
-Ubuntu Advantage includes three paid plans namely, Essential, Standard and Advanced. The basic plan (Essential plan) starts from **225 USD per year for one physical node** and **75 USD per year for one VPS**. It seems there is no monthly subscription for Ubuntu servers and desktops. You can view detailed information on all plans [**here**][7].
-
-**Pros:** Simple. Semi-automatic. No reboot necessary. Free for 3 systems.
-
-**Cons:** Expensive for 4 or more hosts. No patch rollback.
-
-**Enable Canonical Livepatch Service**
-
-If you want to setup Livepatch service after installation, just do the following steps.
-
-Get a key at [**https://auth.livepatch.canonical.com/**][8].
-
-```
-$ sudo snap install canonical-livepatch
-
-$ sudo canonical-livepatch enable your-key
-```
-
-#### Method 7 – Update the Linux Kernel with KernelCare
-
-![][9]
-
-[**KernelCare**][10] is the newest of all the live patching solutions. It is the product of [CloudLinux][11]. KernelCare runs on Ubuntu and other flavors of Linux. It checks for patch releases every 4 hours and will install them without confirmation. Patches can be rolled back if there are problems.
-
-**Cost**
-
-Fees, per server: **4 USD per month** , **45 USD per year**.
-
-Compared to Ubuntu Livepatch, kernelCare seems very cheap and affordable. Good thing is **monthly subscriptions are also available**. Another notable feature is it supports other Linux distributions, such as Red Hat, CentOS, Debian, Oracle Linux, Amazon Linux and virtualization platforms like OpenVZ, Proxmox etc.
-
-You can read all the features and benefits of KernelCare [**here**][12] and check all available plan details [**here**][13].
-
-**Pros:** Simple. Fully automated. Wide OS coverage. Patch rollback. No reboot necessary. Free license for non-profit organizations. Low cost.
-
-**Cons:** Not free (except for 30 day trial).
-
-**Enable KernelCare Service**
-
-Get a 30-day trial key at [**https://cloudlinux.com/kernelcare-free-trial5**][14].
-
-Run the following commands to enable KernelCare and register the key.
-
-```
-$ sudo wget -qq -O - https://repo.cloudlinux.com/kernelcare/kernelcare_install.sh | bash
-
-$ sudo /usr/bin/kcarectl --register KEY
-```
-
-If you’re looking for an affordable and reliable commercial service to keep the Linux Kernel updated on your Linux servers, KernelCare is good to go.
-
-*with inputs from **Paul A. Jacobs** , a Technical Evangelist and Content Writer from Cloud Linux.*
-
-**Suggested read:**
-
-And, that’s all for now. Hope this was useful. If you believe any other tools/methods should include in this list, feel free to let us know in the comment section below. I will check and update this guide accordingly.
-
-More good stuffs to come. Stay tuned!
-
-Cheers!
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.ostechnix.com/different-ways-to-update-linux-kernel-for-ubuntu/
-
-作者:[SK][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.ostechnix.com/author/sk/
-[b]: https://github.com/lujun9972
-[1]: http://kernel.ubuntu.com/~kernel-ppa/mainline/
-[2]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[3]: http://www.ostechnix.com/wp-content/uploads/2019/01/Ubuntu-mainline-kernel.png
-[4]: http://www.kernel.org
-[5]: http://www.ostechnix.com/wp-content/uploads/2019/01/Livepatch.png
-[6]: https://www.ubuntu.com/livepatch
-[7]: https://www.ubuntu.com/support/plans-and-pricing
-[8]: https://auth.livepatch.canonical.com/
-[9]: http://www.ostechnix.com/wp-content/uploads/2019/01/KernelCare.png
-[10]: https://www.kernelcare.com/
-[11]: https://www.cloudlinux.com/
-[12]: https://www.kernelcare.com/update-kernel-linux/
-[13]: https://www.kernelcare.com/pricing/
-[14]: https://cloudlinux.com/kernelcare-free-trial5
diff --git a/sources/tech/20190116 Best Audio Editors For Linux.md b/sources/tech/20190116 Best Audio Editors For Linux.md
deleted file mode 100644
index 3b14f5b366..0000000000
--- a/sources/tech/20190116 Best Audio Editors For Linux.md
+++ /dev/null
@@ -1,156 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (MFGJT)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Best Audio Editors For Linux)
-[#]: via: (https://itsfoss.com/best-audio-editors-linux)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Best Audio Editors For Linux
-======
-
-You’ve got a lot of choices when it comes to audio editors for Linux. No matter whether you are a professional music producer or just learning to create awesome music, the audio editors will always come in handy.
-
-Well, for professional-grade usage, a [DAW][1] (Digital Audio Workstation) is always recommended. However, not everyone needs all the functionalities, so you should know about some of the most simple audio editors as well.
-
-In this article, we will talk about a couple of DAWs and basic audio editors which are available as **free and open source** solutions for Linux and (probably) for other operating systems.
-
-### Top Audio Editors for Linux
-
-![Best audio editors and DAW for Linux][2]
-
-We will not be focusing on all the functionalities that DAWs offer – but the basic audio editing capabilities. You may still consider this as the list of best DAW for Linux.
-
-**Installation instruction:** You will find all the mentioned audio editors or DAWs in your AppCenter or Software center. In case, you do not find them listed, please head to their official website for more information.
-
-#### 1\. Audacity
-
-![audacity audio editor][3]
-
-Audacity is one of the most basic yet a capable audio editor available for Linux. It is a free and open-source cross-platform tool. A lot of you must be already knowing about it.
-
-It has improved a lot when compared to the time when it started trending. I do recall that I utilized it to “try” making karaokes by removing the voice from an audio file. Well, you can still do it – but it depends.
-
-**Features:**
-
-It also supports plug-ins that include VST effects. Of course, you should not expect it to support VST Instruments.
-
- * Live audio recording through a microphone or a mixer
- * Export/Import capability supporting multiple formats and multiple files at the same time
- * Plugin support: LADSPA, LV2, Nyquist, VST and Audio Unit effect plug-ins
- * Easy editing with cut, paste, delete and copy functions.
- * Spectogram view mode for analyzing frequencies
-
-
-
-#### 2\. LMMS
-
-![][4]
-
-LMMS is a free and open source (cross-platform) digital audio workstation. It includes all the basic audio editing functionalities along with a lot of advanced features.
-
-You can mix sounds, arrange them, or create them using VST instruments. It does support them. Also, it comes baked in with some samples, presets, VST Instruments, and effects to get started. In addition, you also get a spectrum analyzer for some advanced audio editing.
-
-**Features:**
-
- * Note playback via MIDI
- * VST Instrument support
- * Native multi-sample support
- * Built-in compressor, limiter, delay, reverb, distortion and bass enhancer
-
-
-
-#### 3\. Ardour
-
-![Ardour audio editor][5]
-
-Ardour is yet another free and open source digital audio workstation. If you have an audio interface, Ardour will support it. Of course, you can add unlimited multichannel tracks. The multichannel tracks can also be routed to different mixer tapes for the ease of editing and recording.
-
-You can also import a video to it and edit the audio to export the whole thing. It comes with a lot of built-in plugins and supports VST plugins as well.
-
-**Features:**
-
- * Non-linear editing
- * Vertical window stacking for easy navigation
- * Strip silence, push-pull trimming, Rhythm Ferret for transient and note onset-based editing
-
-
-
-#### 4\. Cecilia
-
-![cecilia audio editor][6]
-
-Cecilia is not an ordinary audio editor application. It is meant to be used by sound designers or if you are just in the process of becoming one. It is technically an audio signal processing environment. It lets you create ear-bending sound out of them.
-
-You get in-build modules and plugins for sound effects and synthesis. It is tailored for a specific use – if that is what you were looking for – look no further!
-
-**Features:**
-
- * Modules to achieve more (UltimateGrainer – A state-of-the-art granulation processing, RandomAccumulator – Variable speed recording accumulator,
-UpDistoRes – Distortion with upsampling and resonant lowpass filter)
- * Automatic Saving of modulations
-
-
-
-#### 5\. Mixxx
-
-![Mixxx audio DJ ][7]
-
-If you want to mix and record something while being able to have a virtual DJ tool, [Mixxx][8] would be a perfect tool. You get to know the BPM, key, and utilize the master sync feature to match the tempo and beats of a song. Also, do not forget that it is yet another free and open source application for Linux!
-
-It supports custom DJ equipment as well. So, if you have one or a MIDI – you can record your live mixes using this tool.
-
-**Features**
-
- * Broadcast and record DJ Mixes of your song
- * Ability to connect your equipment and perform live
- * Key detection and BPM detection
-
-
-
-#### 6\. Rosegarden
-
-![rosegarden audio editor][9]
-
-Rosegarden is yet another impressive audio editor for Linux which is free and open source. It is neither a fully featured DAW nor a basic audio editing tool. It is a mixture of both with some scaled down functionalities.
-
-I wouldn’t recommend this for professionals but if you have a home studio or just want to experiment, this would be one of the best audio editors for Linux to have installed.
-
-**Features:**
-
- * Music notation editing
- * Recording, Mixing, and samples
-
-
-
-### Wrapping Up
-
-These are some of the best audio editors you could find out there for Linux. No matter whether you need a DAW, a cut-paste editing tool, or a basic mixing/recording audio editor, the above-mentioned tools should help you out.
-
-Did we miss any of your favorite? Let us know about it in the comments below.
-
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/best-audio-editors-linux
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://en.wikipedia.org/wiki/Digital_audio_workstation
-[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/linux-audio-editors-800x450.jpeg?resize=800%2C450&ssl=1
-[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/audacity-audio-editor.jpg?fit=800%2C591&ssl=1
-[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/lmms-daw.jpg?fit=800%2C472&ssl=1
-[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/ardour-audio-editor.jpg?fit=800%2C639&ssl=1
-[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/01/cecilia.jpg?fit=800%2C510&ssl=1
-[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/01/mixxx.jpg?fit=800%2C486&ssl=1
-[8]: https://itsfoss.com/dj-mixxx-2/
-[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/rosegarden.jpg?fit=800%2C391&ssl=1
-[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/linux-audio-editors.jpeg?fit=800%2C450&ssl=1
diff --git a/sources/tech/20190204 Getting started with Git- Terminology 101.md b/sources/tech/20190204 Getting started with Git- Terminology 101.md
new file mode 100644
index 0000000000..0b76cd3a43
--- /dev/null
+++ b/sources/tech/20190204 Getting started with Git- Terminology 101.md
@@ -0,0 +1,157 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Getting started with Git: Terminology 101)
+[#]: via: (https://opensource.com/article/19/2/git-terminology)
+[#]: author: (Matthew Broberg https://opensource.com/users/mbbroberg)
+
+Getting started with Git: Terminology 101
+======
+Want to learn Git? Check out this quick summary of the most important
+terms and commands.
+![Digital hand surrounding by objects, bike, light bulb, graphs][1]
+
+Version control is an important tool for anyone looking to track their changes these days. It's especially helpful for programmers, sysadmins, and site reliability engineers (SREs) alike. The promise of recovering from mistakes to a known good state is a huge win and a touch friendlier than the previous strategy of adding **`.old`** to a copied file.
+
+But learning Git is often oversimplified by well-meaning peers telling everyone to "get into open source." Before you know it, someone asks for a _pull request_ or *merge request *where you _rebase_ from _upstream_ before they can merge from your _remote_—and be sure to remove _merge commits_. Whatever well-working contribution you want to give back to an open source project feels much further from being added when you look at all these words you don't know.
+
+![Git Cheat Sheet cover image][2]
+
+[Download][3] our
+Git cheat sheet.
+
+If you have a month or two and enough curiosity, [Git SCM][4] is the definitive source for all the terms you need to learn. If you're looking for a summary from the trenches, keep reading.
+
+### Reminder: What's a commit?
+
+The toughest part of Git for me to internalize was the simplest idea of Git: _a commit is a collection of content, a message about how you got there, and the commits that came before it_. There's no inherent code release strategy or even strong opinions built in. The content doesn't even have to be code—it is _anything_ you want to add to the repository. The commit message annotates that content.
+
+I like to think of a commit message as a gift to your future self: it may mention the files you edited, but more importantly it reminds you of your intention for changing those files. Adding more about why you have edited what you have helps anyone who uses your repository, even when that person is you.
+
+### There's no place like 'origin/master'
+
+Knowing where you are in a Git project starts with thinking of a tree. All Git projects have a root, similar to the idea of a filesystem's root directory. All commits branch off from that root. In this way, a branch is only a pointer to a commit. By convention, **master** is the default name for the default branch in your root directory.
+
+Since Git is a distributed version control system, where the same codebase is distributed to multiple locations, people often use the term "repository" as a way of talking about all copies of the same project. There is the _local repository_, where you edit your code (more on that in a minute), and the _remote repository_, the place where you want to send it after you're finished. Remotes can be anywhere, even on the same computer where your local repository is located, but they are often hosted on repository services like GitLab or GitHub.
+
+### What's the pwd of Git commands?
+
+While it's not an official selling point, being lost is part of the fun of a Git repository. You can find your way by running through this reliable set of commands:
+
+ * `git branch`—to find which branch you're on
+
+ * `git log`—to see what commit you're on
+
+ * `git status`—to see what edits you've made since the last commit
+
+ * `git remote`—to see what remote repository you're tracking
+
+
+
+
+Orienting yourself using these commands will give you a sense of direction when you're stuck.
+
+### Have I stashed or cached my commit?
+
+The code local to your computer is colloquially called your _workspace_. What is not immediately obvious is that you have two (yes, two!) other locations local to you when you are in a Git repository: _index_ and _stash_. When you write some content and then **add** it, you are adding it to the index, which is the cached content that is ready to commit. There are times when you have files in the index that you are not ready to commit, but you want to view another branch. That's where the stash comes in handy. You can store indexed-but-not-yet-committed files to the stash using `git stash`. When you're ready to retrieve the file, run `git stash pop` to bring changes back into the index.
+
+Here are some commands you'll need to use your stash and cache.
+
+ * `git diff ..origin/master`—to show the difference between the most recent local commit and the remote called "origin" and its branch called "master"
+
+ * `git diff --cached`—to show any differences between the most recent local commit and what has been added to the local index
+
+ * `git stash`—to place indexed (added but not committed) files in the stash stack
+
+ * `git stash list`—to show what changes are in the stash stack
+
+ * `git stash pop`—to take the most recent change off the stash stack
+
+
+
+
+### HEADless horseman
+
+Git is a collection of all kinds of metaphors. When I think of where the HEAD is, I think of train lines. If you end up in a _detached HEAD_ mode, it means you're off the metaphorical rails.
+
+HEAD is a pointer to your most recent commit in the currently checked-out branch. The default "checkout" is when you create a Git repository and land on the **master** branch. Every time you create or change to another branch, you are on that branch line. If you `git checkout ` somewhere in your current branch, HEAD will move to that commit. If there is no commit history connecting your current commit to the commit you checked out, then you'll be in a detached HEAD state. If you ever lose your head finding where HEAD is, you can always `git reset --hard origin/master` to delete changes and get back to a known state. _Warning: this will delete any changes you have made since you last pushed to master._
+
+### Are you upstream or downstream?
+
+The local copy of your project is considered your local repository. It may or may not have a remote repository—the place where you have a copy of your repository for collaboration or safekeeping. There may also be an _upstream_ repository where a third copy of the project is hosted and maintained by a different set of contributors.
+
+For instance, let's say I want to contribute to Kubernetes. I would first fork the **kubernetes/kubernetes** project to my account, **mbbroberg/kubernetes**. I would then clone my project to my local workspace. In this scenario, my local clone is my local repository, **mbbroberg/kubernetes** is my remote repository, and **kubernetes/kubernetes** is the upstream.
+
+### Merging the metaphors
+
+The visual of a root system merges with the train tracks image when you get deeper into Git branches. Branches are often used as ways of developing a new feature that you eventually want to _merge_ into the master branch. When doing this, Git keeps the common history of commits in order then appends the new commits for your branch to the history. There are a ton of nuances to this process—whether to rebase or not, whether to add a merge commit or not—which [Brent Laster][5] explores in greater detail in "[How to reset, revert, and return to previous states in Git][6]."
+
+### I think I Git it now
+
+There is a ton of terminology and a lot to explore to master the world of Git commands. I hope this first-person exploration of how I use the terms day-to-day helps you acclimate to it all. If you ever feel stuck or frustrated, feel free to reach out to me on Twitter [@mbbroberg][7].
+
+#### To review:
+
+ * **Commit**—stores the current contents of the index in a new commit along with a log message from the user describing the changes
+
+ * **Branch**—a pointer to a commit
+
+ * **Master**—the default name for the first branch
+
+ * **HEAD**—a pointer to the most recent commit on the current branch
+
+ * **Merge**—joining two or more commit histories
+
+ * **Workspace**—the colloquial name for your local copy of a Git repository
+
+ * **Working tree**—the current branch in your workspace; you see this in `git status` output all the time
+
+ * **Cache**—a space intended to temporarily store uncommitted changes
+
+ * **Index**—the cache where changes are stored before they are committed
+
+ * **Tracked and untracked files**—files either in the index cache or not yet added to it
+
+ * **Stash**—another cache, that acts as a stack, where changes can be stored without committing them
+
+ * **Origin**—the default name for a remote repository
+
+ * **Local repository**—another term for where you keep your copy of a Git repository on your workstation
+
+ * **Remote repository**—a secondary copy of a Git repository where you push changes for collaboration or backup
+
+ * **Upstream repository**—the colloquial term for a remote repository that you track
+
+ * **Pull request**—a GitHub-specific term to let others know about changes you've pushed to a branch in a repository
+
+ * **Merge request**—a GitLab-specific term to let others know about changes you've pushed to a branch in a repository
+
+ * **'origin/master'**—the default setting for a remote repository and its primary branch
+
+
+
+
+Postscript: Puns are one of the best parts of Git. Have fun with them.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/19/2/git-terminology
+
+作者:[Matthew Broberg][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mbbroberg
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003588_01_rd3os.combacktoschoolseriesk12_rh_021x_0.png?itok=fvorN0e- (Digital hand surrounding by objects, bike, light bulb, graphs)
+[2]: https://opensource.com/sites/default/files/uploads/git_cheat_sheet_cover.jpg (Git Cheat Sheet cover image)
+[3]: https://opensource.com/downloads/cheat-sheet-git
+[4]: https://git-scm.com/about
+[5]: https://opensource.com/users/bclaster
+[6]: https://opensource.com/article/18/6/git-reset-revert-rebase-commands
+[7]: https://twitter.com/mbbroberg
diff --git a/sources/tech/20190205 Installing Kali Linux on VirtualBox- Quickest - Safest Way.md b/sources/tech/20190205 Installing Kali Linux on VirtualBox- Quickest - Safest Way.md
deleted file mode 100644
index e8722c63cc..0000000000
--- a/sources/tech/20190205 Installing Kali Linux on VirtualBox- Quickest - Safest Way.md
+++ /dev/null
@@ -1,146 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Installing Kali Linux on VirtualBox: Quickest & Safest Way)
-[#]: via: (https://itsfoss.com/install-kali-linux-virtualbox/)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Installing Kali Linux on VirtualBox: Quickest & Safest Way
-======
-
-_**This tutorial shows you how to install Kali Linux on Virtual Box in Windows and Linux in the quickest way possible.**_
-
-[Kali Linux][1] is one of the [best Linux distributions for hacking][2] and security enthusiasts.
-
-Since it deals with a sensitive topic like hacking, it’s like a double-edged sword. We have discussed it in the detailed Kali Linux review in the past so I am not going to bore you with the same stuff again.
-
-While you can install Kali Linux by replacing the existing operating system, using it via a virtual machine would be a better and safer option.
-
-With Virtual Box, you can use Kali Linux as a regular application in your Windows/Linux system. It’s almost the same as running VLC or a game in your system.
-
-Using Kali Linux in a virtual machine is also safe. Whatever you do inside Kali Linux will NOT impact your ‘host system’ (i.e. your original Windows or Linux operating system). Your actual operating system will be untouched and your data in the host system will be safe.
-
-![][3]
-
-### How to install Kali Linux on VirtualBox
-
-I’ll be using [VirtualBox][4] here. It is a wonderful open source virtualization solution for just about anyone (professional or personal use). It’s available free of cost.
-
-In this tutorial, we will talk about Kali Linux in particular but you can install almost any other OS whose ISO file exists or a pre-built virtual machine save file is available.
-
-**Note:** _The same steps apply for Windows/Linux running VirtualBox._
-
-As I already mentioned, you can have either Windows or Linux installed as your host. But, in this case, I have Windows 10 installed (don’t hate me!) where I try to install Kali Linux in VirtualBox step by step.
-
-And, the best part is – even if you happen to use a Linux distro as your primary OS, the same steps will be applicable!
-
-Wondering, how? Let’s see…
-
-[Subscribe to Our YouTube Channel for More Linux Videos][5]
-
-### Step by Step Guide to install Kali Linux on VirtualBox
-
-_We are going to use a custom Kali Linux image made for VirtualBox specifically. You can also download the ISO file for Kali Linux and create a new virtual machine – but why do that when you have an easy alternative?_
-
-#### 1\. Download and install VirtualBox
-
-The first thing you need to do is to download and install VirtualBox from Oracle’s official website.
-
-[Download VirtualBox][6]
-
-Once you download the installer, just double click on it to install VirtualBox. It’s the same for [installing VirtualBox on Ubuntu][7]/Fedora Linux as well.
-
-#### 2\. Download ready-to-use virtual image of Kali Linux
-
-After installing it successfully, head to [Offensive Security’s download page][8] to download the VM image for VirtualBox. If you change your mind to utilize [VMware][9], that is available too.
-
-![][10]
-
-As you can see the file size is well over 3 GB, you should either use the torrent option or download it using a [download manager][11].
-
-[Kali Linux Virtual Image][8]
-
-#### 3\. Install Kali Linux on Virtual Box
-
-Once you have installed VirtualBox and downloaded the Kali Linux image, you just need to import it to VirtualBox in order to make it work.
-
-Here’s how to import the VirtualBox image for Kali Linux:
-
-**Step 1** : Launch VirtualBox. You will notice an **Import** button – click on it
-
-![Click on Import button][12]
-
-**Step 2:** Next, browse the file you just downloaded and choose it to be imported (as you can see in the image below). The file name should start with ‘kali linux‘ and end with . **ova** extension.
-
-![Importing Kali Linux image][13]
-
-**S** Once selected, proceed by clicking on **Next**.
-
-**Step 3** : Now, you will be shown the settings for the virtual machine you are about to import. So, you can customize them or not – that is your choice. It is okay if you go with the default settings.
-
-You need to select a path where you have sufficient storage available. I would never recommend the **C:** drive on Windows.
-
-![Import hard drives as VDI][14]
-
-Here, the hard drives as VDI refer to virtually mount the hard drives by allocating the storage space set.
-
-After you are done with the settings, hit **Import** and wait for a while.
-
-**Step 4:** You will now see it listed. So, just hit **Start** to launch it.
-
-You might get an error at first for USB port 2.0 controller support, you can disable it to resolve it or just follow the on-screen instruction of installing an additional package to fix it. And, you are done!
-
-![Kali Linux running in VirtualBox][15]
-
-The default username in Kali Linux is root and the default password is toor. You should be able to login to the system with it.
-
-Do note that you should [update Kali Linux][16] before trying to install a new applications or trying to hack your neighbor’s WiFi.
-
-I hope this guide helps you easily install Kali Linux on Virtual Box. Of course, Kali Linux has a lot of useful tools in it for penetration testing – good luck with that!
-
-**Tip** : Both Kali Linux and Ubuntu are Debian-based. If you face any issues or error with Kali Linux, you may follow the tutorials intended for Ubuntu or Debian on the internet.
-
-### Bonus: Free Kali Linux Guide Book
-
-If you are just starting with Kali Linux, it will be a good idea to know how to use Kali Linux.
-
-Offensive Security, the company behind Kali Linux, has created a guide book that explains the basics of Linux, basics of Kali Linux, configuration, setups. It also has a few chapters on penetration testing and security tools.
-
-Basically, it has everything you need to get started with Kali Linux. And the best thing is that the book is available to download for free.
-
-[Download Kali Linux Revealed for FREE][17]
-
-Let us know in the comments below if you face an issue or simply share your experience with Kali Linux on VirtualBox.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/install-kali-linux-virtualbox/
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://www.kali.org/
-[2]: https://itsfoss.com/linux-hacking-penetration-testing/
-[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-virtual-box.png?resize=800%2C450&ssl=1
-[4]: https://www.virtualbox.org/
-[5]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
-[6]: https://www.virtualbox.org/wiki/Downloads
-[7]: https://itsfoss.com/install-virtualbox-ubuntu/
-[8]: https://www.offensive-security.com/kali-linux-vm-vmware-virtualbox-image-download/
-[9]: https://itsfoss.com/install-vmware-player-ubuntu-1310/
-[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-virtual-box-image.jpg?resize=800%2C347&ssl=1
-[11]: https://itsfoss.com/4-best-download-managers-for-linux/
-[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-import-kali-linux.jpg?ssl=1
-[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-linux-next.jpg?ssl=1
-[14]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/vmbox-kali-linux-settings.jpg?ssl=1
-[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2019/02/kali-linux-on-windows-virtualbox.jpg?resize=800%2C429&ssl=1
-[16]: https://linuxhandbook.com/update-kali-linux/
-[17]: https://kali.training/downloads/Kali-Linux-Revealed-1st-edition.pdf
diff --git a/sources/tech/20190212 Top 10 Best Linux Media Server Software.md b/sources/tech/20190212 Top 10 Best Linux Media Server Software.md
index 8fcea6343a..79b9dcb3bc 100644
--- a/sources/tech/20190212 Top 10 Best Linux Media Server Software.md
+++ b/sources/tech/20190212 Top 10 Best Linux Media Server Software.md
@@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
-[#]: translator: ( )
+[#]: translator: (kodark)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
diff --git a/sources/tech/20190213 How to build a WiFi picture frame with a Raspberry Pi.md b/sources/tech/20190213 How to build a WiFi picture frame with a Raspberry Pi.md
deleted file mode 100644
index 615f7620ed..0000000000
--- a/sources/tech/20190213 How to build a WiFi picture frame with a Raspberry Pi.md
+++ /dev/null
@@ -1,135 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to build a WiFi picture frame with a Raspberry Pi)
-[#]: via: (https://opensource.com/article/19/2/wifi-picture-frame-raspberry-pi)
-[#]: author: (Manuel Dewald https://opensource.com/users/ntlx)
-
-How to build a WiFi picture frame with a Raspberry Pi
-======
-DIY a digital photo frame that streams photos from the cloud.
-
-
-
-Digital picture frames are really nice because they let you enjoy your photos without having to print them out. Plus, adding and removing digital files is a lot easier than opening a traditional frame and swapping the picture inside when you want to display a new photo. Even so, it's still a bit of overhead to remove your SD card, USB stick, or other storage from a digital picture frame, plug it into your computer, and copy new pictures onto it.
-
-An easier option is a digital picture frame that gets its pictures over WiFi, for example from a cloud service. Here's how to make one.
-
-### Gather your materials
-
- * Old [TFT][1] LCD screen
- * HDMI-to-DVI cable (as the TFT screen supports DVI)
- * Raspberry Pi 3
- * Micro SD card
- * Raspberry Pi power supply
- * Keyboard
- * Mouse (optional)
-
-
-
-Connect the Raspberry Pi to the display using the cable and attach the power supply.
-
-### Install Raspbian
-
-**sudo raspi-config**. There I change the hostname (e.g., to **picframe** ) in Network Options and enable SSH to work remotely on the Raspberry Pi in Interfacing Options. Connect to the Raspberry Pi using (for example) .
-
-### Build and install the cloud client
-
-Download and flash Raspbian to the Micro SD card by following these [directions][2] . Plug the Micro SD card into the Raspberry Pi, boot it up, and configure your WiFi. My first action after a new Raspbian installation is usually running. There I change the hostname (e.g., to) in Network Options and enable SSH to work remotely on the Raspberry Pi in Interfacing Options. Connect to the Raspberry Pi using (for example)
-
-I use [Nextcloud][3] to synchronize my pictures, but you could use NFS, [Dropbox][4], or whatever else fits your needs to upload pictures to the frame.
-
-If you use Nextcloud, get a client for Raspbian by following these [instructions][5]. This is handy for placing new pictures on your picture frame and will give you the client application you may be familiar with on a desktop PC. When connecting the client application to your Nextcloud server, make sure to select only the folder where you'll store the images you want to be displayed on the picture frame.
-
-### Set up the slideshow
-
-The easiest way I've found to set up the slideshow is with a [lightweight slideshow project][6] built for exactly this purpose. There are some alternatives, like configuring a screensaver, but this application appears to be the simplest to set up.
-
-On your Raspberry Pi, download the binaries from the latest release, unpack them, and move them to an executable folder:
-
-```
-wget https://github.com/NautiluX/slide/releases/download/v0.9.0/slide_pi_stretch_0.9.0.tar.gz
-tar xf slide_pi_stretch_0.9.0.tar.gz
-mv slide_0.9.0/slide /usr/local/bin/
-```
-
-Install the dependencies:
-
-```
-sudo apt install libexif12 qt5-default
-```
-
-Run the slideshow by executing the command below (don't forget to modify the path to your images). If you access your Raspberry Pi via SSH, set the **DISPLAY** variable to start the slideshow on the display attached to the Raspberry Pi.
-
-```
-DISPLAY=:0.0 slide -p /home/pi/nextcloud/picframe
-```
-
-### Autostart the slideshow
-
-To autostart the slideshow on Raspbian Stretch, create the following folder and add an **autostart** file to it:
-
-```
-mkdir -p /home/pi/.config/lxsession/LXDE/
-vi /home/pi/.config/lxsession/LXDE/autostart
-```
-
-Insert the following commands to autostart your slideshow. The **slide** command can be adjusted to your needs:
-
-```
-@xset s noblank
-@xset s off
-@xset -dpms
-@slide -p -t 60 -o 200 -p /home/pi/nextcloud/picframe
-```
-
-Disable screen blanking, which the Raspberry Pi normally does after 10 minutes, by editing the following file:
-
-```
-vi /etc/lightdm/lightdm.conf
-```
-
-and adding these two lines to the end:
-
-```
-[SeatDefaults]
-xserver-command=X -s 0 -dpms
-```
-
-### Configure a power-on schedule
-
-You can schedule your picture frame to turn on and off at specific times by using two simple cronjobs. For example, say you want it to turn on automatically at 7 am and turn off at 11 pm. Run **crontab -e** and insert the following two lines.
-
-```
-0 23 * * * /opt/vc/bin/tvservice -o
-
-0 7 * * * /opt/vc/bin/tvservice -p && sudo systemctl restart display-manager
-```
-
-Note that this won't turn the Raspberry Pi power's on and off; it will just turn off HDMI, which will turn the screen off. The first line will power off HDMI at 11 pm. The second line will bring the display back up and restart the display manager at 7 am.
-
-### Add a final touch
-
-By following these simple steps, you can create your own WiFi picture frame. If you want to give it a nicer look, build a wooden frame for the display.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/2/wifi-picture-frame-raspberry-pi
-
-作者:[Manuel Dewald][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ntlx
-[b]: https://github.com/lujun9972
-[1]: https://en.wikipedia.org/wiki/Thin-film-transistor_liquid-crystal_display
-[2]: https://www.raspberrypi.org/documentation/installation/installing-images/README.md
-[3]: https://nextcloud.com/
-[4]: http://dropbox.com/
-[5]: https://github.com/nextcloud/client_theming#building-on-debian
-[6]: https://github.com/NautiluX/slide/releases/tag/v0.9.0
diff --git a/sources/tech/20190218 Talk, then code.md b/sources/tech/20190218 Talk, then code.md
deleted file mode 100644
index 18ed81e43c..0000000000
--- a/sources/tech/20190218 Talk, then code.md
+++ /dev/null
@@ -1,64 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Talk, then code)
-[#]: via: (https://dave.cheney.net/2019/02/18/talk-then-code)
-[#]: author: (Dave Cheney https://dave.cheney.net/author/davecheney)
-
-Talk, then code
-======
-
-The open source projects that I contribute to follow a philosophy which I describe as _talk, then code_. I think this is generally a good way to develop software and I want to spend a little time talking about the benefits of this methodology.
-
-### Avoiding hurt feelings
-
-The most important reason for discussing the change you want to make is it avoids hurt feelings. Often I see a contributor work hard in isolation on a pull request only to find their work is rejected. This can be for a bunch of reasons; the PR is too large, the PR doesn’t follow the local style, the PR fixes an issue which wasn’t important to the project or was recently fixed indirectly, and many more.
-
-The underlying cause of all these issues is a lack of communication. The goal of the _talk, then code_ philosophy is not to impede or frustrate, but to ensure that a feature lands correctly the first time, without incurring significant maintenance debt, and neither the author of the change, or the reviewer, has to carry the emotional burden of dealing with hurt feelings when a change appears out of the blue with an implicit “well, I’ve done the work, all you have to do is merge it, right?”
-
-### What does discussion look like?
-
-Every new feature or bug fix should be discussed with the maintainer(s) of the project before work commences. It’s fine to experiment privately, but do not send a change without discussing it first.
-
-The definition of _talk_ for simple changes can be as little as a design sketch in a GitHub issue. If your PR fixes a bug, you should link to the bug it fixes. If there isn’t one, you should raise a bug and wait for the maintainers to acknowledge it before sending a PR. This might seem a little backward–who wouldn’t want a bug fixed–but consider the bug could be a misunderstanding in how the software works or it could be a symptom of a larger problem that needs further investigation.
-
-For more complicated changes, especially feature requests, I recommend that a design document be circulated and agreed upon before sending code. This doesn’t have to be a full blown document, a sketch in an issue may be sufficient, but the key is to reach agreement using words, before locking it in stone with code.
-
-In all cases you shouldn’t proceed to send code until there is a positive agreement from the maintainer that the approach is one they are happy with. A pull request is for life, not just for Christmas.
-
-### Code review, not design by committee
-
-A code review is not the place for arguments about design. This is for two reasons. First, most code review tools are not suitable for long comment threads, GitHub’s PR interface is very bad at this, Gerrit is better, but few have a team of admins to maintain a Gerrit instance. More importantly, disagreements at the code review stage suggests there wasn’t agreement on how the change should be implemented.
-
-* * *
-
-Talk about what you want to code, then code what you talked about. Please don’t do it the other way around.
-
-### Related posts:
-
- 1. [How to include C code in your Go package][1]
- 2. [Let’s talk about logging][2]
- 3. [The value of TDD][3]
- 4. [Suggestions for contributing to an Open Source project][4]
-
-
-
---------------------------------------------------------------------------------
-
-via: https://dave.cheney.net/2019/02/18/talk-then-code
-
-作者:[Dave Cheney][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://dave.cheney.net/author/davecheney
-[b]: https://github.com/lujun9972
-[1]: https://dave.cheney.net/2013/09/07/how-to-include-c-code-in-your-go-package (How to include C code in your Go package)
-[2]: https://dave.cheney.net/2015/11/05/lets-talk-about-logging (Let’s talk about logging)
-[3]: https://dave.cheney.net/2016/04/11/the-value-of-tdd (The value of TDD)
-[4]: https://dave.cheney.net/2016/03/12/suggestions-for-contributing-to-an-open-source-project (Suggestions for contributing to an Open Source project)
diff --git a/sources/tech/20190325 Reducing sysadmin toil with Kubernetes controllers.md b/sources/tech/20190325 Reducing sysadmin toil with Kubernetes controllers.md
index 80ddb77264..ab1207cc30 100644
--- a/sources/tech/20190325 Reducing sysadmin toil with Kubernetes controllers.md
+++ b/sources/tech/20190325 Reducing sysadmin toil with Kubernetes controllers.md
@@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
-[#]: translator: ( )
+[#]: translator: (chen-ni)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
@@ -140,7 +140,7 @@ via: https://opensource.com/article/19/3/reducing-sysadmin-toil-kubernetes-contr
作者:[Paul Czarkowski][a]
选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
+译者:[chen-ni](https://github.com/chen-ni)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
diff --git a/sources/tech/20190510 Learn to change history with git rebase.md b/sources/tech/20190510 Learn to change history with git rebase.md
deleted file mode 100644
index 4d46fef81f..0000000000
--- a/sources/tech/20190510 Learn to change history with git rebase.md
+++ /dev/null
@@ -1,597 +0,0 @@
-Translating by Scoutydren....
-
-
-[#]: collector: (lujun9972)
-[#]: translator: (Scoutydren)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Learn to change history with git rebase!)
-[#]: via: (https://git-rebase.io/)
-[#]: author: (git-rebase https://git-rebase.io/)
-
-Learn to change history with git rebase!
-======
-One of Git 's core value-adds is the ability to edit history. Unlike version control systems that treat the history as a sacred record, in git we can change history to suit our needs. This gives us a lot of powerful tools and allows us to curate a good commit history in the same way we use refactoring to uphold good software design practices. These tools can be a little bit intimidating to the novice or even intermediate git user, but this guide will help to demystify the powerful git-rebase .
-
-```
-A word of caution : changing the history of public, shared, or stable branches is generally advised against. Editing the history of feature branches and personal forks is fine, and editing commits that you haven't pushed yet is always okay. Use git push -f to force push your changes to a personal fork or feature branch after editing your commits.
-```
-
-Despite the scary warning, it's worth mentioning that everything mentioned in this guide is a non-destructive operation. It's actually pretty difficult to permanently lose data in git. Fixing things when you make mistakes is covered at the end of this guide.
-
-### Setting up a sandbox
-
-We don't want to mess up any of your actual repositories, so throughout this guide we'll be working with a sandbox repo. Run these commands to get started:
-
-```
-git init /tmp/rebase-sandbox
-cd /tmp/rebase-sandbox
-git commit --allow-empty -m"Initial commit"
-```
-
-If you run into trouble, just run rm -rf /tmp/rebase-sandbox and run these steps again to start over. Each step of this guide can be run on a fresh sandbox, so it's not necessary to re-do every task.
-
-
-### Amending your last commit
-
-Let's start with something simple: fixing your most recent commit. Let's add a file to our sandbox - and make a mistake:
-
-```
-echo "Hello wrold!" >greeting.txt
- git add greeting.txt
- git commit -m"Add greeting.txt"
-```
-
-Fixing this mistake is pretty easy. We can just edit the file and commit with `--amend`, like so:
-
-```
-echo "Hello world!" >greeting.txt
- git commit -a --amend
-```
-
-Specifying `-a` automatically stages (i.e. `git add`'s) all files that git already knows about, and `--amend` will squash the changes into the most recent commit. Save and quit your editor (you have a chance to change the commit message now if you'd like). You can see the fixed commit by running `git show`:
-
-```
-commit f5f19fbf6d35b2db37dcac3a55289ff9602e4d00 (HEAD -> master)
-Author: Drew DeVault
-Date: Sun Apr 28 11:09:47 2019 -0400
-
- Add greeting.txt
-
-diff --git a/greeting.txt b/greeting.txt
-new file mode 100644
-index 0000000..cd08755
---- /dev/null
-+++ b/greeting.txt
-@@ -0,0 +1 @@
-+Hello world!
-```
-
-### Fixing up older commits
-
-Amending only works for the most recent commit. What happens if you need to correct an older commit? Let's start by setting up our sandbox accordingly:
-
-```
-echo "Hello!" >greeting.txt
-git add greeting.txt
-git commit -m"Add greeting.txt"
-
-echo "Goodbye world!" >farewell.txt
-git add farewell.txt
-git commit -m"Add farewell.txt"
-```
-
-Looks like `greeting.txt` is missing "world". Let's write a commit normally which fixes that:
-
-```
-echo "Hello world!" >greeting.txt
-git commit -a -m"fixup greeting.txt"
-```
-
-So now the files look correct, but our history could be better - let's use the new commit to "fixup" the last one. For this, we need to introduce a new tool: the interactive rebase. We're going to edit the last three commits this way, so we'll run `git rebase -i HEAD~3` (`-i` for interactive). This'll open your text editor with something like this:
-
-```
-pick 8d3fc77 Add greeting.txt
-pick 2a73a77 Add farewell.txt
-pick 0b9d0bb fixup greeting.txt
-
-# Rebase f5f19fb..0b9d0bb onto f5f19fb (3 commands)
-#
-# Commands:
-# p, pick = use commit
-# f, fixup = like "squash", but discard this commit's log message
-```
-
-This is the rebase plan, and by editing this file you can instruct git on how to edit history. I've trimmed the summary to just the details relevant to this part of the rebase guide, but feel free to skim the full summary in your text editor.
-
-When we save and close our editor, git is going to remove all of these commits from its history, then execute each line one at a time. By default, it's going to pick each commit, summoning it from the heap and adding it to the branch. If we don't edit this file at all, we'll end up right back where we started, picking every commit as-is. We're going to use one of my favorite features now: fixup. Edit the third line to change the operation from "pick" to "fixup" and move it to immediately after the commit we want to "fix up":
-
-```
-pick 8d3fc77 Add greeting.txt
-fixup 0b9d0bb fixup greeting.txt
-pick 2a73a77 Add farewell.txt
-```
-
-**Tip** : We can also abbreviate this with just "f" to speed things up next time.
-
-Save and quit your editor - git will run these commands. We can check the log to verify the result:
-
-```
-$ git log -2 --oneline
-fcff6ae (HEAD -> master) Add farewell.txt
-a479e94 Add greeting.txt
-```
-
-### Squashing several commits into one
-
-As you work, you may find it useful to write lots of commits as you reach small milestones or fix bugs in previous commits. However, it may be useful to "squash" these commits together, to make a cleaner history before merging your work into master. For this, we'll use the "squash" operation. Let's start by writing a bunch of commits - just copy and paste this if you want to speed it up:
-
-```
-git checkout -b squash
-for c in H e l l o , ' ' w o r l d; do
- echo "$c" >>squash.txt
- git add squash.txt
- git commit -m"Add '$c' to squash.txt"
-done
-```
-
-That's a lot of commits to make a file that says "Hello, world"! Let's start another interactive rebase to squash them together. Note that we checked out a branch to try this on, first. Because of that, we can quickly rebase all of the commits since we branched by using `git rebase -i master`. The result:
-
-```
-pick 1e85199 Add 'H' to squash.txt
-pick fff6631 Add 'e' to squash.txt
-pick b354c74 Add 'l' to squash.txt
-pick 04aaf74 Add 'l' to squash.txt
-pick 9b0f720 Add 'o' to squash.txt
-pick 66b114d Add ',' to squash.txt
-pick dc158cd Add ' ' to squash.txt
-pick dfcf9d6 Add 'w' to squash.txt
-pick 7a85f34 Add 'o' to squash.txt
-pick c275c27 Add 'r' to squash.txt
-pick a513fd1 Add 'l' to squash.txt
-pick 6b608ae Add 'd' to squash.txt
-
-# Rebase 1af1b46..6b608ae onto 1af1b46 (12 commands)
-#
-# Commands:
-# p, pick = use commit
-# s, squash = use commit, but meld into previous commit
-```
-
-**Tip** : your local master branch evolves independently of the remote master branch, and git stores the remote branch as `origin/master`. Combined with this trick, `git rebase -i origin/master` is often a very convenient way to rebase all of the commits which haven't been merged upstream yet!
-
-We're going to squash all of these changes into the first commit. To do this, change every "pick" operation to "squash", except for the first line, like so:
-
-```
-pick 1e85199 Add 'H' to squash.txt
-squash fff6631 Add 'e' to squash.txt
-squash b354c74 Add 'l' to squash.txt
-squash 04aaf74 Add 'l' to squash.txt
-squash 9b0f720 Add 'o' to squash.txt
-squash 66b114d Add ',' to squash.txt
-squash dc158cd Add ' ' to squash.txt
-squash dfcf9d6 Add 'w' to squash.txt
-squash 7a85f34 Add 'o' to squash.txt
-squash c275c27 Add 'r' to squash.txt
-squash a513fd1 Add 'l' to squash.txt
-squash 6b608ae Add 'd' to squash.txt
-```
-
-When you save and close your editor, git will think about this for a moment, then open your editor again to revise the final commit message. You'll see something like this:
-
-```
-# This is a combination of 12 commits.
-# This is the 1st commit message:
-
-Add 'H' to squash.txt
-
-# This is the commit message #2:
-
-Add 'e' to squash.txt
-
-# This is the commit message #3:
-
-Add 'l' to squash.txt
-
-# This is the commit message #4:
-
-Add 'l' to squash.txt
-
-# This is the commit message #5:
-
-Add 'o' to squash.txt
-
-# This is the commit message #6:
-
-Add ',' to squash.txt
-
-# This is the commit message #7:
-
-Add ' ' to squash.txt
-
-# This is the commit message #8:
-
-Add 'w' to squash.txt
-
-# This is the commit message #9:
-
-Add 'o' to squash.txt
-
-# This is the commit message #10:
-
-Add 'r' to squash.txt
-
-# This is the commit message #11:
-
-Add 'l' to squash.txt
-
-# This is the commit message #12:
-
-Add 'd' to squash.txt
-
-# Please enter the commit message for your changes. Lines starting
-# with '#' will be ignored, and an empty message aborts the commit.
-#
-# Date: Sun Apr 28 14:21:56 2019 -0400
-#
-# interactive rebase in progress; onto 1af1b46
-# Last commands done (12 commands done):
-# squash a513fd1 Add 'l' to squash.txt
-# squash 6b608ae Add 'd' to squash.txt
-# No commands remaining.
-# You are currently rebasing branch 'squash' on '1af1b46'.
-#
-# Changes to be committed:
-# new file: squash.txt
-#
-```
-
-This defaults to a combination of all of the commit messages which were squashed, but leaving it like this is almost always not what you want. The old commit messages may be useful for reference when writing the new one, though.
-
-**Tip** : the "fixup" command you learned about in the previous section can be used for this purpose, too - but it discards the messages of the squashed commits.
-
-Let's delete everything and replace it with a better commit message, like this:
-
-```
-Add squash.txt with contents "Hello, world"
-
-# Please enter the commit message for your changes. Lines starting
-# with '#' will be ignored, and an empty message aborts the commit.
-#
-# Date: Sun Apr 28 14:21:56 2019 -0400
-#
-# interactive rebase in progress; onto 1af1b46
-# Last commands done (12 commands done):
-# squash a513fd1 Add 'l' to squash.txt
-# squash 6b608ae Add 'd' to squash.txt
-# No commands remaining.
-# You are currently rebasing branch 'squash' on '1af1b46'.
-#
-# Changes to be committed:
-# new file: squash.txt
-#
-```
-
-Save and quit your editor, then examine your git log - success!
-
-```
-commit c785f476c7dff76f21ce2cad7c51cf2af00a44b6 (HEAD -> squash)
-Author: Drew DeVault
-Date: Sun Apr 28 14:21:56 2019 -0400
-
- Add squash.txt with contents "Hello, world"
-```
-
-Before we move on, let's pull our changes into the master branch and get rid of this scratch one. We can use `git rebase` like we use `git merge`, but it avoids making a merge commit:
-
-```
-git checkout master
-git rebase squash
-git branch -D squash
-```
-
-We generally prefer to avoid using git merge unless we're actually merging unrelated histories. If you have two divergent branches, a git merge is useful to have a record of when they were... merged. In the course of your normal work, rebase is often more appropriate.
-
-### Splitting one commit into several
-
-Sometimes the opposite problem happens - one commit is just too big. Let's look into splitting it up. This time, let's write some actual code. Start with a simple C program2 (you can still copy+paste this snippet into your shell to do this quickly):
-
-```
-cat <main.c
-int main(int argc, char *argv[]) {
- return 0;
-}
-EOF
-```
-
-We'll commit this first.
-
-```
-git add main.c
-git commit -m"Add C program skeleton"
-```
-
-Next, let's extend the program a bit:
-
-```
-cat <main.c
-#include <stdio.h>
-
-const char *get_name() {
- static char buf[128];
- scanf("%s", buf);
- return buf;
-}
-
-int main(int argc, char *argv[]) {
- printf("What's your name? ");
- const char *name = get_name();
- printf("Hello, %s!\n", name);
- return 0;
-}
-EOF
-```
-
-After we commit this, we'll be ready to learn how to split it up.
-
-```
-git commit -a -m"Flesh out C program"
-```
-
-The first step is to start an interactive rebase. Let's rebase both commits with `git rebase -i HEAD~2`, giving us this rebase plan:
-
-```
-pick 237b246 Add C program skeleton
-pick b3f188b Flesh out C program
-
-# Rebase c785f47..b3f188b onto c785f47 (2 commands)
-#
-# Commands:
-# p, pick = use commit
-# e, edit = use commit, but stop for amending
-```
-
-Change the second commit's command from "pick" to "edit", then save and close your editor. Git will think about this for a second, then present you with this:
-
-```
-Stopped at b3f188b... Flesh out C program
-You can amend the commit now, with
-
- git commit --amend
-
-Once you are satisfied with your changes, run
-
- git rebase --continue
-```
-
-We could follow these instructions to add new changes to the commit, but instead let's do a "soft reset"3 by running `git reset HEAD^`. If you run `git status` after this, you'll see that it un-commits the latest commit and adds its changes to the working tree:
-
-```
-Last commands done (2 commands done):
- pick 237b246 Add C program skeleton
- edit b3f188b Flesh out C program
-No commands remaining.
-You are currently splitting a commit while rebasing branch 'master' on 'c785f47'.
- (Once your working directory is clean, run "git rebase --continue")
-
-Changes not staged for commit:
- (use "git add ..." to update what will be committed)
- (use "git checkout -- ..." to discard changes in working directory)
-
- modified: main.c
-
-no changes added to commit (use "git add" and/or "git commit -a")
-```
-
-To split this up, we're going to do an interactive commit. This allows us to selectively commit only specific changes from the working tree. Run `git commit -p` to start this process, and you'll be presented with the following prompt:
-
-```
-diff --git a/main.c b/main.c
-index b1d9c2c..3463610 100644
---- a/main.c
-+++ b/main.c
-@@ -1,3 +1,14 @@
-+#include <stdio.h>
-+
-+const char *get_name() {
-+ static char buf[128];
-+ scanf("%s", buf);
-+ return buf;
-+}
-+
- int main(int argc, char *argv[]) {
-+ printf("What's your name? ");
-+ const char *name = get_name();
-+ printf("Hello, %s!\n", name);
- return 0;
- }
-Stage this hunk [y,n,q,a,d,s,e,?]?
-```
-
-Git has presented you with just one "hunk" (i.e. a single change) to consider committing. This one is too big, though - let's use the "s" command to "split" up the hunk into smaller parts.
-
-```
-Split into 2 hunks.
-@@ -1 +1,9 @@
-+#include
-+
-+const char *get_name() {
-+ static char buf[128];
-+ scanf("%s", buf);
-+ return buf;
-+}
-+
- int main(int argc, char *argv[]) {
-Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?
-```
-
-**Tip** : If you're curious about the other options, press "?" to summarize them.
-
-This hunk looks better - a single, self-contained change. Let's hit "y" to answer the question (and stage that "hunk"), then "q" to "quit" the interactive session and proceed with the commit. Your editor will pop up to ask you to enter a suitable commit message.
-
-```
-Add get_name function to C program
-
-# Please enter the commit message for your changes. Lines starting
-# with '#' will be ignored, and an empty message aborts the commit.
-#
-# interactive rebase in progress; onto c785f47
-# Last commands done (2 commands done):
-# pick 237b246 Add C program skeleton
-# edit b3f188b Flesh out C program
-# No commands remaining.
-# You are currently splitting a commit while rebasing branch 'master' on 'c785f47'.
-#
-# Changes to be committed:
-# modified: main.c
-#
-# Changes not staged for commit:
-# modified: main.c
-#
-```
-
-Save and close your editor, then we'll make the second commit. We could do another interactive commit, but since we just want to include the rest of the changes in this commit we'll just do this:
-
-```
-git commit -a -m"Prompt user for their name"
-git rebase --continue
-```
-
-That last command tells git that we're done editing this commit, and to continue to the next rebase command. That's it! Run `git log` to see the fruits of your labor:
-
-```
-$ git log -3 --oneline
-fe19cc3 (HEAD -> master) Prompt user for their name
-659a489 Add get_name function to C program
-237b246 Add C program skeleton
-```
-
-### Reordering commits
-
-This one is pretty easy. Let's start by setting up our sandbox:
-
-```
-echo "Goodbye now!" >farewell.txt
-git add farewell.txt
-git commit -m"Add farewell.txt"
-
-echo "Hello there!" >greeting.txt
-git add greeting.txt
-git commit -m"Add greeting.txt"
-
-echo "How're you doing?" >inquiry.txt
-git add inquiry.txt
-git commit -m"Add inquiry.txt"
-```
-
-The git log should now look like this:
-
-```
-f03baa5 (HEAD -> master) Add inquiry.txt
-a4cebf7 Add greeting.txt
-90bb015 Add farewell.txt
-```
-
-Clearly, this is all out of order. Let's do an interactive rebase of the past 3 commits to resolve this. Run `git rebase -i HEAD~3` and this rebase plan will appear:
-
-```
-pick 90bb015 Add farewell.txt
-pick a4cebf7 Add greeting.txt
-pick f03baa5 Add inquiry.txt
-
-# Rebase fe19cc3..f03baa5 onto fe19cc3 (3 commands)
-#
-# Commands:
-# p, pick = use commit
-#
-# These lines can be re-ordered; they are executed from top to bottom.
-```
-
-The fix is now straightforward: just reorder these lines in the order you wish for the commits to appear. Should look something like this:
-
-```
-pick a4cebf7 Add greeting.txt
-pick f03baa5 Add inquiry.txt
-pick 90bb015 Add farewell.txt
-```
-
-Save and close your editor and git will do the rest for you. Note that it's possible to end up with conflicts when you do this in practice - click here for help resolving conflicts.
-
-### git pull --rebase
-
-If you've been writing some commits on a branch which has been updated upstream, normally `git pull` will create a merge commit. In this respect, `git pull`'s behavior by default is equivalent to:
-
-```
-git fetch origin
-git merge origin/master
-```
-
-There's another option, which is often more useful and leads to a much cleaner history: `git pull --rebase`. Unlike the merge approach, this is equivalent to the following:
-
-```
-git fetch origin
-git rebase origin/master
-```
-
-The merge approach is simpler and easier to understand, but the rebase approach is almost always what you want to do if you understand how to use git rebase. If you like, you can set it as the default behavior like so:
-
-```
-git config --global pull.rebase true
-```
-
-When you do this, technically you're applying the procedure we discuss in the next section... so let's explain what it means to do that deliberately, too.
-
-### Using git rebase to... rebase
-
-Ironically, the feature of git rebase that I use the least is the one it's named for: rebasing branches. Say you have the following branches:
-
-```
-o--o--o--o--> master
- \--o--o--> feature-1
- \--o--> feature-2
-```
-
-It turns out feature-2 doesn't depend on any of the changes in feature-1, so you can just base it off of master. The fix is thus:
-
-```
-git checkout feature-2
-git rebase master
-```
-
-The non-interactive rebase does the default operation for all implicated commits ("pick")4, which simply rolls your history back to the last common anscestor and replays the commits from both branches. Your history now looks like this:
-
-```
-o--o--o--o--> master
- | \--o--> feature-2
- \--o--o--> feature-1
-```
-
-### Resolving conflicts
-
-The details on resolving merge conflicts are beyond the scope of this guide - keep your eye out for another guide for this in the future. Assuming you're familiar with resolving conflicts in general, here are the specifics that apply to rebasing.
-
-The details on resolving merge conflicts are beyond the scope of this guide - keep your eye out for another guide for this in the future. Assuming you're familiar with resolving conflicts in general, here are the specifics that apply to rebasing.
-
-Sometimes you'll get a merge conflict when doing a rebase, which you can handle just like any other merge conflict. Git will set up the conflict markers in the affected files, `git status` will show you what you need to resolve, and you can mark files as resolved with `git add` or `git rm`. However, in the context of a git rebase, there are two options you should be aware of.
-
-The first is how you complete the conflict resolution. Rather than `git commit` like you'll use when addressing conflicts that arise from `git merge`, the appropriate command for rebasing is `git rebase --continue`. However, there's another option available to you: `git rebase --skip`. This will skip the commit you're working on, and it won't be included in the rebase. This is most common when doing a non-interactive rebase, when git doesn't realize that a commit it's pulled from the "other" branch is an updated version of the commit that it conflicts with on "our" branch.
-
-### Help! I broke it!
-
-No doubt about it - rebasing can be hard sometimes. If you've made a mistake and in so doing lost commits which you needed, then `git reflog` is here to save the day. Running this command will show you every operation which changed a ref, or reference - that is, branches and tags. Each line shows you what the old reference pointed to, and you can `git cherry-pick`, `git checkout`, `git show`, or use any other operation on git commits once thought lost.
-
-
---------------------------------------------------------------------------------
-
-via: https://git-rebase.io/
-
-作者:[git-rebase][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://git-rebase.io/
-[b]: https://github.com/lujun9972
diff --git a/sources/tech/20190523 Run your blog on GitHub Pages with Python.md b/sources/tech/20190523 Run your blog on GitHub Pages with Python.md
deleted file mode 100644
index da6c13a20e..0000000000
--- a/sources/tech/20190523 Run your blog on GitHub Pages with Python.md
+++ /dev/null
@@ -1,235 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (MjSeven)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Run your blog on GitHub Pages with Python)
-[#]: via: (https://opensource.com/article/19/5/run-your-blog-github-pages-python)
-[#]: author: (Erik O'Shaughnessy https://opensource.com/users/jnyjny/users/jasperzanjani/users/jasperzanjani/users/jasperzanjani/users/jnyjny/users/jasperzanjani)
-
-Run your blog on GitHub Pages with Python
-======
-Create a blog with Pelican, a Python-based blogging platform that works
-well with GitHub.
-![Raspberry Pi and Python][1]
-
-[GitHub][2] is a hugely popular web service for source code control that uses [Git][3] to synchronize local files with copies kept on GitHub's servers so you can easily share and back up your work.
-
-In addition to providing a user interface for code repositories, GitHub also enables users to [publish web pages][4] directly from a repository. The website generation package GitHub recommends is [Jekyll][5], written in Ruby. Since I'm a bigger fan of [Python][6], I prefer [Pelican][7], a Python-based blogging platform that works well with GitHub.
-
-Pelican and Jekyll both transform content written in [Markdown][8] or [reStructuredText][9] into HTML to generate static websites, and both generators support themes that allow unlimited customization.
-
-In this article, I'll describe how to install Pelican, set up your GitHub repository, run a quickstart helper, write some Markdown files, and publish your first page. I'll assume that you have a [GitHub account][10], are comfortable with [basic Git commands][11], and want to publish a blog using Pelican.
-
-### Install Pelican and create the repo
-
-First things first, Pelican (and **ghp-import** ) must be installed on your local machine. This is super easy with [pip][12], the Python package installation tool (you have pip right?):
-
-
-```
-`$ pip install pelican ghp-import`
-```
-
-Next, open a browser and create a new repository on GitHub for your sweet new blog. Name it as follows (substituting your GitHub username for here and throughout this tutorial):
-
-
-```
-`https://GitHub.com/username/username.github.io`
-```
-
-Leave it empty; we will fill it with compelling blog content in a moment.
-
-Using a command line (you command line right?), clone your empty Git repository to your local machine:
-
-
-```
-$ git clone blog
-$ cd blog
-```
-
-### That one weird trick…
-
-Here's a not-super-obvious trick about publishing web content on GitHub. For user pages (pages hosted in repos named _username.github.io_ ), the content is served from the **master** branch.
-
-I strongly prefer not to keep all the Pelican configuration files and raw Markdown files in **master** , rather just the web content. So I keep the Pelican configuration and the raw content in a separate branch I like to call **content**. (You can call it whatever you want, but the following instructions will call it **content**.) I like this structure since I can throw away all the files in **master** and re-populate it with the **content** branch.
-
-
-```
-$ git checkout -b content
-Switched to a new branch 'content'
-```
-
-### Configure Pelican
-
-Now it's time for content configuration. Pelican provides a great initialization tool called **pelican-quickstart** that will ask you a series of questions about your blog.
-
-
-```
-$ pelican-quickstart
-Welcome to pelican-quickstart v3.7.1.
-
-This script will help you create a new Pelican-based website.
-
-Please answer the following questions so this script can generate the files
-needed by Pelican.
-
-> Where do you want to create your new web site? [.]
-> What will be the title of this web site? Super blog
-> Who will be the author of this web site? username
-> What will be the default language of this web site? [en]
-> Do you want to specify a URL prefix? e.g., (Y/n) n
-> Do you want to enable article pagination? (Y/n)
-> How many articles per page do you want? [10]
-> What is your time zone? [Europe/Paris] US/Central
-> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) y
-> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n) y
-> Do you want to upload your website using FTP? (y/N) n
-> Do you want to upload your website using SSH? (y/N) n
-> Do you want to upload your website using Dropbox? (y/N) n
-> Do you want to upload your website using S3? (y/N) n
-> Do you want to upload your website using Rackspace Cloud Files? (y/N) n
-> Do you want to upload your website using GitHub Pages? (y/N) y
-> Is this your personal page (username.github.io)? (y/N) y
-Done. Your new project is available at /Users/username/blog
-```
-
-You can take the defaults on every question except:
-
- * Website title, which should be unique and special
- * Website author, which can be a personal username or your full name
- * Time zone, which may not be in Paris
- * Upload to GitHub Pages, which is a "y" in our case
-
-
-
-After answering all the questions, Pelican leaves the following in the current directory:
-
-
-```
-$ ls
-Makefile content/ develop_server.sh*
-fabfile.py output/ pelicanconf.py
-publishconf.py
-```
-
-You can check out the [Pelican docs][13] to find out how to use those files, but we're all about getting things done _right now_. No, I haven't read the docs yet either.
-
-### Forge on
-
-Add all the Pelican-generated files to the **content** branch of the local Git repo, commit the changes, and push the local changes to the remote repo hosted on GitHub by entering:
-
-
-```
-$ git add .
-$ git commit -m 'initial pelican commit to content'
-$ git push origin content
-```
-
-This isn't super exciting, but it will be handy if we need to revert edits to one of these files.
-
-### Finally getting somewhere
-
-OK, now you can get bloggy! All of your blog posts, photos, images, PDFs, etc., will live in the **content** directory, which is initially empty. To begin creating a first post and an About page with a photo, enter:
-
-
-```
-$ cd content
-$ mkdir pages images
-$ cp /Users/username/SecretStash/HotPhotoOfMe.jpg images
-$ touch first-post.md
-$ touch pages/about.md
-```
-
-Next, open the empty file **first-post.md** in your favorite text editor and add the following:
-
-
-```
-title: First Post on My Sweet New Blog
-date:
-author: Your Name Here
-
-# I am On My Way To Internet Fame and Fortune!
-
-This is my first post on my new blog. While not super informative it
-should convey my sense of excitement and eagerness to engage with you,
-the reader!
-```
-
-The first three lines contain metadata that Pelican uses to organize things. There are lots of different metadata you can put there; again, the docs are your best bet for learning more about the options.
-
-Now, open the empty file **pages/about.md** and add this text:
-
-
-```
-title: About
-date:
-
-![So Schmexy][my_sweet_photo]
-
-Hi, I am and I wrote this epic collection of Interweb
-wisdom. In days of yore, much of this would have been deemed sorcery
-and I would probably have been burned at the stake.
-
-😆
-
-[my_sweet_photo]: {filename}/images/HotPhotoOfMe.jpg
-```
-
-You now have three new pieces of web content in your content directory. Of the content branch. That's a lot of content.
-
-### Publish
-
-Don't worry; the payoff is coming!
-
-All that's left to do is:
-
- * Run Pelican to generate the static HTML files in **output** : [code]`$ pelican content -o output -s publishconf.py`
-```
-* Use **ghp-import** to add the contents of the **output** directory to the **master** branch: [code]`$ ghp-import -m "Generate Pelican site" --no-jekyll -b master output`
-```
- * Push the local master branch to the remote repo: [code]`$ git push origin master`
-```
- * Commit and push the new content to the **content** branch: [code] $ git add content
-$ git commit -m 'added a first post, a photo and an about page'
-$ git push origin content
-```
-
-
-
-### OMG, I did it!
-
-Now the exciting part is here, when you get to view what you've published for everyone to see! Open your browser and enter:
-
-
-```
-`https://username.github.io`
-```
-
-Congratulations on your new blog, self-published on GitHub! You can follow this pattern whenever you want to add more pages or articles. Happy blogging.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/5/run-your-blog-github-pages-python
-
-作者:[Erik O'Shaughnessy][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/jnyjny/users/jasperzanjani/users/jasperzanjani/users/jasperzanjani/users/jnyjny/users/jasperzanjani
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/getting_started_with_python.png?itok=MFEKm3gl (Raspberry Pi and Python)
-[2]: https://github.com/
-[3]: https://git-scm.com
-[4]: https://help.github.com/en/categories/github-pages-basics
-[5]: https://jekyllrb.com
-[6]: https://python.org
-[7]: https://blog.getpelican.com
-[8]: https://guides.github.com/features/mastering-markdown
-[9]: http://docutils.sourceforge.net/docs/user/rst/quickref.html
-[10]: https://github.com/join?source=header-home
-[11]: https://git-scm.com/docs
-[12]: https://pip.pypa.io/en/stable/
-[13]: https://docs.getpelican.com
diff --git a/sources/tech/20190612 How to write a loop in Bash.md b/sources/tech/20190612 How to write a loop in Bash.md
deleted file mode 100644
index f63bff9cd3..0000000000
--- a/sources/tech/20190612 How to write a loop in Bash.md
+++ /dev/null
@@ -1,282 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to write a loop in Bash)
-[#]: via: (https://opensource.com/article/19/6/how-write-loop-bash)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth/users/goncasousa/users/howtopamm/users/howtopamm/users/seth/users/wavesailor/users/seth)
-
-How to write a loop in Bash
-======
-Automatically perform a set of actions on multiple files with for loops
-and find commands.
-![bash logo on green background][1]
-
-A common reason people want to learn the Unix shell is to unlock the power of batch processing. If you want to perform some set of actions on many files, one of the ways to do that is by constructing a command that iterates over those files. In programming terminology, this is called _execution control,_ and one of the most common examples of it is the **for** loop.
-
-A **for** loop is a recipe detailing what actions you want your computer to take _for_ each data object (such as a file) you specify.
-
-### The classic for loop
-
-An easy loop to try is one that analyzes a collection of files. This probably isn't a useful loop on its own, but it's a safe way to prove to yourself that you have the ability to handle each file in a directory individually. First, create a simple test environment by creating a directory and placing some copies of some files into it. Any file will do initially, but later examples require graphic files (such as JPEG, PNG, or similar). You can create the folder and copy files into it using a file manager or in the terminal:
-
-
-```
-$ mkdir example
-$ cp ~/Pictures/vacation/*.{png,jpg} example
-```
-
-Change directory to your new folder, then list the files in it to confirm that your test environment is what you expect:
-
-
-```
-$ cd example
-$ ls -1
-cat.jpg
-design_maori.png
-otago.jpg
-waterfall.png
-```
-
-The syntax to loop through each file individually in a loop is: create a variable ( **f** for file, for example). Then define the data set you want the variable to cycle through. In this case, cycle through all files in the current directory using the ***** wildcard character (the ***** wildcard matches _everything_ ). Then terminate this introductory clause with a semicolon ( **;** ).
-
-
-```
-`$ for f in * ;`
-```
-
-Depending on your preference, you can choose to press **Return** here. The shell won't try to execute the loop until it is syntactically complete.
-
-Next, define what you want to happen with each iteration of the loop. For simplicity, use the **file** command to get a little bit of data about each file, represented by the **f** variable (but prepended with a **$** to tell the shell to swap out the value of the variable for whatever the variable currently contains):
-
-
-```
-`do file $f ;`
-```
-
-Terminate the clause with another semi-colon and close the loop:
-
-
-```
-`done`
-```
-
-Press **Return** to start the shell cycling through _everything_ in the current directory. The **for** loop assigns each file, one by one, to the variable **f** and runs your command:
-
-
-```
-$ for f in * ; do
-> file $f ;
-> done
-cat.jpg: JPEG image data, EXIF standard 2.2
-design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-otago.jpg: JPEG image data, EXIF standard 2.2
-waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-```
-
-You can also write it this way:
-
-
-```
-$ for f in *; do file $f; done
-cat.jpg: JPEG image data, EXIF standard 2.2
-design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-otago.jpg: JPEG image data, EXIF standard 2.2
-waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-```
-
-Both the multi-line and single-line formats are the same to your shell and produce the exact same results.
-
-### A practical example
-
-Here's a practical example of how a loop can be useful for everyday computing. Assume you have a collection of vacation photos you want to send to friends. Your photo files are huge, making them too large to email and inconvenient to upload to your [photo-sharing service][2]. You want to create smaller web-versions of your photos, but you have 100 photos and don't want to spend the time reducing each photo, one by one.
-
-First, install the **ImageMagick** command using your package manager on Linux, BSD, or Mac. For instance, on Fedora and RHEL:
-
-
-```
-`$ sudo dnf install ImageMagick`
-```
-
-On Ubuntu or Debian:
-
-
-```
-`$ sudo apt install ImageMagick`
-```
-
-On BSD, use **ports** or [pkgsrc][3]. On Mac, use [Homebrew][4] or [MacPorts][5].
-
-Once you install ImageMagick, you have a set of new commands to operate on photos.
-
-Create a destination directory for the files you're about to create:
-
-
-```
-`$ mkdir tmp`
-```
-
-To reduce each photo to 33% of its original size, try this loop:
-
-
-```
-`$ for f in * ; do convert $f -scale 33% tmp/$f ; done`
-```
-
-Then look in the **tmp** folder to see your scaled photos.
-
-You can use any number of commands within a loop, so if you need to perform complex actions on a batch of files, you can place your whole workflow between the **do** and **done** statements of a **for** loop. For example, suppose you want to copy each processed photo straight to a shared photo directory on your web host and remove the photo file from your local system:
-
-
-```
-$ for f in * ; do
-convert $f -scale 33% tmp/$f
-scp -i seth_web tmp/$f [seth@example.com][6]:~/public_html
-trash tmp/$f ;
-done
-```
-
-For each file processed by the **for** loop, your computer automatically runs three commands. This means if you process just 10 photos this way, you save yourself 30 commands and probably at least as many minutes.
-
-### Limiting your loop
-
-A loop doesn't always have to look at every file. You might want to process only the JPEG files in your example directory:
-
-
-```
-$ for f in *.jpg ; do convert $f -scale 33% tmp/$f ; done
-$ ls -m tmp
-cat.jpg, otago.jpg
-```
-
-Or, instead of processing files, you may need to repeat an action a specific number of times. A **for** loop's variable is defined by whatever data you provide it, so you can create a loop that iterates over numbers instead of files:
-
-
-```
-$ for n in {0..4}; do echo $n ; done
-0
-1
-2
-3
-4
-```
-
-### More looping
-
-You now know enough to create your own loops. Until you're comfortable with looping, use them on _copies_ of the files you want to process and, as often as possible, use commands with built-in safeguards to prevent you from clobbering your data and making irreparable mistakes, like accidentally renaming an entire directory of files to the same name, each overwriting the other.
-
-For advanced **for** loop topics, read on.
-
-### Not all shells are Bash
-
-The **for** keyword is built into the Bash shell. Many similar shells use the same keyword and syntax, but some shells, like [tcsh][7], use a different keyword, like **foreach** , instead.
-
-In tcsh, the syntax is similar in spirit but more strict than Bash. In the following code sample, do not type the string **foreach?** in lines 2 and 3. It is a secondary prompt alerting you that you are still in the process of building your loop.
-
-
-```
-$ foreach f (*)
-foreach? file $f
-foreach? end
-cat.jpg: JPEG image data, EXIF standard 2.2
-design_maori.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-otago.jpg: JPEG image data, EXIF standard 2.2
-waterfall.png: PNG image data, 4608 x 2592, 8-bit/color RGB, non-interlaced
-```
-
-In tcsh, both **foreach** and **end** must appear alone on separate lines, so you cannot create a **for** loop on one line as you can with Bash and similar shells.
-
-### For loops with the find command
-
-In theory, you could find a shell that doesn't provide a **for** loop function, or you may just prefer to use a different command with added features.
-
-The **find** command is another way to implement the functionality of a **for** loop, as it offers several ways to define the scope of which files to include in your loop as well as options for [Parallel][8] processing.
-
-The **find** command is meant to help you find files on your hard drives. Its syntax is simple: you provide the path of the location you want to search, and **find** finds all files and directories:
-
-
-```
-$ find .
-.
-./cat.jpg
-./design_maori.png
-./otago.jpg
-./waterfall.png
-```
-
-You can filter the search results by adding some portion of the name:
-
-
-```
-$ find . -name "*jpg"
-./cat.jpg
-./otago.jpg
-```
-
-The great thing about **find** is that each file it finds can be fed into a loop using the **-exec** flag. For instance, to scale down only the PNG photos in your example directory:
-
-
-```
-$ find . -name "*png" -exec convert {} -scale 33% tmp/{} \;
-$ ls -m tmp
-design_maori.png, waterfall.png
-```
-
-In the **-exec** clause, the bracket characters **{}** stand in for whatever item **find** is processing (in other words, any file ending in PNG that has been located, one at a time). The **-exec** clause must be terminated with a semicolon, but Bash usually tries to use the semicolon for itself. You "escape" the semicolon with a backslash ( **\;** ) so that **find** knows to treat that semicolon as its terminating character.
-
-The **find** command is very good at what it does, and it can be too good sometimes. For instance, if you reuse it to find PNG files for another photo process, you will get a few errors:
-
-
-```
-$ find . -name "*png" -exec convert {} -flip -flop tmp/{} \;
-convert: unable to open image `tmp/./tmp/design_maori.png':
-No such file or directory @ error/blob.c/OpenBlob/2643.
-...
-```
-
-It seems that **find** has located all the PNG files—not only the ones in your current directory ( **.** ) but also those that you processed before and placed in your **tmp** subdirectory. In some cases, you may want **find** to search the current directory plus all other directories within it (and all directories in _those_ ). It can be a powerful recursive processing tool, especially in complex file structures (like directories of music artists containing directories of albums filled with music files), but you can limit this with the **-maxdepth** option.
-
-To find only PNG files in the current directory (excluding subdirectories):
-
-
-```
-`$ find . -maxdepth 1 -name "*png"`
-```
-
-To find and process files in the current directory plus an additional level of subdirectories, increment the maximum depth by 1:
-
-
-```
-`$ find . -maxdepth 2 -name "*png"`
-```
-
-Its default is to descend into all subdirectories.
-
-### Looping for fun and profit
-
-The more you use loops, the more time and effort you save, and the bigger the tasks you can tackle. You're just one user, but with a well-thought-out loop, you can make your computer do the hard work.
-
-You can and should treat looping like any other command, keeping it close at hand for when you need to repeat a single action or two on several files. However, it's also a legitimate gateway to serious programming, so if you have to accomplish a complex task on any number of files, take a moment out of your day to plan out your workflow. If you can achieve your goal on one file, then wrapping that repeatable process in a **for** loop is relatively simple, and the only "programming" required is an understanding of how variables work and enough organization to separate unprocessed from processed files. With a little practice, you can move from a Linux user to a Linux user who knows how to write a loop, so get out there and make your computer work for you!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/6/how-write-loop-bash
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth/users/goncasousa/users/howtopamm/users/howtopamm/users/seth/users/wavesailor/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bash_command_line.png?itok=k4z94W2U (bash logo on green background)
-[2]: http://nextcloud.com
-[3]: http://pkgsrc.org
-[4]: http://brew.sh
-[5]: https://www.macports.org
-[6]: mailto:seth@example.com
-[7]: https://en.wikipedia.org/wiki/Tcsh
-[8]: https://opensource.com/article/18/5/gnu-parallel
diff --git a/sources/tech/20190612 Why use GraphQL.md b/sources/tech/20190612 Why use GraphQL.md
deleted file mode 100644
index ad0d3a0056..0000000000
--- a/sources/tech/20190612 Why use GraphQL.md
+++ /dev/null
@@ -1,97 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Why use GraphQL?)
-[#]: via: (https://opensource.com/article/19/6/why-use-graphql)
-[#]: author: (Zach Lendon https://opensource.com/users/zachlendon/users/goncasousa/users/patrickhousley)
-
-Why use GraphQL?
-======
-Here's why GraphQL is gaining ground on standard REST API technology.
-![][1]
-
-[GraphQL][2], as I wrote [previously][3], is a next-generation API technology that is transforming both how client applications communicate with backend systems and how backend systems are designed.
-
-As a result of the support that began with the organization that founded it, Facebook, and continues with the backing of other technology giants such as Github, Twitter, and AirBnB, GraphQL's place as a linchpin technology for application systems seems secure; both now and long into the future.
-
-### GraphQL's ascent
-
-The rise in importance of mobile application performance and organizational agility has provided booster rockets for GraphQL's ascent to the top of modern enterprise architectures.
-
-Given that [REST][4] is a wildly popular architectural style that already allows mechanisms for data interaction, what advantages does this new technology provide over [REST][4]? The ‘QL’ in GraphQL stands for query language, and that is a great place to start.
-
-The ease at which different client applications within an organization can query only the data they need with GraphQL usurps alternative REST approaches and delivers real-world application performance boosts. With traditional [REST][4] API endpoints, client applications interrogate a server resource, and receive a response containing all the data that matches the request. If a successful response from a [REST][4] API endpoint returns 35 fields, the client application receives 35 fields
-
-### Fetching problems
-
-[REST][4] APIs traditionally provide no clean way for client applications to retrieve or update only the data they care about. This is often described as the “over-fetching” problem. With the prevalence of mobile applications in people’s day to day lives, the over-fetching problem has real world consequences. Every request a mobile application needs to make, every byte it has to send and receive, has an increasingly negative performance impact for end users. Users with slower data connections are particularly affected by suboptimal API design choices. Customers who experience poor performance using mobile applications are more likely to not purchase products and use services. Inefficient API designs cost companies money.
-
-“Over-fetching” isn’t alone - it has a partner in crime - “under-fetching”. Endpoints that, by default, return only a portion of the data a client actually needs require clients to make additional calls to satisfy their data needs - which requires additional HTTP requests. Because of the over and under fetching problems and their impact on client application performance, an API technology that facilitates efficient fetching has a chance to catch fire in the marketplace - and GraphQL has boldly jumped in and filled that void.
-
-### REST's response
-
-[REST][4] API designers, not willing to go down without a fight, have attempted to counter the mobile application performance problem through a mix of:
-
- * “include” and “exclude” query parameters, allowing client applications to specify which fields they want through a potentially long query format.
- * “Composite” services, which combine multiple endpoints in a way that allow client applications to be more efficient in the number of requests they make and the data they receive.
-
-
-
-While these patterns are a valiant attempt by the [REST][4] API community to address challenges mobile clients face, they fall short in a few key regards, namely:
-
- * Include and exclude query key/value pairs quickly get messy, in particular for deeper object graphs that require a nested dot notation syntax (or similar) to target data to include and exclude. Additionally, debugging issues with the query string in this model often requires manually breaking up a URL.
- * Server implementations for include and exclude queries are often custom, as there is no standard way for server-based applications to handle the use of include and exclude queries, just as there is no standard way for include and exclude queries to be defined.
- * The rise of composite services creates more tightly coupled back-end and front-end systems, requiring increasing coordination to deliver projects and turning once agile projects back to waterfall. This coordination and coupling has the painful side effect of slowing organizational agility. Additionally, composite services are by definition, not RESTful.
-
-
-
-### GraphQL's genesis
-
-For Facebook, GraphQL’s genesis was a response to pain felt and experiences learned from an HTML5-based version of their flagship mobile application back in 2011-2012. Understanding that improved performance was paramount, Facebook engineers realized that they needed a new API design to ensure peak performance. Likely taking the above [REST][4] limitations into consideration, and with needing to support different needs of a number of API clients, one can begin to understand the early seeds of what led co-creators Lee Byron and Dan Schaeffer, Facebook employees at the time, to create what has become known as GraphQL.
-
-With what is often a single GraphQL endpoint, through the GraphQL query language, client applications are able to reduce, often significantly, the number of network calls they need to make, and ensure that they only are retrieving the data they need. In many ways, this harkens back to earlier models of web programming, where client application code would directly query back-end systems - some might remember writing SQL queries with JSTL on JSPs 10-15 years ago for example!
-
-The biggest difference now is with GraphQL, we have a specification that is implemented across a variety of client and server languages and libraries. And with GraphQL being an API technology, we have decoupled the back-end and front-end application systems by introducing an intermediary GraphQL application layer that provides a mechanism to access organizational data in a manner that aligns with an organization’s business domain(s).
-
-Beyond solving technical challenges experienced by software engineering teams, GraphQL has also been a boost to organizational agility, in particular in the enterprise. GraphQL-enabled organizational agility increases are commonly attributable to the following:
-
- * Rather than creating new endpoints when 1 or more new fields are needed by clients, GraphQL API designers and developers are able to include those fields in existing graph implementations, exposing new capabilities in a fashion that requires less development effort and less change across application systems.
- * By encouraging API design teams to focus more on defining their object graph and be less focused on what client applications are delivering, the speed at which front-end and back-end software teams deliver solutions for customers has increasingly decoupled.
-
-
-
-### Considerations before adoption
-
-Despite GraphQL’s compelling benefits, GraphQL is not without its implementation challenges. A few examples include:
-
- * Caching mechanisms around [REST][4] APIs are much more mature.
- * The patterns used to build APIs using [REST][4] are much more well established.
- * While engineers may be more attracted to newer technologies like GraphQL, the talent pool in the marketplace is much broader for building [REST][4]-based solutions vs. GraphQL.
-
-
-
-### Conclusion
-
-By providing both a boost to performance and organizational agility, GraphQL's adoption by companies has skyrocketed in the past few years. It does, however, have some maturing to do in comparison to the RESTful ecosystem of API design.
-
-One of the great benefits of GraphQL is that it’s not designed as a wholesale replacement for alternative API solutions. Instead, GraphQL can be implemented to complement or enhance existing APIs. As a result, companies are encouraged to explore incrementally adopting GraphQL where it makes the most sense for them - where they find it has the greatest positive impact on application performance and organizational agility.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/6/why-use-graphql
-
-作者:[Zach Lendon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/zachlendon/users/goncasousa/users/patrickhousley
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_graph_stats_blue.png?itok=OKCc_60D
-[2]: https://graphql.org/
-[3]: https://opensource.com/article/19/6/what-is-graphql
-[4]: https://en.wikipedia.org/wiki/Representational_state_transfer
diff --git a/sources/tech/20190620 How to use OpenSSL- Hashes, digital signatures, and more.md b/sources/tech/20190620 How to use OpenSSL- Hashes, digital signatures, and more.md
deleted file mode 100644
index 724c97bc01..0000000000
--- a/sources/tech/20190620 How to use OpenSSL- Hashes, digital signatures, and more.md
+++ /dev/null
@@ -1,337 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to use OpenSSL: Hashes, digital signatures, and more)
-[#]: via: (https://opensource.com/article/19/6/cryptography-basics-openssl-part-2)
-[#]: author: (Marty Kalin https://opensource.com/users/mkalindepauledu)
-
-How to use OpenSSL: Hashes, digital signatures, and more
-======
-Dig deeper into the details of cryptography with OpenSSL: Hashes,
-digital signatures, digital certificates, and more
-![A person working.][1]
-
-The [first article in this series][2] introduced hashes, encryption/decryption, digital signatures, and digital certificates through the OpenSSL libraries and command-line utilities. This second article drills down into the details. Let’s begin with hashes, which are ubiquitous in computing, and consider what makes a hash function _cryptographic_.
-
-### Cryptographic hashes
-
-The download page for the OpenSSL source code () contains a table with recent versions. Each version comes with two hash values: 160-bit SHA1 and 256-bit SHA256. These values can be used to verify that the downloaded file matches the original in the repository: The downloader recomputes the hash values locally on the downloaded file and then compares the results against the originals. Modern systems have utilities for computing such hashes. Linux, for instance, has **md5sum** and **sha256sum**. OpenSSL itself provides similar command-line utilities.
-
-Hashes are used in many areas of computing. For example, the Bitcoin blockchain uses SHA256 hash values as block identifiers. To mine a Bitcoin is to generate a SHA256 hash value that falls below a specified threshold, which means a hash value with at least N leading zeroes. (The value of N can go up or down depending on how productive the mining is at a particular time.) As a point of interest, today’s miners are hardware clusters designed for generating SHA256 hashes in parallel. During a peak time in 2018, Bitcoin miners worldwide generated about 75 million terahashes per second—yet another incomprehensible number.
-
-Network protocols use hash values as well—often under the name **checksum**—to support message integrity; that is, to assure that a received message is the same as the one sent. The message sender computes the message’s checksum and sends the results along with the message. The receiver recomputes the checksum when the message arrives. If the sent and the recomputed checksum do not match, then something happened to the message in transit, or to the sent checksum, or to both. In this case, the message and its checksum should be sent again, or at least an error condition should be raised. (Low-level network protocols such as UDP do not bother with checksums.)
-
-Other examples of hashes are familiar. Consider a website that requires users to authenticate with a password, which the user enters in their browser. Their password is then sent, encrypted, from the browser to the server via an HTTPS connection to the server. Once the password arrives at the server, it's decrypted for a database table lookup.
-
-What should be stored in this lookup table? Storing the passwords themselves is risky. It’s far less risky is to store a hash generated from a password, perhaps with some _salt_ (extra bits) added to taste before the hash value is computed. Your password may be sent to the web server, but the site can assure you that the password is not stored there.
-
-Hash values also occur in various areas of security. For example, hash-based message authentication code ([HMAC][3]) uses a hash value and a secret cryptographic key to authenticate a message sent over a network. HMAC codes, which are lightweight and easy to use in programs, are popular in web services. An X509 digital certificate includes a hash value known as the _fingerprint_, which can facilitate certificate verification. An in-memory truststore could be implemented as a lookup table keyed on such fingerprints—as a _hash map_, which supports constant-time lookups. The fingerprint from an incoming certificate can be compared against the truststore keys for a match.
-
-What special property should a _cryptographic hash function_ have? It should be _one-way_, which means very difficult to invert. A cryptographic hash function should be relatively straightforward to compute, but computing its inverse—the function that maps the hash value back to the input bitstring—should be computationally intractable. Here is a depiction, with **chf** as a cryptographic hash function and my password **foobar** as the sample input:
-
-
-```
- +---+
-foobar—>|chf|—>hash value ## straightforward
- +--–+
-```
-
-By contrast, the inverse operation is infeasible:
-
-
-```
- +-----------+
-hash value—>|chf inverse|—>foobar ## intractable
- +-----------+
-```
-
-Recall, for example, the SHA256 hash function. For an input bitstring of any length N > 0, this function generates a fixed-length hash value of 256 bits; hence, this hash value does not reveal even the input bitstring’s length N, let alone the value of each bit in the string. By the way, SHA256 is not susceptible to a [_length extension attack_][4]. The only effective way to reverse engineer a computed SHA256 hash value back to the input bitstring is through a brute-force search, which means trying every possible input bitstring until a match with the target hash value is found. Such a search is infeasible on a sound cryptographic hash function such as SHA256.
-
-Now, a final review point is in order. Cryptographic hash values are statistically rather than unconditionally unique, which means that it is unlikely but not impossible for two different input bitstrings to yield the same hash value—a _collision_. The [_birthday problem_][5] offers a nicely counter-intuitive example of collisions. There is extensive research on various hash algorithms’ _collision resistance_. For example, MD5 (128-bit hash values) has a breakdown in collision resistance after roughly 221 hashes. For SHA1 (160-bit hash values), the breakdown starts at about 261 hashes.
-
-A good estimate of the breakdown in collision resistance for SHA256 is not yet in hand. This fact is not surprising. SHA256 has a range of 2256 distinct hash values, a number whose decimal representation has a whopping 78 digits! So, can collisions occur with SHA256 hashing? Of course, but they are extremely unlikely.
-
-In the command-line examples that follow, two input files are used as bitstring sources: **hashIn1.txt** and **hashIn2.txt**. The first file contains **abc** and the second contains **1a2b3c**.
-
-These files contain text for readability, but binary files could be used instead.
-
-Using the Linux **sha256sum** utility on these two files at the command line—with the percent sign (**%**) as the prompt—produces the following hash values (in hex):
-
-
-```
-% sha256sum hashIn1.txt
-9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3 hashIn1.txt
-
-% sha256sum hashIn2.txt
-3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13 hashIn2.txt
-```
-
-The OpenSSL hashing counterparts yield the same results, as expected:
-
-
-```
-% openssl dgst -sha256 hashIn1.txt
-SHA256(hashIn1.txt)= 9e83e05bbf9b5db17ac0deec3b7ce6cba983f6dc50531c7a919f28d5fb3696c3
-
-% openssl dgst -sha256 hashIn2.txt
-SHA256(hashIn2.txt)= 3eaac518777682bf4e8840dd012c0b104c2e16009083877675f00e995906ed13
-```
-
-This examination of cryptographic hash functions sets up a closer look at digital signatures and their relationship to key pairs.
-
-### Digital signatures
-
-As the name suggests, a digital signature can be attached to a document or some other electronic artifact (e.g., a program) to vouch for its authenticity. Such a signature is thus analogous to a hand-written signature on a paper document. To verify the digital signature is to confirm two things. First, that the vouched-for artifact has not changed since the signature was attached because it is based, in part, on a cryptographic _hash_ of the document. Second, that the signature belongs to the person (e.g., Alice) who alone has access to the private key in a pair. By the way, digitally signing code (source or compiled) has become a common practice among programmers.
-
-Let’s walk through how a digital signature is created. As mentioned before, there is no digital signature without a public and private key pair. When using OpenSSL to create these keys, there are two separate commands: one to create a private key, and another to extract the matching public key from the private one. These key pairs are encoded in base64, and their sizes can be specified during this process.
-
-The private key consists of numeric values, two of which (a _modulus_ and an _exponent_) make up the public key. Although the private key file contains the public key, the extracted public key does _not_ reveal the value of the corresponding private key.
-
-The resulting file with the private key thus contains the full key pair. Extracting the public key into its own file is practical because the two keys have distinct uses, but this extraction also minimizes the danger that the private key might be publicized by accident.
-
-Next, the pair’s private key is used to process a hash value for the target artifact (e.g., an email), thereby creating the signature. On the other end, the receiver’s system uses the pair’s public key to verify the signature attached to the artifact.
-
-Now for an example. To begin, generate a 2048-bit RSA key pair with OpenSSL:
-
-**openssl genpkey -out privkey.pem -algorithm rsa 2048**
-
-We can drop the **-algorithm rsa** flag in this example because **genpkey** defaults to the type RSA. The file’s name (**privkey.pem**) is arbitrary, but the Privacy Enhanced Mail (PEM) extension **pem** is customary for the default PEM format. (OpenSSL has commands to convert among formats if needed.) If a larger key size (e.g., 4096) is in order, then the last argument of **2048** could be changed to **4096**. These sizes are always powers of two.
-
-Here’s a slice of the resulting **privkey.pem** file, which is in base64:
-
-
-```
-\-----BEGIN PRIVATE KEY-----
-MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANnlAh4jSKgcNj/Z
-JF4J4WdhkljP2R+TXVGuKVRtPkGAiLWE4BDbgsyKVLfs2EdjKL1U+/qtfhYsqhkK
-…
-\-----END PRIVATE KEY-----
-```
-
-The next command then extracts the pair’s public key from the private one:
-
-**openssl rsa -in privkey.pem -outform PEM -pubout -out pubkey.pem**
-
-The resulting **pubkey.pem** file is small enough to show here in full:
-
-
-```
-\-----BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ5QIeI0ioHDY/2SReCeFnYZJY
-z9kfk11RrilUbT5BgIi1hOAQ24LMilS37NhHYyi9VPv6rX4WLKoZCmkeYaWk/TR5
-4nbH1E/AkniwRoXpeh5VncwWMuMsL5qPWGY8fuuTE27GhwqBiKQGBOmU+MYlZonO
-O0xnAKpAvysMy7G7qQIDAQAB
-\-----END PUBLIC KEY-----
-```
-
-Now, with the key pair at hand, the digital signing is easy—in this case with the source file **client.c** as the artifact to be signed:
-
-**openssl dgst -sha256 -sign privkey.pem -out sign.sha256 client.c**
-
-The digest for the **client.c** source file is SHA256, and the private key resides in the **privkey.pem** file created earlier. The resulting binary signature file is **sign.sha256**, an arbitrary name. To get a readable (if base64) version of this file, the follow-up command is:
-
-**openssl enc -base64 -in sign.sha256 -out sign.sha256.base64**
-
-The file **sign.sha256.base64** now contains:
-
-
-```
-h+e+3UPx++KKSlWKIk34fQ1g91XKHOGFRmjc0ZHPEyyjP6/lJ05SfjpAJxAPm075
-VNfFwysvqRGmL0jkp/TTdwnDTwt756Ej4X3OwAVeYM7i5DCcjVsQf5+h7JycHKlM
-o/Jd3kUIWUkZ8+Lk0ZwzNzhKJu6LM5KWtL+MhJ2DpVc=
-```
-
-Or, the executable file **client** could be signed instead, and the resulting base64-encoded signature would differ as expected:
-
-
-```
-VMVImPgVLKHxVBapJ8DgLNJUKb98GbXgehRPD8o0ImADhLqlEKVy0HKRm/51m9IX
-xRAN7DoL4Q3uuVmWWi749Vampong/uT5qjgVNTnRt9jON112fzchgEoMb8CHNsCT
-XIMdyaPtnJZdLALw6rwMM55MoLamSc6M/MV1OrJnk/g=
-```
-
-The final step in this process is to verify the digital signature with the public key. The hash used to sign the artifact (in this case, the executable **client** program) should be recomputed as an essential step in the verification since the verification process should indicate whether the artifact has changed since being signed.
-
-There are two OpenSSL commands used for this purpose. The first decodes the base64 signature:
-
-**openssl enc -base64 -d -in sign.sha256.base64 -out sign.sha256**
-
-The second verifies the signature:
-
-**openssl dgst -sha256 -verify pubkey.pem -signature sign.sha256 client**
-
-The output from this second command is, as it should be:
-
-
-```
-`Verified OK`
-```
-
-To understand what happens when verification fails, a short but useful exercise is to replace the executable **client** file in the last OpenSSL command with the source file **client.c** and then try to verify. Another exercise is to change the **client** program, however slightly, and try again.
-
-### Digital certificates
-
-A digital certificate brings together the pieces analyzed so far: hash values, key pairs, digital signatures, and encryption/decryption. The first step toward a production-grade certificate is to create a certificate signing request (CSR), which is then sent to a certificate authority (CA). To do this for the example with OpenSSL, run:
-
-**openssl req -out myserver.csr -new -newkey rsa:4096 -nodes -keyout myserverkey.pem**
-
-This example generates a CSR document and stores the document in the file **myserver.csr** (base64 text). The purpose here is this: the CSR document requests that the CA vouch for the identity associated with the specified domain name—the common name (CN) in CA-speak.
-
-A new key pair also is generated by this command, although an existing pair could be used. Note that the use of **server** in names such as **myserver.csr** and **myserverkey.pem** hints at the typical use of digital certificates: as vouchers for the identity of a web server associated with a domain such as [www.google.com][6].
-
-The same command, however, creates a CSR regardless of how the digital certificate might be used. It also starts an interactive question/answer session that prompts for relevant information about the domain name to link with the requester’s digital certificate. This interactive session can be short-circuited by providing the essentials as part of the command, with backslashes as continuations across line breaks. The **-subj** flag introduces the required information:
-
-
-```
-% openssl req -new
--newkey rsa:2048 -nodes -keyout privkeyDC.pem
--out myserver.csr
--subj "/C=US/ST=Illinois/L=Chicago/O=Faulty Consulting/OU=IT/CN=myserver.com"
-```
-
-The resulting CSR document can be inspected and verified before being sent to a CA. This process creates the digital certificate with the desired format (e.g., X509), signature, validity dates, and so on:
-
-**openssl req -text -in myserver.csr -noout -verify**
-
-Here’s a slice of the output:
-
-
-```
-verify OK
-Certificate Request:
-Data:
-Version: 0 (0x0)
-Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
-Subject Public Key Info:
-Public Key Algorithm: rsaEncryption
-Public-Key: (2048 bit)
-Modulus:
-00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e🇩🇪73:
-…
-Exponent: 65537 (0x10001)
-Attributes:
-a0:00
-Signature Algorithm: sha256WithRSAEncryption
-…
-```
-
-### A self-signed certificate
-
-During the development of an HTTPS web site, it is convenient to have a digital certificate on hand without going through the CA process. A self-signed certificate fills the bill during the HTTPS handshake’s authentication phase, although any modern browser warns that such a certificate is worthless. Continuing the example, the OpenSSL command for a self-signed certificate—valid for a year and with an RSA public key—is:
-
-**openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:4096 -keyout myserver.pem -out myserver.crt**
-
-The OpenSSL command below presents a readable version of the generated certificate:
-
-**openssl x509 -in myserver.crt -text -noout**
-
-Here’s part of the output for the self-signed certificate:
-
-
-```
-Certificate:
-Data:
-Version: 3 (0x2)
-Serial Number: 13951598013130016090 (0xc19e087965a9055a)
-Signature Algorithm: sha256WithRSAEncryption
-Issuer: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
-Validity
-Not Before: Apr 11 17:22:18 2019 GMT
-Not After : Apr 10 17:22:18 2020 GMT
-Subject: C=US, ST=Illinois, L=Chicago, O=Faulty Consulting, OU=IT, CN=myserver.com
-Subject Public Key Info:
-Public Key Algorithm: rsaEncryption
-Public-Key: (4096 bit)
-Modulus:
-00:ba:36:fb:57:17:65:bc:40:30:96:1b:6e🇩🇪73:
-…
-Exponent: 65537 (0x10001)
-X509v3 extensions:
-X509v3 Subject Key Identifier:
-3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
-X509v3 Authority Key Identifier:
-keyid:3A:32:EF:3D:EB:DF:65:E5:A8:96:D7:D7:16:2C:1B:29:AF:46:C4:91
-
- X509v3 Basic Constraints:
- CA:TRUE
-Signature Algorithm: sha256WithRSAEncryption
- 3a:eb:8d:09:53:3b:5c:2e:48:ed:14:ce:f9:20:01:4e:90:c9:
- ...
-```
-
-As mentioned earlier, an RSA private key contains values from which the public key is generated. However, a given public key does _not_ give away the matching private key. For an introduction to the underlying mathematics, see .
-
-There is an important correspondence between a digital certificate and the key pair used to generate the certificate, even if the certificate is only self-signed:
-
- * The digital certificate contains the _exponent_ and _modulus_ values that make up the public key. These values are part of the key pair in the originally-generated PEM file, in this case, the file **myserver.pem**.
- * The exponent is almost always 65,537 (as in this case) and so can be ignored.
- * The modulus from the key pair should match the modulus from the digital certificate.
-
-
-
-The modulus is a large value and, for readability, can be hashed. Here are two OpenSSL commands that check for the same modulus, thereby confirming that the digital certificate is based upon the key pair in the PEM file:
-
-
-```
-% openssl x509 -noout -modulus -in myserver.crt | openssl sha1 ## modulus from CRT
-(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769
-
-% openssl rsa -noout -modulus -in myserver.pem | openssl sha1 ## modulus from PEM
-(stdin)= 364d21d5e53a59d482395b1885aa2c3a5d2e3769
-```
-
-The resulting hash values match, thereby confirming that the digital certificate is based upon the specified key pair.
-
-### Back to the key distribution problem
-
-Let’s return to an issue raised at the end of Part 1: the TLS handshake between the **client** program and the Google web server. There are various handshake protocols, and even the Diffie-Hellman version at work in the **client** example offers wiggle room. Nonetheless, the **client** example follows a common pattern.
-
-To start, during the TLS handshake, the **client** program and the web server agree on a cipher suite, which consists of the algorithms to use. In this case, the suite is **ECDHE-RSA-AES128-GCM-SHA256**.
-
-The two elements of interest now are the RSA key-pair algorithm and the AES128 block cipher used for encrypting and decrypting messages if the handshake succeeds. Regarding encryption/decryption, this process comes in two flavors: symmetric and asymmetric. In the symmetric flavor, the _same_ key is used to encrypt and decrypt, which raises the _key distribution problem_ in the first place: How is the key to be distributed securely to both parties? In the asymmetric flavor, one key is used to encrypt (in this case, the RSA public key) but a different key is used to decrypt (in this case, the RSA private key from the same pair).
-
-The **client** program has the Google web server’s public key from an authenticating certificate, and the web server has the private key from the same pair. Accordingly, the **client** program can send an encrypted message to the web server, which alone can readily decrypt this message.
-
-In the TLS situation, the symmetric approach has two significant advantages:
-
- * In the interaction between the **client** program and the Google web server, the authentication is one-way. The Google web server sends three certificates to the **client** program, but the **client** program does not send a certificate to the web server; hence, the web server has no public key from the client and can’t encrypt messages to the client.
- * Symmetric encryption/decryption with AES128 is nearly a _thousand times faster_ than the asymmetric alternative using RSA keys.
-
-
-
-The TLS handshake combines the two flavors of encryption/decryption in a clever way. During the handshake, the **client** program generates random bits known as the pre-master secret (PMS). Then the **client** program encrypts the PMS with the server’s public key and sends the encrypted PMS to the server, which in turn decrypts the PMS message with its private key from the RSA pair:
-
-
-```
- +-------------------+ encrypted PMS +--------------------+
-client PMS--->|server’s public key|--------------->|server’s private key|--->server PMS
- +-------------------+ +--------------------+
-```
-
-At the end of this process, the **client** program and the Google web server now have the same PMS bits. Each side uses these bits to generate a _master secret_ and, in short order, a symmetric encryption/decryption key known as the _session key_. There are now two distinct but identical session keys, one on each side of the connection. In the **client** example, the session key is of the AES128 variety. Once generated on both the **client** program’s and Google web server’s sides, the session key on each side keeps the conversation between the two sides confidential. A handshake protocol such as Diffie-Hellman allows the entire PMS process to be repeated if either side (e.g., the **client** program) or the other (in this case, the Google web server) calls for a restart of the handshake.
-
-### Wrapping up
-
-The OpenSSL operations illustrated at the command line are available, too, through the API for the underlying libraries. These two articles have emphasized the utilities to keep the examples short and to focus on the cryptographic topics. If you have an interest in security issues, OpenSSL is a fine place to start—and to stay.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/6/cryptography-basics-openssl-part-2
-
-作者:[Marty Kalin][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/mkalindepauledu
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003784_02_os.comcareers_os_rh2x.png?itok=jbRfXinl (A person working.)
-[2]: https://opensource.com/article/19/6/cryptography-basics-openssl-part-1
-[3]: https://en.wikipedia.org/wiki/HMAC
-[4]: https://en.wikipedia.org/wiki/Length_extension_attack
-[5]: https://en.wikipedia.org/wiki/Birthday_problem
-[6]: http://www.google.com
diff --git a/sources/tech/20190624 Book Review- A Byte of Vim.md b/sources/tech/20190624 Book Review- A Byte of Vim.md
deleted file mode 100644
index e221a3bc6f..0000000000
--- a/sources/tech/20190624 Book Review- A Byte of Vim.md
+++ /dev/null
@@ -1,99 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Book Review: A Byte of Vim)
-[#]: via: (https://itsfoss.com/book-review-a-byte-of-vim/)
-[#]: author: (John Paul https://itsfoss.com/author/john/)
-
-Book Review: A Byte of Vim
-======
-
-[Vim][1] is a tool that is both simple and very powerful. Most new users will be intimidated by it because it doesn’t ‘work’ like regular graphical text editors. The ‘unusual’ keyboard shortcuts makes people wonder about [how to save and exit Vim][2]. But once you master Vim, there is nothing like it.
-
-There are numerous [Vim resources available online][3]. We have covered some Vim tricks on It’s FOSS as well. Apart from online resources, plenty of books have been dedicated to this editor as well. Today, we will look at one of such book that is designed to make Vim easy for most users to understand. The book we will be discussing is [A Byte of Vim][4] by [Swaroop C H][5].
-
-The author [Swaroop C H][6] has worked in computing for over a decade. He previously worked at Yahoo and Adobe. Out of college, he made money by selling Linux CDs. He started a number of businesses, including an iPod charger named ion. He is currently an engineering manager for the AI team at [Helpshift][7].
-
-### A Byte of Vim
-
-![][8]
-
-Like all good books, A Byte of Vim starts by talking about what Vim is: “a computer program used for writing any kind of text”. He does on to say, “What makes Vim special is that it is one of those few software which is both simple and powerful.”
-
-Before diving into telling how to use Vim, Swaroop tells the reader how to install Vim for Windows, Mac, Linux, and BSD. Once the installation is complete, he runs you through how to launch Vim and how to create your first file.
-
-Next, Swaroop discusses the different modes of Vim and how to navigate around your document using Vim’s keyboard shortcuts. This is followed by the basics of editing a document with Vim, including the Vim version of cut/copy/paste and undo/redo.
-
-Once the editing basics are covered, Swaroop talks about using Vim to edit multiple parts of a single document. You can also multiple tabs and windows to edit multiple documents at the same time.
-
-[][9]
-
-Suggested read Bring Your Old Computer Back to Life With 4MLinux
-
-The book also covers extending the functionality of Vim through scripting and installing plugins. There are two ways to using scripts in Vim, use Vim’s built-in scripting language or using a programming language like Python or Perl to access Vim’s internals. There are five types of Vim plugins that can be written or downloaded: vimrc, global plugin, filetype plugin, syntax highlighting plugin, and compiler plugin.
-
-In a separate section, Swaroop C H covers the features of Vim that make it good for programming. These features include syntax highlighting, smart indentation, support for shell commands, omnicompletion, and the ability to be used as an IDE.
-
-#### Getting the ‘A Byte of Vim’ book and contributing to it
-
-A Byte of Book is licensed under [Creative Commons 4.0][10]. You can read an online version of the book for free on [the author’s website][4]. You can also download a [PDF][11], [Epub][12], or [Mobi][13] for free.
-
-[Get A Byte of Vim for FREE][4]
-
-If you prefer reading a [hard copy][14], you have that option, as well.
-
-Please note that the _**original version of A Byte of Vim was written in 2008**_ and converted to PDf. Unfortunately, Swaroop C H lost the original source files and he is working to convert the book to [Markdown][15]. If you would like to help, please visit the [book’s GitHub page][16].
-
-Preview | Product | Price |
----|---|---|---
-![Mastering Vim Quickly: From WTF to OMG in no time][17] ![Mastering Vim Quickly: From WTF to OMG in no time][17] | [Mastering Vim Quickly: From WTF to OMG in no time][18] | $34.00[][19] | [Buy on Amazon][20]
-
-#### Conclusion
-
-When I first stared into the angry maw that is Vim, I did not have a clue what to do. I wish that I had known about A Byte of Vim then. This book is a good resource for anyone learning about Linux, especially if you are getting into the command line.
-
-Have you read [A Byte of Vim][4] by Swaroop C H? If yes, how do you find it? If not, what is your favorite book on an open source topic? Let us know in the comments below.
-
-[][21]
-
-Suggested read Iridium Browser: A Browser for the Privacy Conscious
-
-If you found this article interesting, please take a minute to share it on social media, Hacker News or [Reddit][22].
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/book-review-a-byte-of-vim/
-
-作者:[John Paul][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/john/
-[b]: https://github.com/lujun9972
-[1]: https://www.vim.org/
-[2]: https://itsfoss.com/how-to-exit-vim/
-[3]: https://linuxhandbook.com/basic-vim-commands/
-[4]: https://vim.swaroopch.com/
-[5]: https://swaroopch.com/
-[6]: https://swaroopch.com/about/
-[7]: https://www.helpshift.com/
-[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/06/Byte-of-vim-book.png?resize=800%2C450&ssl=1
-[9]: https://itsfoss.com/4mlinux-review/
-[10]: https://creativecommons.org/licenses/by/4.0/
-[11]: https://www.gitbook.com/download/pdf/book/swaroopch/byte-of-vim
-[12]: https://www.gitbook.com/download/epub/book/swaroopch/byte-of-vim
-[13]: https://www.gitbook.com/download/mobi/book/swaroopch/byte-of-vim
-[14]: https://swaroopch.com/buybook/
-[15]: https://itsfoss.com/best-markdown-editors-linux/
-[16]: https://github.com/swaroopch/byte-of-vim#status-incomplete
-[17]: https://i2.wp.com/images-na.ssl-images-amazon.com/images/I/41itW8furUL._SL160_.jpg?ssl=1
-[18]: https://www.amazon.com/Mastering-Vim-Quickly-WTF-time/dp/1983325740?SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1983325740 (Mastering Vim Quickly: From WTF to OMG in no time)
-[19]: https://www.amazon.com/gp/prime/?tag=chmod7mediate-20 (Amazon Prime)
-[20]: https://www.amazon.com/Mastering-Vim-Quickly-WTF-time/dp/1983325740?SubscriptionId=AKIAJ3N3QBK3ZHDGU54Q&tag=chmod7mediate-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=1983325740 (Buy on Amazon)
-[21]: https://itsfoss.com/iridium-browser-review/
-[22]: http://reddit.com/r/linuxusersgroup
diff --git a/sources/tech/20190702 One CI-CD pipeline per product to rule them all.md b/sources/tech/20190702 One CI-CD pipeline per product to rule them all.md
deleted file mode 100644
index 0fd04ee54a..0000000000
--- a/sources/tech/20190702 One CI-CD pipeline per product to rule them all.md
+++ /dev/null
@@ -1,136 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (hj24)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (One CI/CD pipeline per product to rule them all)
-[#]: via: (https://opensource.com/article/19/7/cicd-pipeline-rule-them-all)
-[#]: author: (Willy-Peter Schaub https://opensource.com/users/wpschaub/users/bclaster/users/matt-micene/users/barkerd427)
-
-One CI/CD pipeline per product to rule them all
-======
-Is the idea of a unified continuous integration and delivery pipeline a
-pipe dream?
-![An intersection of pipes.][1]
-
-When I joined the cloud ops team, responsible for cloud operations and engineering process streamlining, at WorkSafeBC, I shared my dream for one instrumented pipeline, with one continuous integration build and continuous deliveries for every product.
-
-According to Lukas Klose, [flow][2] (within the context of software engineering) is "the state of when a system produces value at a steady and predictable rate." I think it is one of the greatest challenges and opportunities, especially in the complex domain of emergent solutions. Strive towards a continuous and incremental delivery model with consistent, efficient, and quality solutions, building the right things and delighting our users. Find ways to break down our systems into smaller pieces that are valuable on their own, enabling teams to deliver value incrementally. This requires a change of mindset for both business and engineering.
-
-### Continuous integration and delivery (CI/CD) pipeline
-
-The CI/CD pipeline is a DevOps practice for delivering code changes more often, consistently, and reliably. It enables agile teams to increase _deployment frequency_ and decrease _lead time for change_, _change-failure rate_, and _mean time to recovery_ key performance indicators (KPIs), thereby improving _quality_ and delivering _value_ faster. The only prerequisites are a solid development process, a mindset for quality and accountability for features from ideation to deprecation, and a comprehensive pipeline (as illustrated below).
-
-![Prerequisites for a solid development process][3]
-
-It streamlines the engineering process and products to stabilize infrastructure environments; optimize flow; and create consistent, repeatable, and automated tasks. This enables us to turn complex tasks into complicated tasks, as outlined by Dave Snowden's [Cynefin Sensemaking][4] model, reducing maintenance costs and increasing quality and reliability.
-
-Part of streamlining our flow is to minimize waste for the [wasteful practice types][5] Muri (overloaded), Mura (variation), and Muda (waste).
-
- * **Muri:** avoid over-engineering, features that do not link to business value, and excessive documentation
- * **Mura:** improve approval and validation processes (e.g., security signoffs); drive the [shift-left][6] initiative to push unit testing, security vulnerability scanning, and code quality inspection; and improve risk assessment
- * **Muda:** avoid waste such as technical debt, bugs, and upfront, detailed documentation
-
-
-
-It appears that 80% of the focus and intention is on products that provide an integrated and collaborative engineering system that can take an idea and plan, develop, test, and monitor your solutions. However, a successful transformation and engineering system is only 5% about products, 15% about process, and 80% about people.
-
-There are many products at our disposal. For example, Azure DevOps offers rich support for continuous integration (CI), continuous delivery (CD), extensibility, and integration with open source and commercial off-the-shelve (COTS) software as a service (SaaS) solutions such as Stryker, SonarQube, WhiteSource, Jenkins, and Octopus. For engineers, it is always a temptation to focus on products, but remember that they are only 5% of our journey.
-
-![5% about products, 15% about process, 80% about people][7]
-
-The biggest challenge is breaking down a process based on decades of rules, regulations, and frustrating areas of comfort: "_It is how we have always done it; why change?_"
-
-The friction between people in development and operation results in a variety of fragmented, duplicated, and incessant integration and delivery pipelines. Development wants access to everything, to iterate continuously, to enable users, and to release continuously and fast. Operations wants to lock down everything to protect the business and users and drive quality. This inadvertently and often entails processes and governance that are hard to automate, which results in slower-than-expected release cycles.
-
-Let us explore the pipeline with snippets from a recent whiteboard discussion.
-
-The variation of pipelines is difficult and costly to support; the inconsistency of versioning and traceability complicates live site incidents, and continuous streamlining of the development process and pipelines is a challenge.
-
-![Improving quality and visibility of pipelines][8]
-
-I advocate a few principles that enable one universal pipeline per product:
-
- * Automate everything automatable
- * Build once
- * Maintain continuous integration and delivery
- * Maintain continuous streamlining and improvement
- * Maintain one build definition
- * Maintain one release pipeline definition
- * Scan for vulnerabilities early and often, and _fail fast_
- * Test early and often, and _fail fast_
- * Maintain traceability and observability of releases
-
-
-
-If I poke the hornet's nest, however, the most important principle is to _keep it simple_. If you cannot explain the reason (_what_, _why_) and the process (_how_) of your pipelines, you do not understand your engineering process. Most of us are not looking for the best, ultramodern, and revolutionary pipeline—we need one that is functional, valuable, and an enabler for engineering. Tackle the 80%—the culture, people, and their mindset—first. Ask your CI/CD knights in shining armor, with their TLA (two/three-lettered acronym) symbols on their shield, to join the might of practical and empirical engineering.
-
-### Unified pipeline
-
-Let us walk through one of our design practice whiteboard sessions.
-
-![CI build/CD release pipeline][9]
-
-Define one CI/CD pipeline with one build definition per application that is used to trigger _pull-request pre-merge validation_ and _continuous integration_ builds. Generate a _release_ build with debug information and upload to the [Symbol Server][10]. ****This enables developers to debug locally and remotely in production without having to worry which build and symbols they need to load—the symbol server performs that magic for us.
-
-![Breaking down the CI build pipeline][11]
-
-Perform as many validations as possible in the build—_shift left_—allowing feature teams to fail fast, continuously raise the overall product quality, and include invaluable evidence for the reviewers with every pull request. Do you prefer a pull request with a gazillion commits? Or a pull request with a couple of commits and supporting evidence such as security vulnerabilities, test coverage, code quality, and [Stryker][12] mutant remnants? Personally, I vote for the latter.
-
-![Breaking down the CD release pipeline][13]
-
-Do not use build transformation to generate multiple, environment-specific builds. Create one build and perform release-time _transformation_, _tokenization_, and/or XML/JSON _value replacement_. In other words, _shift-right_ the environment-specific configuration.
-
-![Shift-right the environment-specific configuration][14]
-
-Securely store release configuration data and make it available to both Dev and Ops teams based on the level of _trust_ and _sensitivity_ of the data. Use the open source Key Manager, Azure Key Vault, AWS Key Management Service, or one of many other products—remember, there are many hammers in your toolkit!
-
-![Dev-QA-production pipeline][15]
-
-Use _groups_ instead of _users_ to move approver management from multiple stages across multiple pipelines to simple group membership.
-
-![Move approver management to simple group membership][16]
-
-Instead of duplicating pipelines to give teams access to their _areas of interest_, create one pipeline and grant access to _specific stages_ of the delivery environments.
-
-![Pipeline with access to specific delivery stages][17]
-
-Last, but not least, embrace pull requests to help raise insight and transparency into your codebase, improve the overall quality, collaborate, and release pre-validation builds into selected environments; e.g., the Dev environment.
-
-Here is a more formal view of the whole whiteboard sketch.
-
-![The full pipeline][18]
-
-So, what are your thoughts and learnings with CI/CD pipelines? Is my dream of _one pipeline to rule them all_ a pipe dream?
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/7/cicd-pipeline-rule-them-all
-
-作者:[Willy-Peter Schaub][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/wpschaub/users/bclaster/users/matt-micene/users/barkerd427
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LAW-Internet_construction_9401467_520x292_0512_dc.png?itok=RPkPPtDe (An intersection of pipes.)
-[2]: https://continuingstudies.sauder.ubc.ca/courses/agile-delivery-methods/ii861
-[3]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-2.png (Prerequisites for a solid development process)
-[4]: https://en.wikipedia.org/wiki/Cynefin_framework
-[5]: https://www.lean.org/lexicon/muda-mura-muri
-[6]: https://en.wikipedia.org/wiki/Shift_left_testing
-[7]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-3.png (5% about products, 15% about process, 80% about people)
-[8]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-4_0.png (Improving quality and visibility of pipelines)
-[9]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-5_0.png (CI build/CD release pipeline)
-[10]: https://en.wikipedia.org/wiki/Microsoft_Symbol_Server
-[11]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-6.png (Breaking down the CI build pipeline)
-[12]: https://stryker-mutator.io/
-[13]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-7.png (Breaking down the CD release pipeline)
-[14]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-8.png (Shift-right the environment-specific configuration)
-[15]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-9.png (Dev-QA-production pipeline)
-[16]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-10.png (Move approver management to simple group membership)
-[17]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-11.png (Pipeline with access to specific delivery stages)
-[18]: https://opensource.com/sites/default/files/uploads/devops_pipeline_pipe-12.png (The full pipeline)
diff --git a/sources/tech/20190712 What is Silverblue.md b/sources/tech/20190712 What is Silverblue.md
deleted file mode 100644
index c23a45b9f8..0000000000
--- a/sources/tech/20190712 What is Silverblue.md
+++ /dev/null
@@ -1,98 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (What is Silverblue?)
-[#]: via: (https://fedoramagazine.org/what-is-silverblue/)
-[#]: author: (Tomáš Popela https://fedoramagazine.org/author/tpopela/)
-
-What is Silverblue?
-======
-
-![][1]
-
-Fedora Silverblue is becoming more and more popular inside and outside the Fedora world. So based on feedback from the community, here are answers to some interesting questions about the project. If you do have any other Silverblue related questions, please leave it in the comments section and we will try to answer them in a future article.
-
-### What is Silverblue?
-
-Silverblue is a codename for the new generation of the desktop operating system, previously known as Atomic Workstation. The operating system is delivered in images that are created by utilizing the _[rpm-ostree][2]_ [project][2]. The main benefits of the system are speed, security, atomic updates and immutability.
-
-### What does “Silverblue” actually mean?
-
-“Team Silverblue” or “Silverblue” in short doesn’t have any hidden meaning. It was chosen after roughly two months when the project, previously known as Atomic Workstation was rebranded. There were over 150 words or word combinations reviewed in the process. In the end _Silverblue_ was chosen because it had an available domain as well as the social network accounts. One could think of it as a new take on Fedora’s blue branding, and could be used in phrases like “Go, Team Silverblue!” or “Want to join the team and improve Silverblue?”.
-
-### What is ostree?
-
-[OSTree or libostree is a project][3] that combines a “git-like” model for committing and downloading bootable filesystem trees, together with a layer to deploy them and manage the bootloader configuration. OSTree is used by rpm-ostree, a hybrid package/image based system that Silverblue uses. It atomically replicates a base OS and allows the user to “layer” the traditional RPM on top of the base OS if needed.
-
-### Why use Silverblue?
-
-Because it allows you to concentrate on your work and not on the operating system you’re running. It’s more robust as the updates of the system are atomic. The only thing you need to do is to restart into the new image. Also, if there’s anything wrong with the currently booted image, you can easily reboot/rollback to the previous working one, if available. If it isn’t, you can download and boot any other image that was generated in the past, using the _ostree_ command.
-
-Another advantage is the possibility of an easy switch between branches (or, in an old context, Fedora releases). You can easily try the _[Rawhide][4]_ or _[updates-testing][5]_ branch and then return back to the one that contains the current stable release. Also, you should consider Silverblue if you want to try something new and unusual.
-
-### What are the benefits of an immutable OS?
-
-One of the main benefits is security. The base operating system is mounted as read-only, and thus cannot be modified by malicious software. The only way to alter the system is through the _rpm-ostree_ utility.
-
-Another benefit is robustness. It’s nearly impossible for a regular user to get the OS to the state when it doesn’t boot or doesn’t work properly after accidentally or unintentionally removing some system library. Try to think about these kind of experiences from your past, and imagine how Silverblue could help you there.
-
-### How does one manage applications and packages in Silverblue?
-
-For graphical user interface applications, [Flatpak][6] is recommended, if the application is available as a flatpak. Users can choose between Flatpaks from either Fedora and built from Fedora packages and in Fedora-owned infrastructure, or Flathub that currently has a wider offering. Users can install them easily through GNOME Software, which already supports Fedora Silverblue.
-
-One of the first things users find out is there is no _dnf_ preinstalled in the OS. The main reason is that it wouldn’t work on Silverblue — and part of its functionality was replaced by the _rpm-ostree_ command. Users can overlay the traditional packages by using the _rpm-ostree install PACKAGE_. But it should only be used when there is no other way. This is because when the new system images are pulled from the repository, the system image must be rebuilt every time it is altered to accommodate the layered packages, or packages that were removed from the base OS or replaced with a different version.
-
-Fedora Silverblue comes with the default set of GUI applications that are part of the base OS. The team is working on porting them to Flatpaks so they can be distributed that way. As a benefit, the base OS will become smaller and easier to maintain and test, and users can modify their default installation more easily. If you want to look at how it’s done or help, take a look at the official [documentation][7].
-
-### What is Toolbox?
-
-[_Toolbox_][8] is a project to make containers easily consumable for regular users. It does that by using _podman_’s rootless containers. _Toolbox_ lets you easily and quickly create a container with a regular Fedora installation that you can play with or develop on, separated from your OS.
-
-### Is there any Silverblue roadmap?
-
-Formally there isn’t any, as we’re focusing on problems we discover during our testing and from community feedback. We’re currently using Fedora’s [Taiga][9] to do our planning.
-
-### What’s the release life cycle of the Silverblue?
-
-It’s the same as regular Fedora Workstation. A new release comes every 6 months and is supported for 13 months. The team plans to release updates for the OS bi-weekly (or longer) instead of daily as they currently do. That way the updates can be more thoroughly tested by QA and community volunteers before they are sent to the rest of the users.
-
-### What is the future of the immutable OS?
-
-From our point of view the future of the desktop involves the immutable OS. It’s safest for the user, and Android, ChromeOS, and the last macOS Catalina all use this method under the hood. For the Linux desktop there are still problems with some third party software that expects to write to the OS. HP printer drivers are a good example.
-
-Another issue is how parts of the system are distributed and installed. Fonts are a good example. Currently in Fedora they’re distributed in RPM packages. If you want to use them, you have to overlay them and then restart to the newly created image that contains them.
-
-### What is the future of standard Workstation?
-
-There is a possibility that the Silverblue will replace the regular Workstation. But there’s still a long way to go for Silverblue to provide the same functionality and user experience as the Workstation. In the meantime both desktop offerings will be delivered at the same time.
-
-### How does Atomic Workstation or Fedora CoreOS relate to any of this?
-
-Atomic Workstation was the name of the project before it was renamed to Fedora Silverblue.
-
-Fedora CoreOS is a different, but similar project. It shares some fundamental technologies with Silverblue, such as _rpm-ostree_, _toolbox_ and others. Nevertheless, CoreOS is a more minimal, container-focused and automatically updating OS.
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/what-is-silverblue/
-
-作者:[Tomáš Popela][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://fedoramagazine.org/author/tpopela/
-[b]: https://github.com/lujun9972
-[1]: https://fedoramagazine.org/wp-content/uploads/2019/07/what-is-fedora-silverblue-816x345.jpg
-[2]: https://rpm-ostree.readthedocs.io/en/latest/
-[3]: https://ostree.readthedocs.io/en/latest/
-[4]: https://fedoraproject.org/wiki/Releases/Rawhide
-[5]: https://fedoraproject.org/wiki/QA:Updates_Testing
-[6]: https://flatpak.org/
-[7]: https://docs.fedoraproject.org/en-US/flatpak/tutorial/
-[8]: https://github.com/debarshiray/toolbox
-[9]: https://teams.fedoraproject.org/project/silverblue/
diff --git a/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md b/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md
index b4e1a2667b..b72de600e0 100644
--- a/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md
+++ b/sources/tech/20190804 Learn how to Install LXD - LXC Containers in Ubuntu.md
@@ -1,11 +1,11 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Learn how to Install LXD / LXC Containers in Ubuntu)
-[#]: via: (https://www.linuxtechi.com/install-lxd-lxc-containers-from-scratch/)
-[#]: author: (Shashidhar Soppin https://www.linuxtechi.com/author/shashidhar/)
+[#]: collector: "lujun9972"
+[#]: translator: "runningwater "
+[#]: reviewer: " "
+[#]: publisher: " "
+[#]: url: " "
+[#]: subject: "Learn how to Install LXD / LXC Containers in Ubuntu"
+[#]: via: "https://www.linuxtechi.com/install-lxd-lxc-containers-from-scratch/"
+[#]: author: "Shashidhar Soppin https://www.linuxtechi.com/author/shashidhar/"
Learn how to Install LXD / LXC Containers in Ubuntu
======
@@ -497,7 +497,7 @@ via: https://www.linuxtechi.com/install-lxd-lxc-containers-from-scratch/
作者:[Shashidhar Soppin][a]
选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
+译者:[runningwater](https://github.com/runningwater)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
diff --git a/sources/tech/20190808 Sending custom emails with Python.md b/sources/tech/20190808 Sending custom emails with Python.md
deleted file mode 100644
index fb8e0d3938..0000000000
--- a/sources/tech/20190808 Sending custom emails with Python.md
+++ /dev/null
@@ -1,257 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Sending custom emails with Python)
-[#]: via: (https://opensource.com/article/19/8/sending-custom-emails-python)
-[#]: author: (Brian "bex" Exelbierd https://opensource.com/users/bexelbie)
-
-Sending custom emails with Python
-======
-Customize your group emails with Mailmerge, a command-line program that
-can handle simple and complex emails.
-![Chat via email][1]
-
-Email remains a fact of life. Despite all its warts, it's still the best way to send information to most people, especially in automated ways that allow messages to queue for recipients.
-
-One of the highlights of my work as the [Fedora Community Action and Impact Coordinator][2] is giving people good news about travel funding. I often send this information over email. Here, I'll show you how I send custom messages to groups of people using [Mailmerge][3], a command-line Python program that can handle simple and complex emails.
-
-### Install Mailmerge
-
-Mailmerge is packaged and available in Fedora, and you can install it from the command line with **sudo dnf install python3-mailmerge**. You can also install it from PyPI using **pip**, as the project's [README explains][4].
-
-### Configure your Mailmerge files
-
-Three files control how Mailmerge works. If you run **mailmerge --sample**, it will create template files for you. The files are:
-
- * **mailmerge_server.conf:** This contains the configuration details for your SMTP host to send emails. Your password is _not_ stored in this file.
- * **mailmerge_database.csv:** This holds the custom data for each email, including the recipients' email addresses.
- * **mailmerge_template.txt:** This is your email's text with placeholder fields that will be replaced using the data from **mailmerge_database.csv**.
-
-
-
-#### Server.conf
-
-The sample **mailmerge_server.conf** file includes several examples that should be familiar. If you've ever added email to your phone or set up a desktop email client, you've seen this data before. The big thing to remember is to update your username in the file, especially if you are using one of the example configurations.
-
-#### Database.csv
-
-The **mailmerge_database.csv** file is a bit more complicated. It must contain (at minimum) the recipients' email addresses and any other custom details necessary to replace the fields in your email. It is a good idea to write the **mailmerge_template.txt** file at the same time you create the fields list for this file. I find it helpful to use a spreadsheet to capture this data and export it as a CSV file when I am done. This sample file:
-
-
-```
-email,name,number
-[myself@mydomain.com][5],"Myself",17
-[bob@bobdomain.com][6],"Bob",42
-```
-
-allows you to send emails to two people, using their first name and telling them a number. This file, while not terribly interesting, illustrates an important habit: Always make yourself the first recipient in the file. This enables you to send yourself a test email to verify everything works as expected before you email the entire list.
-
-If any of your values contain commas, you _**must**_ enclose the entire value in double-quotes (**"**). If you need to include a double-quote in a double-quoted field, use two double-quotes in a row. Quoting rules are fun, so read about [CSVs in Python 3][7] for specifics.
-
-#### Template.txt
-
-As part of my work, I get to share news about travel-funding decisions for our Fedora contributor conference, [Flock][8]. A simple email tells people they've been selected for travel funding and their specific funding details. One user-specific detail is how much money we can allocate for their airfare. Here is an abbreviated version of my template file (I've snipped out a lot of the text for brevity):
-
-
-```
-$ cat mailmerge_template.txt
-TO: {{Email}}
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-
-Hi {{Name}},
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: {{Travel_Budget}}
-
-<<snip>>
-```
-
-The top of the template specifies the recipient, sender, and subject. After the blank line, there's the body of the email. This email needs the recipients' **Email**, **Name**, and **Travel_Budget** from the **database.csv** file. Notice that those fields are surrounded by double curly braces (**{{** and **}}**). The corresponding **mailmerge_database.csv** looks like this:
-
-
-```
-$ cat mailmerge_database.csv
-Name,Email,Travel_Budget
-Brian,[bexelbie@redhat.com][9],1000
-PersonA,[persona@fedoraproject.org][10],1500
-PèrsonB,[personb@fedoraproject.org][11],500
-```
-
-Notice that I listed myself first (for testing) and there are two other people in the file. The second person, PèrsonB, has an accented character in their name; Mailmerge will automatically encode it.
-
-That's the whole template concept: Write your email and put placeholders in double curly braces. Then create a database that provides those values. Now let's test the email.
-
-### Test and send simple email merges
-
-#### Do a dry-run
-
-Start by doing a dry-run that prints the emails, with the placeholder fields completed, to the screen. By default, if you run the command **mailmerge**, it will do a dry-run of the first email:
-
-
-```
-$ mailmerge
->>> encoding ascii
->>> message 0
-TO: [bexelbie@redhat.com][9]
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="us-ascii"
-Content-Transfer-Encoding: 7bit
-Date: Sat, 20 Jul 2019 18:17:15 -0000
-
-Hi Brian,
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: 1000
-
-<<snip>>
-
->>> sent message 0 DRY RUN
->>> No attachments were sent with the emails.
->>> Limit was 1 messages. To remove the limit, use the --no-limit option.
->>> This was a dry run. To send messages, use the --no-dry-run option.
-```
-
-Reviewing the first email (**message 0**, as counting starts from zero, like many things in computer science), you can see my name and travel budget are correct. If you want to review every email, enter **mailmerge --no-limit** to tell Mailmerge not to limit itself to the first email. Here's the dry-run of the third email, which shows the special character encoding:
-
-
-```
->>> message 2
-TO: [personb@fedoraproject.org][11]
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-Date: Sat, 20 Jul 2019 18:22:48 -0000
-
-Hi P=E8rsonB,
-```
-
-That's not an error; **P=E8rsonB** is the encoded form of **PèrsonB**.
-
-#### Send a test message
-
-Now, send a test email with the command **mailmerge --no-dry-run**, which tells Mailmerge to send a message to the first email on the list:
-
-
-```
-$ mailmerge --no-dry-run
->>> encoding ascii
->>> message 0
-TO: [bexelbie@redhat.com][9]
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="us-ascii"
-Content-Transfer-Encoding: 7bit
-Date: Sat, 20 Jul 2019 18:25:45 -0000
-
-Hi Brian,
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: 1000
-
-<<snip>>
-
->>> Read SMTP server configuration from mailmerge_server.conf
->>> host = smtp.gmail.com
->>> port = 587
->>> username = [bexelbie@redhat.com][9]
->>> security = STARTTLS
->>> password for [bexelbie@redhat.com][9] on smtp.gmail.com:
->>> sent message 0
->>> No attachments were sent with the emails.
->>> Limit was 1 messages. To remove the limit, use the --no-limit option.
-```
-
-On the fourth to last line, you can see it prompts you for your password. If you're using two-factor authentication or domain-managed logins, you will need to create an application password that bypasses these controls. If you're using Gmail and similar systems, you can do it directly from the interface; otherwise, contact your email system administrator. This will not compromise the security of your email system, but you should still keep the password complex and secret.
-
-When I checked my email account, I received a beautifully formatted test email. If your test email looks ready, send all the emails by entering **mailmerge --no-dry-run --no-limit**.
-
-### Send complex emails
-
-You can really see the power of Mailmerge when you take advantage of [Jinja2 templating][12]. I've found it useful for including conditional text and sending attachments. Here is a complex template and the corresponding database:
-
-
-```
-$ cat mailmerge_template.txt
-TO: {{Email}}
-SUBJECT: Flock 2019 Funding Offer
-FROM: Brian Exelbierd <[bexelbie@redhat.com][9]>
-ATTACHMENT: attachments/{{File}}
-
-Hi {{Name}},
-
-I am writing you on behalf of the Flock funding committee. You requested funding for your attendance at Flock. After careful consideration we are able to offer you the following funding:
-
-Travel Budget: {{Travel_Budget}}
-{% if Hotel == "Yes" -%}
-Lodging: Lodging in the hotel Wednesday-Sunday (4 nights)
-{%- endif %}
-
-<<snip>>
-
-$ cat mailmerge_database.csv
-Name,Email,Travel_Budget,Hotel,File
-Brian,[bexelbie@redhat.com][9],1000,Yes,visa_bex.pdf
-PersonA,[persona@fedoraproject.org][10],1500,No,visa_person_a.pdf
-PèrsonB,[personb@fedoraproject.org][11],500,Yes,visa_person_b.pdf
-```
-
-There are two new things in this email. First, there's an attachment. I have to send visa invitation letters to international travelers to help them come to Flock, and the **ATTACHMENT** part of the header specifies which file to attach. To keep my directory clean, I put all of them in my Attachments subdirectory. Second, it includes conditional information about a hotel, because some people receive funding for their hotel stay, and I need to include those details for those who do. This is done with the **if** construction:
-
-
-```
-{% if Hotel == "Yes" -%}
-Lodging: Lodging in the hotel Wednesday-Sunday (4 nights)
-{%- endif %}
-```
-
-This works just like an **if** in most programming languages. Jinja2 is very expressive and can do multi-level conditions. Experiment with making your life easier by including database elements that control the contents of the email. Using whitespace is important for email readability. The minus (**-**) symbols in **if** and **endif** are part of how Jinja2 controls [whitespace][13]. There are lots of options, so experiment to see what looks best for you.
-
-Also note that I extended the database with two fields, **Hotel** and **File**. These are the values that control the inclusion of the hotel text and provide the name of the attachment. In my example, PèrsonB and I got hotel funding, while PersonA didn't.
-
-Doing a dry-run and sending the emails is the same whether you're using a simple or a complex template. Give it a try!
-
-You can also experiment with using conditionals (**if** … **endif**) in the header. You can, for example, have an attachment only if one is in the database, or maybe you need to change the sender's name for some emails but not others.
-
-### Mailmerge's advantages
-
-The Mailmerge program provides a powerful but simple method of sending lots of customized emails. Everyone gets only the information they need, and extraneous steps and details are omitted.
-
-Even for simple group emails, I have found this method much more effective than sending one email to a bunch of people using CC or BCC. A lot of people filter their email and delay reading anything not sent directly to them. Using Mailmerge ensures that every person gets their own email. Messages will filter properly for the recipient and no one can accidentally "reply all" to the entire group.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/8/sending-custom-emails-python
-
-作者:[Brian "bex" Exelbierd][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/bexelbie
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/email_chat_communication_message.png?itok=LKjiLnQu (Chat via email)
-[2]: https://docs.fedoraproject.org/en-US/council/fcaic/
-[3]: https://github.com/awdeorio/mailmerge
-[4]: https://github.com/awdeorio/mailmerge#install
-[5]: mailto:myself@mydomain.com
-[6]: mailto:bob@bobdomain.com
-[7]: https://docs.python.org/3/library/csv.html
-[8]: https://flocktofedora.org/
-[9]: mailto:bexelbie@redhat.com
-[10]: mailto:persona@fedoraproject.org
-[11]: mailto:personb@fedoraproject.org
-[12]: http://jinja.pocoo.org/docs/latest/templates/
-[13]: http://jinja.pocoo.org/docs/2.10/templates/#whitespace-control
diff --git a/sources/tech/20190814 9 open source cloud native projects to consider.md b/sources/tech/20190814 9 open source cloud native projects to consider.md
deleted file mode 100644
index 8f95262799..0000000000
--- a/sources/tech/20190814 9 open source cloud native projects to consider.md
+++ /dev/null
@@ -1,266 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (9 open source cloud native projects to consider)
-[#]: via: (https://opensource.com/article/19/8/cloud-native-projects)
-[#]: author: (Bryant Son https://opensource.com/users/brsonhttps://opensource.com/users/marcobravo)
-
-9 open source cloud native projects to consider
-======
-Work with containers? Get familiar with these projects from the Cloud
-Native Computing Foundation
-![clouds in the sky with blue pattern][1]
-
-As the practice of developing applications with containers is getting more popular, [cloud-native applications][2] are also on the rise. By [definition][3]:
-
-> "Cloud-native technologies are used to develop applications built with services packaged in containers, deployed as microservices, and managed on elastic infrastructure through agile DevOps processes and continuous delivery workflows."
-
-This description includes four elements that are integral to cloud-native applications:
-
- 1. Container
- 2. Microservice
- 3. DevOps
- 4. Continuous integration and continuous delivery (CI/CD)
-
-
-
-Although these technologies have very distinct histories, they complement each other well and have led to surprisingly exponential growth of cloud-native applications and toolsets in a short time. This [Cloud Native Computing Foundation][4] (CNCF) infographic shows the size and breadth of the cloud-native application ecosystem today.
-
-![Cloud-Native Computing Foundation applications ecosystem][5]
-
-Cloud-Native Computing Foundation projects
-
-I mean, just look at that! And this is just a start. Just as NodeJS’s creation sparked the explosion of endless JavaScript tools, the popularity of container technology started the exponential growth of cloud-native applications.
-
-The good news is that there are several organizations that oversee and connect these dots together. One is the [**Open Containers Initiative (OCI)**][6], which is a lightweight, open governance structure (or project), "formed under the auspices of the Linux Foundation for the express purpose of creating open industry standards around container formats and runtime." The other is the **CNCF**, "an open source software foundation dedicated to making cloud native computing universal and sustainable."
-
-In addition to building a community around cloud-native applications generally, CNCF also helps projects set up structured governance around their cloud-native applications. CNCF created the concept of maturity levels—Sandbox, Incubating, or Graduated—which correspond to the Innovators, Early Adopters, and Early Majority tiers on the diagram below.
-
-![CNCF project maturity levels][7]
-
-CNCF project maturity levels
-
-The CNCF has detailed [criteria][8] for each maturity level (included below for readers’ convenience). A two-thirds supermajority of the Technical Oversight Committee (TOC) is required for a project to be Incubating or Graduated.
-
-### Sandbox stage
-
-> To be accepted in the sandbox, a project must have at least two TOC sponsors. See the CNCF Sandbox Guidelines v1.0 for the detailed process.
-
-### Incubating stage
-
-> Note: The incubation level is the point at which we expect to perform full due diligence on projects.
->
-> To be accepted to incubating stage, a project must meet the sandbox stage requirements plus:
->
-> * Document that it is being used successfully in production by at least three independent end users which, in the TOC’s judgement, are of adequate quality and scope.
-> * Have a healthy number of committers. A committer is defined as someone with the commit bit; i.e., someone who can accept contributions to some or all of the project.
-> * Demonstrate a substantial ongoing flow of commits and merged contributions.
-> * Since these metrics can vary significantly depending on the type, scope, and size of a project, the TOC has final judgement over the level of activity that is adequate to meet these criteria
->
-
-
-### Graduated stage
-
-> To graduate from sandbox or incubating status, or for a new project to join as a graduated project, a project must meet the incubating stage criteria plus:
->
-> * Have committers from at least two organizations.
-> * Have achieved and maintained a Core Infrastructure Initiative Best Practices Badge.
-> * Have completed an independent and third party security audit with results published of similar scope and quality as the following example (including critical vulnerabilities addressed): and all critical vulnerabilities need to be addressed before graduation.
-> * Adopt the CNCF Code of Conduct.
-> * Explicitly define a project governance and committer process. This preferably is laid out in a GOVERNANCE.md file and references an OWNERS.md file showing the current and emeritus committers.
-> * Have a public list of project adopters for at least the primary repo (e.g., ADOPTERS.md or logos on the project website).
-> * Receive a supermajority vote from the TOC to move to graduation stage. Projects can attempt to move directly from sandbox to graduation, if they can demonstrate sufficient maturity. Projects can remain in an incubating state indefinitely, but they are normally expected to graduate within two years.
->
-
-
-## 9 projects to consider
-
-While it’s impossible to cover all of the CNCF projects in this article, I’ll describe are nine of most interesting Graduated and Incubating open source projects.
-
-Name | License | What It Is
----|---|---
-[Kubernetes][9] | Apache 2.0 | Orchestration platform for containers
-[Prometheus][10] | Apache 2.0 | Systems and service monitoring tool
-[Envoy][11] | Apache 2.0 | Edge and service proxy
-[rkt][12] | Apache 2.0 | Pod-native container engine
-[Jaeger][13] | Apache 2.0 | Distributed tracing system
-[Linkerd][14] | Apache 2.0 | Transparent service mesh
-[Helm][15] | Apache 2.0 | Kubernetes package manager
-[Etcd][16] | Apache 2.0 | Distributed key-value store
-[CRI-O][17] | Apache 2.0 | Lightweight runtime for Kubernetes
-
-I also created this video tutorial to walk through these projects.
-
-## Graduated projects
-
-Graduated projects are considered mature—adopted by many organizations—and must adhere to the CNCF’s guidelines. Following are three of the most popular open source CNCF Graduated projects. (Note that some of these descriptions are adapted and reused from the projects' websites.)
-
-### Kubernetes
-
-Ah, Kubernetes. How can we talk about cloud-native applications without mentioning Kubernetes? Invented by Google, Kubernetes is undoubtedly the most famous container-orchestration platform for container-based applications, and it is also an open source tool.
-
-What is a container orchestration platform? Basically, a container engine on its own may be okay for managing a few containers. However, when you are talking about thousands of containers and hundreds of services, managing those containers becomes super complicated. This is where the container engine comes in. The container-orchestration engine helps scale containers by automating the deployment, management, networking, and availability of containers.
-
-Docker Swarm and Mesosphere Marathon are other container-orchestration engines, but it is safe to say that Kubernetes has won the race (at least for now). Kubernetes also gave birth to Container-as-a-Service (CaaS) platforms like [OKD][18], the Origin community distribution of Kubernetes that powers [Red Hat OpenShift][19].
-
-To get started, visit the [Kubernetes GitHub repository][9], and access its documentation and learning resources from the [Kubernetes documentation][20] page.
-
-### Prometheus
-
-Prometheus is an open source system monitoring and alerting toolkit built at SoundCloud in 2012. Since then, many companies and organizations have adopted Prometheus, and the project has a very active developer and user community. It is now a standalone open source project that is maintained independently of the company.
-
-![Prometheus’ architecture][21]
-
-Prometheus’ architecture
-
-The easiest way to think about Prometheus is to visualize a production system that needs to be up 24 hours a day and 365 days a year. No system is perfect, and there are techniques to reduce failures (called fault-tolerant systems). However, if an issue occurs, the most important thing is to identify it as soon as possible. That is where a monitoring tool like Prometheus comes in handy. Prometheus is more than a container-monitoring tool, but it is most popular among cloud-native application companies. In addition, other open source monitoring tools, including [Grafana][22], leverage Prometheus.
-
-The best way to get started with Prometheus is to check out its [GitHub repo][10]. Running Prometheus locally is easy, but you need to have a container engine installed. You can access detailed documentation on [Prometheus’ website][23].
-
-### Envoy
-
-Envoy (or Envoy Proxy) is an open source edge and service proxy designed for cloud-native applications. Created at Lyft, Envoy is a high-performance, C++, distributed proxy designed for single services and applications, as well as a communications bus and a universal data plane designed for large microservice service mesh architectures. Built on the learnings of solutions such as Nginx, HAProxy, hardware load balancers, and cloud load balancers, Envoy runs alongside every application and abstracts the network by providing common features in a platform-agnostic manner.
-
-When all service traffic in an infrastructure flows through an Envoy mesh, it becomes easy to visualize problem areas via consistent observability, tune overall performance, and add substrate features in a single place. Basically, Envoy Proxy is a service mesh tool that helps organizations build a fault-tolerant system for production environments.
-
-There are numerous alternatives for service mesh applications, such as Uber’s [Linkerd][24] (discussed below) and [Istio][25]. Istio extends Envoy Proxy by deploying as a [Sidecar][26] and leveraging the [Mixer][27] configuration model. Notable Envoy features are:
-
- * All the "table stakes" features (when paired with a control plane, like Istio) are included
- * Low, 99th percentile latencies at scale when running under load
- * Acts as an L3/L4 filter at its core with many L7 filters provided out of the box
- * Support for gRPC and HTTP/2 (upstream/downstream)
- * It’s API-driven and supports dynamic configuration and hot reloads
- * Has a strong focus on metric collection, tracing, and overall observability
-
-
-
-Understanding Envoy, proving its capabilities, and realizing its full benefits require extensive experience with running production-level environments. You can learn more in its [detailed documentation][28] and by accessing its [GitHub][11] repository.
-
-## Incubating projects
-
-Following are six of the most popular open source CNCF Incubating projects.
-
-### rkt
-
-rkt, pronounced "rocket," is a pod-native container engine. It has a command-line interface (CLI) for running containers on Linux. In a sense, it is similar to other containers, like [Podman][29], Docker, and CRI-O.
-
-rkt was originally developed by CoreOS (later acquired by Red Hat), and you can find detailed [documentation][30] on its website and access the source code on [GitHub][12].
-
-### Jaeger
-
-Jaeger is an open source, end-to-end distributed tracing system for cloud-native applications. In one way, it is a monitoring solution like Prometheus. Yet it is different because its use cases extend into:
-
- * Distributed transaction monitoring
- * Performance and latency optimization
- * Root-cause analysis
- * Service dependency analysis
- * Distributed context propagation
-
-
-
-Jaeger is an open source technology built by Uber. You can find [detailed documentation][31] on its website and its [source code][13] on GitHub.
-
-### Linkerd
-
-Like Lyft with Envoy Proxy, Uber developed Linkerd as an open source solution to maintain its service at the production level. In some ways, Linkerd is just like Envoy, as both are service mesh tools designed to give platform-wide observability, reliability, and security without requiring configuration or code changes.
-
-However, there are some subtle differences between the two. While Envoy and Linkerd function as proxies and can report over services that are connected, Envoy isn’t designed to be a Kubernetes Ingress controller, as Linkerd is. Notable features of Linkerd include:
-
- * Support for multiple platforms (Docker, Kubernetes, DC/OS, Amazon ECS, or any stand-alone machine)
- * Built-in service discovery abstractions to unite multiple systems
- * Support for gRPC, HTTP/2, and HTTP/1.x requests plus all TCP traffic
-
-
-
-You can read more about it on [Linkerd’s website][32] and access its source code on [GitHub][14].
-
-### Helm
-
-Helm is basically the package manager for Kubernetes. If you’ve used Apache Maven, Maven Nexus, or a similar service, you will understand Helm’s purpose. Helm helps you manage your Kubernetes application. It uses "Helm Charts" to define, install, and upgrade even the most complex Kubernetes applications. Helm isn’t the only method for this; another concept becoming popular is [Kubernetes Operators][33], which are used by Red Hat OpenShift 4.
-
-You can try Helm by following the [quickstart guide][34] in its documentation or its [GitHub guide][15].
-
-### Etcd
-
-Etcd is a distributed, reliable key-value store for the most critical data in a distributed system. Its key features are:
-
- * Well-defined, user-facing API (gRPC)
- * Automatic TLS with optional client certificate authentication
- * Speed (benchmarked at 10,000 writes per second)
- * Reliability (distributed using Raft)
-
-
-
-Etcd is used as a built-in default data storage for Kubernetes and many other technologies. That said, it is rarely run independently or as a separate service; instead, it utilizes the one integrated into Kubernetes, OKD/OpenShift, or another service. There is also an [etcd Operator][35] to manage its lifecycle and unlock its API management capabilities:
-
-You can learn more in [etcd’s documentation][36] and access its [source code][16] on GitHub.
-
-### CRI-O
-
-CRI-O is an Open Container Initiative (OCI)-compliant implementation of the Kubernetes runtime interface. CRI-O is used for various functions including:
-
- * Runtime using runc (or any OCI runtime-spec implementation) and OCI runtime tools
- * Image management using containers/image
- * Storage and management of image layers using containers/storage
- * Networking support through the Container Network Interface (CNI)
-
-
-
-CRI-O provides plenty of [documentation][37], including guides, tutorials, articles, and even podcasts, and you can also access its [GitHub page][17].
-
-* * *
-
-Did I miss an interesting open source cloud-native project? Please let me know in the comments.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/8/cloud-native-projects
-
-作者:[Bryant Son][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/brsonhttps://opensource.com/users/marcobravo
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003601_05_mech_osyearbook2016_cloud_cc.png?itok=XSV7yR9e (clouds in the sky with blue pattern)
-[2]: https://opensource.com/article/18/7/what-are-cloud-native-apps
-[3]: https://thenewstack.io/10-key-attributes-of-cloud-native-applications/
-[4]: https://www.cncf.io
-[5]: https://opensource.com/sites/default/files/uploads/cncf_1.jpg (Cloud-Native Computing Foundation applications ecosystem)
-[6]: https://www.opencontainers.org
-[7]: https://opensource.com/sites/default/files/uploads/cncf_2.jpg (CNCF project maturity levels)
-[8]: https://github.com/cncf/toc/blob/master/process/graduation_criteria.adoc
-[9]: https://github.com/kubernetes/kubernetes
-[10]: https://github.com/prometheus/prometheus
-[11]: https://github.com/envoyproxy/envoy
-[12]: https://github.com/rkt/rkt
-[13]: https://github.com/jaegertracing/jaeger
-[14]: https://github.com/linkerd/linkerd
-[15]: https://github.com/helm/helm
-[16]: https://github.com/etcd-io/etcd
-[17]: https://github.com/cri-o/cri-o
-[18]: https://www.okd.io/
-[19]: https://www.openshift.com
-[20]: https://kubernetes.io/docs/home
-[21]: https://opensource.com/sites/default/files/uploads/cncf_3.jpg (Prometheus’ architecture)
-[22]: https://grafana.com
-[23]: https://prometheus.io/docs/introduction/overview
-[24]: https://linkerd.io/
-[25]: https://istio.io/
-[26]: https://istio.io/docs/reference/config/networking/v1alpha3/sidecar
-[27]: https://istio.io/docs/reference/config/policy-and-telemetry
-[28]: https://www.envoyproxy.io/docs/envoy/latest
-[29]: https://podman.io
-[30]: https://coreos.com/rkt/docs/latest
-[31]: https://www.jaegertracing.io/docs/1.13
-[32]: https://linkerd.io/2/overview
-[33]: https://coreos.com/operators
-[34]: https://helm.sh/docs
-[35]: https://github.com/coreos/etcd-operator
-[36]: https://etcd.io/docs/v3.3.12
-[37]: https://github.com/cri-o/cri-o/blob/master/awesome.md
diff --git a/sources/tech/20190814 How to install Python on Windows.md b/sources/tech/20190814 How to install Python on Windows.md
deleted file mode 100644
index a3b7ea2454..0000000000
--- a/sources/tech/20190814 How to install Python on Windows.md
+++ /dev/null
@@ -1,203 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to install Python on Windows)
-[#]: via: (https://opensource.com/article/19/8/how-install-python-windows)
-[#]: author: (Seth Kenlon https://opensource.com/users/sethhttps://opensource.com/users/greg-p)
-
-How to install Python on Windows
-======
-Install Python, run an IDE, and start coding right from your Microsoft
-Windows desktop.
-![Hands programming][1]
-
-So you want to learn to program? One of the most common languages to start with is [Python][2], popular for its unique blend of [object-oriented][3] structure and simple syntax. Python is also an _interpreted_ _language_, meaning you don't need to learn how to compile code into machine language: Python does that for you, allowing you to test your programs sometimes instantly and, in a way, while you write your code.
-
-Just because Python is easy to learn doesn't mean you should underestimate its potential power. Python is used by [movie][4] [studios][5], financial institutions, IT houses, video game studios, makers, hobbyists, [artists][6], teachers, and many others.
-
-On the other hand, Python is also a serious programming language, and learning it takes dedication and practice. Then again, you don't have to commit to anything just yet. You can install and try Python on nearly any computing platform, so if you're on Windows, this article is for you.
-
-If you want to try Python on a completely open source operating system, you can [install Linux][7] and then [try Python][8].
-
-### Get Python
-
-Python is available from its website, [Python.org][9]. Once there, hover your mouse over the **Downloads** menu, then over the **Windows** option, and then click the button to download the latest release.
-
-![Downloading Python on Windows][10]
-
-Alternatively, you can click the **Downloads** menu button and select a specific version from the downloads page.
-
-### Install Python
-
-Once the package is downloaded, open it to start the installer.
-
-It is safe to accept the default install location, and it's vital to add Python to PATH. If you don't add Python to your PATH, then Python applications won't know where to find Python (which they require in order to run). This is _not_ selected by default, so activate it at the bottom of the install window before continuing!
-
-![Select "Add Python 3 to PATH"][11]
-
-Before Windows allows you to install an application from a publisher other than Microsoft, you must give your approval. Click the **Yes** button when prompted by the **User Account Control** system.
-
-![Windows UAC][12]
-
-Wait patiently for Windows to distribute the files from the Python package into the appropriate locations, and when it's finished, you're done installing Python.
-
-Time to play.
-
-### Install an IDE
-
-To write programs in Python, all you really need is a text editor, but it's convenient to have an integrated development environment (IDE). An IDE integrates a text editor with some friendly and helpful Python features. IDLE 3 and NINJA-IDE are two options to consider.
-
-#### IDLE 3
-
-Python comes with an IDE called IDLE. You can write code in any text editor, but using an IDE provides you with keyword highlighting to help detect typos, a **Run** button to test code quickly and easily, and other code-specific features that a plain text editor like [Notepad++][13] normally doesn't have.
-
-To start IDLE, click the **Start** (or **Window**) menu and type **python** for matches. You may find a few matches, since Python provides more than one interface, so make sure you launch IDLE.
-
-![IDLE 3 IDE][14]
-
-If you don't see Python in the Start menu, launch the Windows command prompt by typing **cmd** in the Start menu, then type:
-
-
-```
-`C:\Windows\py.exe`
-```
-
-If that doesn't work, try reinstalling Python. Be sure to select **Add Python to PATH** in the install wizard. Refer to the [Python docs][15] for detailed instructions.
-
-#### Ninja-IDE
-
-If you already have some coding experience and IDLE seems too simple for you, try [Ninja-IDE][16]. Ninja-IDE is an excellent Python IDE. It has keyword highlighting to help detect typos, quotation and parenthesis completion to avoid syntax errors, line numbers (helpful when debugging), indentation markers, and a **Run** button to test code quickly and easily.
-
-![Ninja-IDE][17]
-
-To install it, visit the Ninja-IDE website and [download the Windows installer][18]. The process is the same as with Python: start the installer, allow Windows to install a non-Microsoft application, and wait for the installer to finish.
-
-Once Ninja-IDE is installed, double-click the Ninja-IDE icon on your desktop or select it from the Start menu.
-
-### Tell Python what to do
-
-Keywords tell Python what you want it to do. In either IDLE or Ninja-IDE, go to the File menu and create a new file.
-
-Ninja users: Do not create a new project, just a new file.
-
-In your new, empty file, type this into IDLE or Ninja-IDE:
-
-
-```
-`print("Hello world.")`
-```
-
- * If you are using IDLE, go to the Run menu and select the Run Module option.
- * If you are using Ninja, click the Run File button in the left button bar.
-
-
-
-![Running code in Ninja-IDE][19]
-
-Any time you run code, your IDE prompts you to save the file you're working on. Do that before continuing.
-
-The keyword **print** tells Python to print out whatever text you give it in parentheses and quotes.
-
-That's not very exciting, though. At its core, Python has access to only basic keywords like **print** and **help**, basic math functions, and so on.
-
-Use the **import** keyword to load more keywords. Start a new file in IDLE or Ninja and name it **pen.py**.
-
-**Warning**: Do not call your file **turtle.py**, because **turtle.py** is the name of the file that contains the turtle program you are controlling. Naming your file **turtle.py** confuses Python because it thinks you want to import your own file.
-
-Type this code into your file and run it:
-
-
-```
-`import turtle`
-```
-
-[Turtle][20] is a fun module to use. Add this code to your file:
-
-
-```
-turtle.begin_fill()
-turtle.forward(100)
-turtle.left(90)
-turtle.forward(100)
-turtle.left(90)
-turtle.forward(100)
-turtle.left(90)
-turtle.forward(100)
-turtle.end_fill()
-```
-
-See what shapes you can draw with the turtle module.
-
-To clear your turtle drawing area, use the **turtle.clear()** keyword. What do you think the keyword **turtle.color("blue")** does?
-
-Try more complex code:
-
-
-```
-import turtle as t
-import time
-
-t.color("blue")
-t.begin_fill()
-
-counter = 0
-
-while counter < 4:
- t.forward(100)
- t.left(90)
- counter = counter+1
-
-t.end_fill()
-time.sleep(2)
-```
-
-As a challenge, try changing your script to get this result:
-
-![Example Python turtle output][21]
-
-Once you complete that script, you're ready to move on to more exciting modules. A good place to start is this [introductory dice game][22].
-
-### Stay Pythonic
-
-Python is a fun language with modules for practically anything you can think to do with it. As you can see, it's easy to get started with Python, and as long as you're patient with yourself, you may find yourself understanding and writing Python code with the same fluidity as you write your native language. Work through some [Python articles][23] here on Opensource.com, try scripting some small tasks for yourself, and see where Python takes you. To really integrate Python with your daily workflow, you might even try Linux, which is natively scriptable in ways no other operating system is. You might find yourself, given enough time, using the applications you create!
-
-Good luck, and stay Pythonic.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/8/how-install-python-windows
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/sethhttps://opensource.com/users/greg-p
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop.png?itok=pGfEfu2S (Hands programming)
-[2]: https://www.python.org/
-[3]: https://opensource.com/article/19/7/get-modular-python-classes
-[4]: https://github.com/edniemeyer/weta_python_db
-[5]: https://www.python.org/about/success/ilm/
-[6]: https://opensource.com/article/19/7/rgb-cube-python-scribus
-[7]: https://opensource.com/article/19/7/ways-get-started-linux
-[8]: https://opensource.com/article/17/10/python-101
-[9]: https://www.python.org/downloads/
-[10]: https://opensource.com/sites/default/files/uploads/win-python-install.jpg (Downloading Python on Windows)
-[11]: https://opensource.com/sites/default/files/uploads/win-python-path.jpg (Select "Add Python 3 to PATH")
-[12]: https://opensource.com/sites/default/files/uploads/win-python-publisher.jpg (Windows UAC)
-[13]: https://notepad-plus-plus.org/
-[14]: https://opensource.com/sites/default/files/uploads/idle3.png (IDLE 3 IDE)
-[15]: http://docs.python.org/3/using/windows.html
-[16]: http://ninja-ide.org/
-[17]: https://opensource.com/sites/default/files/uploads/win-python-ninja.jpg (Ninja-IDE)
-[18]: http://ninja-ide.org/downloads/
-[19]: https://opensource.com/sites/default/files/uploads/ninja_run.png (Running code in Ninja-IDE)
-[20]: https://opensource.com/life/15/8/python-turtle-graphics
-[21]: https://opensource.com/sites/default/files/uploads/win-python-idle-turtle.jpg (Example Python turtle output)
-[22]: https://opensource.com/article/17/10/python-101#python-101-dice-game
-[23]: https://opensource.com/sitewide-search?search_api_views_fulltext=Python
diff --git a/sources/tech/20190816 Cockpit and the evolution of the Web User Interface.md b/sources/tech/20190816 Cockpit and the evolution of the Web User Interface.md
deleted file mode 100644
index 267a54e8d7..0000000000
--- a/sources/tech/20190816 Cockpit and the evolution of the Web User Interface.md
+++ /dev/null
@@ -1,169 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Cockpit and the evolution of the Web User Interface)
-[#]: via: (https://fedoramagazine.org/cockpit-and-the-evolution-of-the-web-user-interface/)
-[#]: author: (Shaun Assam https://fedoramagazine.org/author/sassam/)
-
-Cockpit and the evolution of the Web User Interface
-======
-
-![][1]
-
-Over 3 years ago the Fedora Magazine published an article entitled [Cockpit: an overview][2]. Since then, the interface has see some eye-catching changes. Today’s Cockpit is cleaner and the larger fonts makes better use of screen real-estate.
-
-This article will go over some of the changes made to the UI. It will also explore some of the general tools available in the web interface to simplify those monotonous sysadmin tasks.
-
-### Cockpit installation
-
-Cockpit can be installed using the **dnf install cockpit** command. This provides a minimal setup providing the basic tools required to use the interface.
-
-Another option is to install the Headless Management group. This will install additional packages used to extend the usability of Cockpit. It includes extensions for NetworkManager, software packages, disk, and SELinux management.
-
-Run the following commands to enable the web service on boot and open the firewall port:
-
-```
-$ sudo systemctl enable --now cockpit.socket
-Created symlink /etc/systemd/system/sockets.target.wants/cockpit.socket -> /usr/lib/systemd/system/cockpit.socket
-
-$ sudo firewall-cmd --permanent --add-service cockpit
-success
-$ sudo firewall-cmd --reload
-success
-```
-
-### Logging into the web interface
-
-To access the web interface, open your favourite browser and enter the server’s domain name or IP in the address bar followed by the service port (9090). Because Cockpit uses HTTPS, the installation will create a self-signed certificate to encrypt passwords and other sensitive data. You can safely accept this certificate, or request a CA certificate from your sysadmin or a trusted source.
-
-Once the certificate is accepted, the new and improved login screen will appear. Long-time users will notice the username and password fields have been moved to the top. In addition, the white background behind the credential fields immediately grabs the user’s attention.
-
-![][3]
-
-A feature added to the login screen since the previous article is logging in with **sudo** privileges — if your account is a member of the wheel group. Check the box beside _Reuse my password for privileged tasks_ to elevate your rights.
-
-Another edition to the login screen is the option to connect to remote servers also running the Cockpit web service. Click _Other Options_ and enter the host name or IP address of the remote machine to manage it from your local browser.
-
-### Home view
-
-Right off the bat we get a basic overview of common system information. This includes the make and model of the machine, the operating system, if the system is up-to-date, and more.
-
-![][4]
-
-Clicking the make/model of the system displays hardware information such as the BIOS/Firmware. It also includes details about the components as seen with **lspci**.
-
-![][5]
-
-Clicking on any of the options to the right will display the details of that device. For example, the _% of CPU cores_ option reveals details on how much is used by the user and the kernel. In addition, the _Memory & Swap_ graph displays how much of the system’s memory is used, how much is cached, and how much of the swap partition active. The _Disk I/O_ and _Network Traffic_ graphs are linked to the Storage and Networking sections of Cockpit. These topics will be revisited in an upcoming article that explores the system tools in detail.
-
-#### Secure Shell Keys and authentication
-
-Because security is a key factor for sysadmins, Cockpit now has the option to view the machine’s MD5 and SHA256 key fingerprints. Clicking the **Show fingerprints** options reveals the server’s ECDSA, ED25519, and RSA fingerprint keys.
-
-![][6]
-
-You can also add your own keys by clicking on your username in the top-right corner and selecting **Authentication**. Click on **Add keys** to validate the machine on other systems. You can also revoke your privileges in the Cockpit web service by clicking on the **X** button to the right.
-
-![][7]
-
-#### Changing the host name and joining a domain
-
-Changing the host name is a one-click solution from the home page. Click the host name currently displayed, and enter the new name in the _Change Host Name_ box. One of the latest features is the option to provide a _Pretty name_.
-
-Another feature added to Cockpit is the ability to connect to a directory server. Click _Join a domain_ and a pop-up will appear requesting the domain address or name, organization unit (optional), and the domain admin’s credentials. The Domain Membership group provides all the packages required to join an LDAP server including FreeIPA, and the popular Active Directory.
-
-To opt-out, click on the domain name followed by _Leave Domain_. A warning will appear explaining the changes that will occur once the system is no longer on the domain. To confirm click the red _Leave Domain_ button.
-
-![][8]
-
-#### Configuring NTP and system date and time
-
-Using the command-line and editing config files definitely takes the cake when it comes to maximum tweaking. However, there are times when something more straightforward would suffice. With Cockpit, you have the option to set the system’s date and time manually or automatically using NTP. Once synchronized, the information icon on the right turns from red to blue. The icon will disappear if you manually set the date and time.
-
-To change the timezone, type the continent and a list of cities will populate beneath.
-
-![][9]
-
-#### Shutting down and restarting
-
-You can easily shutdown and restart the server right from home screen in Cockpit. You can also delay the shutdown/reboot and send a message to warn users.
-
-![][10]
-
-#### Configuring the performance profile
-
-If the _tuned_ and _tuned-utils_ packages are installed, performance profiles can be changed from the main screen. By default it is set to a recommended profile. However, if the purpose of the server requires more performance, we can change the profile from Cockpit to suit those needs.
-
-![][11]
-
-### Terminal web console
-
-A Linux sysadmin’s toolbox would be useless without access to a terminal. This allows admins to fine-tune the server beyond what’s available in Cockpit. With the addition of themes, admins can quickly adjust the text and background colours to suit their preference.
-
-Also, if you type **exit** by mistake, click the _Reset_ button in the top-right corner*.* This will provide a fresh screen with a flashing cursor.
-
-![][12]
-
-### Adding a remote server and the Dashboard overlay
-
-The Headless Management group includes the Dashboard module (**cockpit-dashboard**). This provides an overview the of the CPU, memory, network, and disk performance in a real-time graph. Remote servers can also be added and managed through the same interface.
-
-For example, to add a remote computer in Dashboard, click the **+** button. Enter the name or IP address of the server and select the colour of your choice. This helps to differentiate the stats of the servers in the graph. To switch between servers, click on the host name (as seen in the screen-cast below). To remove a server from the list, click the check-mark icon, then click the red trash icon. The example below demonstrates how Cockpit manages a remote machine named _server02.local.lan_.
-
-![][13]
-
-### Documentation and finding help
-
-As always, the _man_ pages are a great place to find documentation. A simple search in the command-line results with pages pertaining to different aspects of using and configuring the web service.
-
-```
-$ man -k cockpit
-cockpit (1) - Cockpit
-cockpit-bridge (1) - Cockpit Host Bridge
-cockpit-desktop (1) - Cockpit Desktop integration
-cockpit-ws (8) - Cockpit web service
-cockpit.conf (5) - Cockpit configuration file
-```
-
-The Fedora repository also has a package called **cockpit-doc**. The package’s description explains it best:
-
-> The Cockpit Deployment and Developer Guide shows sysadmins how to deploy Cockpit on their machines as well as helps developers who want to embed or extend Cockpit.
-
-For more documentation visit
-
-### Conclusion
-
-This article only touches upon some of the main functions available in Cockpit. Managing storage devices, networking, user account, and software control will be covered in an upcoming article. In addition, optional extensions such as the 389 directory service, and the _cockpit-ostree_ module used to handle packages in Fedora Silverblue.
-
-The options continue to grow as more users adopt Cockpit. The interface is ideal for admins who want a light-weight interface to control their server(s).
-
-What do you think about Cockpit? Share your experience and ideas in the comments below.
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/cockpit-and-the-evolution-of-the-web-user-interface/
-
-作者:[Shaun Assam][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://fedoramagazine.org/author/sassam/
-[b]: https://github.com/lujun9972
-[1]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-816x345.jpg
-[2]: https://fedoramagazine.org/cockpit-overview/
-[3]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-login-screen.png
-[4]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-home-screen.png
-[5]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-system-info.gif
-[6]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-ssh-key-fingerprints.png
-[7]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-authentication.png
-[8]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-hostname-domain.gif
-[9]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-date-time.png
-[10]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-power-options.gif
-[11]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-tuned.gif
-[12]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-terminal.gif
-[13]: https://fedoramagazine.org/wp-content/uploads/2019/08/cockpit-add-remote-servers.gif
diff --git a/sources/tech/20190915 How to Configure SFTP Server with Chroot in Debian 10.md b/sources/tech/20190915 How to Configure SFTP Server with Chroot in Debian 10.md
deleted file mode 100644
index 877845b87a..0000000000
--- a/sources/tech/20190915 How to Configure SFTP Server with Chroot in Debian 10.md
+++ /dev/null
@@ -1,197 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to Configure SFTP Server with Chroot in Debian 10)
-[#]: via: (https://www.linuxtechi.com/configure-sftp-chroot-debian10/)
-[#]: author: (Pradeep Kumar https://www.linuxtechi.com/author/pradeep/)
-
-How to Configure SFTP Server with Chroot in Debian 10
-======
-
-**SFTP** stands for Secure File Transfer Protocol / SSH File Transfer Protocol, it is one of the most common method which is used to transfer files securely over ssh from our local system to remote server and vice-versa. The main advantage of sftp is that we don’t need to install any additional package except ‘**openssh-server**’, in most of the Linux distributions ‘openssh-server’ package is the part of default installation. Other benefit of sftp is that we can allow user to use sftp only not ssh.
-
-[![Configure-sftp-debian10][1]][2]
-
-Recently Debian 10, Code name ‘Buster’ has been released, in this article we will demonstrate how to configure sftp with Chroot ‘Jail’ like environment in Debian 10 System. Here Chroot Jail like environment means that user’s cannot go beyond from their respective home directories or users cannot change directories from their home directories. Following are the lab details:
-
- * OS = Debian 10
- * IP Address = 192.168.56.151
-
-
-
-Let’s jump into SFTP Configuration Steps,
-
-### Step:1) Create a Group for sftp using groupadd command
-
-Open the terminal, create a group with a name “**sftp_users**” using below groupadd command,
-
-```
-root@linuxtechi:~# groupadd sftp_users
-```
-
-### Step:2) Add Users to Group ‘sftp_users’ and set permissions
-
-In case you want to create new user and want to add that user to ‘sftp_users’ group, then run the following command,
-
-**Syntax:** # useradd -m -G sftp_users <user_name>
-
-Let’s suppose user name is ’Jonathan’
-
-```
-root@linuxtechi:~# useradd -m -G sftp_users jonathan
-```
-
-set the password using following chpasswd command,
-
-```
-root@linuxtechi:~# echo "jonathan:" | chpasswd
-```
-
-In case you want to add existing users to ‘sftp_users’ group then run beneath usermod command, let’s suppose already existing user name is ‘chris’
-
-```
-root@linuxtechi:~# usermod -G sftp_users chris
-```
-
-Now set the required permissions on Users,
-
-```
-root@linuxtechi:~# chown root /home/jonathan /home/chris/
-```
-
-Create an upload folder in both the user’s home directory and set the correct ownership,
-
-```
-root@linuxtechi:~# mkdir /home/jonathan/upload
-root@linuxtechi:~# mkdir /home/chris/upload
-root@linuxtechi:~# chown jonathan /home/jonathan/upload
-root@linuxtechi:~# chown chris /home/chris/upload
-```
-
-**Note:** User like Jonathan and Chris can upload files and directories to upload folder from their local systems.
-
-### Step:3) Edit sftp configuration file (/etc/ssh/sshd_config)
-
-As we have already stated that sftp operations are done over the ssh, so it’s configuration file is “**/etc/ssh/sshd_config**“, Before making any changes I would suggest first take the backup and then edit this file and add the following content,
-
-```
-root@linuxtechi:~# cp /etc/ssh/sshd_config /etc/ssh/sshd_config-org
-root@linuxtechi:~# vim /etc/ssh/sshd_config
-………
-#Subsystem sftp /usr/lib/openssh/sftp-server
-Subsystem sftp internal-sftp
-
-Match Group sftp_users
- X11Forwarding no
- AllowTcpForwarding no
- ChrootDirectory %h
- ForceCommand internal-sftp
-…………
-```
-
-Save & exit the file.
-
-To make above changes into the affect, restart ssh service using following systemctl command
-
-```
-root@linuxtechi:~# systemctl restart sshd
-```
-
-In above ‘sshd_config’ file we have commented out the line which starts with “Subsystem” and added new entry “Subsystem sftp internal-sftp” and new lines like,
-
-“**Match Group sftp_users”** –> It means if a user is a part of ‘sftp_users’ group then apply rules which are mentioned below to this entry.
-
-“**ChrootDierctory %h**” –> It means users can only change directories within their respective home directories, they cannot go beyond their home directories, or in other words we can say users are not permitted to change directories, they will get jai like environment within their directories and can’t access any other user’s and system’s directories.
-
-“**ForceCommand internal-sftp**” –> It means users are limited to sftp command only.
-
-### Step:4) Test and Verify sftp
-
-Login to any other Linux system which is on the same network of your sftp server and then try to ssh sftp server via the users that we have mapped in ‘sftp_users’ group.
-
-```
-[root@linuxtechi ~]# ssh root@linuxtechi
-root@linuxtechi's password:
-Write failed: Broken pipe
-[root@linuxtechi ~]# ssh root@linuxtechi
-root@linuxtechi's password:
-Write failed: Broken pipe
-[root@linuxtechi ~]#
-```
-
-Above confirms that users are not allowed to SSH , now try sftp using following commands,
-
-```
-[root@linuxtechi ~]# sftp root@linuxtechi
-root@linuxtechi's password:
-Connected to 192.168.56.151.
-sftp> ls -l
-drwxr-xr-x 2 root 1001 4096 Sep 14 07:52 debian10-pkgs
--rw-r--r-- 1 root 1001 155 Sep 14 07:52 devops-actions.txt
-drwxr-xr-x 2 1001 1002 4096 Sep 14 08:29 upload
-```
-
-Let’s try to download a file using sftp ‘**get**‘ command
-
-```
-sftp> get devops-actions.txt
-Fetching /devops-actions.txt to devops-actions.txt
-/devops-actions.txt 100% 155 0.2KB/s 00:00
-sftp>
-sftp> cd /etc
-Couldn't stat remote file: No such file or directory
-sftp> cd /root
-Couldn't stat remote file: No such file or directory
-sftp>
-```
-
-Above output confirms that we are able to download file from our sftp server to local machine and apart from this we have also tested that users cannot change directories.
-
-Let’s try to upload a file under “**upload**” folder,
-
-```
-sftp> cd upload/
-sftp> put metricbeat-7.3.1-amd64.deb
-Uploading metricbeat-7.3.1-amd64.deb to /upload/metricbeat-7.3.1-amd64.deb
-metricbeat-7.3.1-amd64.deb 100% 38MB 38.4MB/s 00:01
-sftp> ls -l
--rw-r--r-- 1 1001 1002 40275654 Sep 14 09:18 metricbeat-7.3.1-amd64.deb
-sftp>
-```
-
-This confirms that we have successfully uploaded a file from our local system to sftp server.
-
-Now test the SFTP server with winscp tool, enter the sftp server ip address along user’s credentials,
-
-[![Winscp-sftp-debian10][1]][3]
-
-Click on Login and then try to download and upload files
-
-[![Download-file-winscp-debian10-sftp][1]][4]
-
-Now try to upload files in upload folder,
-
-[![Upload-File-using-winscp-Debian10-sftp][1]][5]
-
-Above window confirms that uploading is also working fine, that’s all from this article. If these steps help you to configure SFTP server with chroot environment in Debian 10 then please do share your feedback and comments.
-
---------------------------------------------------------------------------------
-
-via: https://www.linuxtechi.com/configure-sftp-chroot-debian10/
-
-作者:[Pradeep Kumar][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.linuxtechi.com/author/pradeep/
-[b]: https://github.com/lujun9972
-[1]: data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
-[2]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Configure-sftp-debian10.jpg
-[3]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Winscp-sftp-debian10.jpg
-[4]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Download-file-winscp-debian10-sftp.jpg
-[5]: https://www.linuxtechi.com/wp-content/uploads/2019/09/Upload-File-using-winscp-Debian10-sftp.jpg
diff --git a/sources/tech/20191007 20 Linux Command Tips and Tricks That Will Save You A Lot of Time.md b/sources/tech/20191007 20 Linux Command Tips and Tricks That Will Save You A Lot of Time.md
new file mode 100644
index 0000000000..da080e65ea
--- /dev/null
+++ b/sources/tech/20191007 20 Linux Command Tips and Tricks That Will Save You A Lot of Time.md
@@ -0,0 +1,307 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (20 Linux Command Tips and Tricks That Will Save You A Lot of Time)
+[#]: via: (https://itsfoss.com/linux-command-tricks/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+20 Linux Command Tips and Tricks That Will Save You A Lot of Time
+======
+
+_**Brief**: Here are some tiny but useful Linux commands, terminal tricks and shortcuts that will save you a lot of time while working with Linux command line._
+
+Have you ever encountered a moment when you see your colleague using some simple Linux commands for tasks that took you several keystrokes? And when you saw that you were like, “Wow! I didn’t know it could have been done that easily”.
+
+In this article, I’ll show you some pro Linux command tricks that will save you a lot of time and in some cases, from plenty of frustration. Not only your friends or colleagues will ‘wow’ at you, it will also help you increase your productivity as you will need fewer keystrokes and even fewer mouse clicks.
+
+It’s not that these are Linux tips for beginners only. Chances are that even experienced Linux users will find some hidden gems that they were not aware despite using Linux for all these years.
+
+In any case, you [learn Linux][1] by experience, be it your own or someone else’s :)
+
+### Cool Linux terminal tricks to save time and increase productivity
+
+![][2]
+
+You might already know a few of these Linux command tips or perhaps all of it. In either case, you are welcome to share your favorite tricks in the comment section.
+
+Some of these tips also depend on how the shell is configured. Let’s begin!
+
+#### 0\. Using tab for autocompletion
+
+I’ll start with something really obvious and yet really important: tab completion.
+
+When you are starting to type something in Linux terminal, you can hit the tab key and it will suggest all the possible options that start with string you have typed so far.
+
+For example, if you are trying to copy a file named my_best_file_1.txt, you can just type ‘cp m’ and hit tab to see the possible options.
+
+![Use tab for auto-completion][3]
+
+You can use tab in completing commands as well.
+
+[irp posts=”16244″ name=”Difference Between apt and apt-get Explained”]
+
+#### 1\. Switch back to the last working directory
+
+Suppose you end up in a long directory path and then you move to another directory in a totally different path. And then you realize that you have to go back to the previous directory you were in. In this case, all you need to do is to type this command:
+
+```
+cd -
+```
+
+This will put you back in the last working directory. You don’t need to type the long directory path or copy paste it anymore.
+
+![Easily switch between directories][4]
+
+#### 2\. Go back to home directory
+
+This is way too obvious. You can use the command below to move to your home directory from anywhere in Linux command-line:
+
+```
+cd ~
+```
+
+However, you can also use just cd to go back to home directory:
+
+```
+cd
+```
+
+Most modern Linux distributions have the shell pre-configured for this command. Saves you at least two keystrokes here.
+
+![Move to Home as quickly as possible][5]
+
+#### 3\. List the contents of a directory
+
+You must be guessing what’s the trick in the command for listing the contents of a directory. Everyone knows to use the ls -l for this purpose.
+
+And that’s the thing. Most people use ls -l to list the contents of the directory, whereas the same can be done with the following command:
+
+```
+ll
+```
+
+Again, this depends on the Linux distributions and shell configuration, but chances are that you’ll be able to use it in most Linux distributions.
+
+![Using ll instead of ls -l][6]
+
+#### 4\. Running multiple commands in one single command
+
+Suppose, you have to run several commands one after another. Do you wait for the first command to finish running and then execute the next one?
+
+You can use the ‘;’ separator for this purpose. This way, you can run a number of commands in one line. No need to wait for the previous commands to finish their business.
+
+```
+command_1; command_2; command_3
+```
+
+#### 5\. Running multiple commands in one single command only if the previous command was successful
+
+In the previous command, you saw how to run several commands in one single command to save time. But what if you have to make sure that commands don’t fail?
+
+Imagine a situation where you want to build a code and then if the build was successful, run the make?
+
+You can use && separator for this case. && makes sure that the next command will only run when the previous command was successful.
+
+```
+command_1 && command_2
+```
+
+A good example of this command is when you use sudo apt update && sudo apt upgrade to upgrade your system.
+
+#### 6\. Easily search and use the commands that you had used in the past
+
+Imagine a situation where you used a long command couple of minutes/hours ago and you have to use it again. Problem is that you cannot remember the exact command anymore.
+
+Reverse search is your savior here. You can search for the command in the history using a search term.
+
+Just use the keys ctrl+r to initiate reverse search and type some part of the command. It will look up into the history and will show you the commands that matches the search term.
+
+```
+ctrl+r search_term
+```
+
+By default, it will show just one result. To see more results matching your search term, you will have to use ctrl+r again and again. To quit reverse search, just use Ctrl+C.
+
+![Reverse search in command history][7]
+
+Note that in some Bash shells, you can also use Page Up and Down key with your search term and it will autocomplete the command.
+
+#### 7\. Unfreeze your Linux terminal from accidental Ctrl+S
+
+You probably are habitual of using Ctrl+S for saving. But if you use that in Linux terminal, you’ll have a frozen terminal.
+
+Don’t worry, you don’t have to close the terminal, not anymore. Just use Ctrl+Q and you can use the terminal again.
+
+```
+ctrl+Q
+```
+
+#### 8\. Move to beginning or end of line
+
+Suppose you are typing a long command and midway you realize that you had to change something at the beginning. You would use several left arrow keystrokes to move to the start of the line. And similarly for going to the end of the line.
+
+You can use Home and End keys here of course but alternatively, you can use Ctrl+A to go to the beginning of the line and Ctrl+E to go to the end.
+
+![Move to the beginning or end of the line][8]
+
+I find it more convenient than using the home and end keys, especially on my laptop.
+
+#### 9\. Reading a log file in real time
+
+In situations where you need to analyze the logs while the application is running, you can use the tail command with -f option.
+
+```
+tail -f path_to_Log
+```
+
+You can also use the regular grep options to display only those lines that are meaningful to you:
+
+```
+tail -f path_to_log | grep search_term
+```
+
+You can also use the option F here. This will keep the tail running even if the log file is deleted. So if the log file is created again, tail will continue logging.
+
+#### 10\. Reading compressed logs without extracting
+
+Server logs are usually gzip compressed to save disk space. It creates an issue for the developer or sysadmin analyzing the logs. You might have to [scp][9] it to your local and then extract it to access the files because, at times, you don’t have write permission to extract the logs.
+
+Thankfully, z commands save you in such situations. z commands provide alternatives of the regular commands that you use to deal with log files such as less, cat, grep etc.
+
+So you get zless, zcat, zgrep etc and you don’t even have to explicitly extract the compressed files. Please refer to my earlier article about [using z commands to real compressed logs][10] in detail.
+
+This was one of the secret finds that won me a coffee from my colleague.
+
+#### 11\. Use less to read files
+
+To see the contents of a file, cat is not the best option especially if it is a big file. cat command will display the entire file on your screen.
+
+You can use Vi, Vim or other terminal based text editors but if you just want to read a file, less command is a far better choice.
+
+```
+less path_to_file
+```
+
+You can search for terms inside less, move by page, display with line numbers etc.
+
+#### 12\. Reuse the last item from the previous command with !$
+
+Using the argument of the previous command comes handy in many situations.
+
+Say you have to create a directory and then go into the newly created directory. There you can use the !$ options.
+
+![Use !$ to use the argument of last command][11]
+
+A better way to do the same is to use alt+. . You can use . a number times to shuffle between the options of the last commands.
+
+#### 13\. Reuse the previous command in present command with !!
+
+You can call the entire previous command with !!. This comes particularly useful when you have to run a command and realize that it needs root privileges.
+
+A quick sudo !! saves plenty of keystrokes here.
+
+![Use !! to use last command as an argument][12]
+
+#### 14\. Using alias to fix typos
+
+You probably already know what is an alias command in Linux. What you can do is, to use them to fix typos.
+
+For example, you might often mistype grep as gerp. If you put an alias in your bashrc in this fashion:
+
+```
+alias gerp=grep
+```
+
+This way you won’t have to retype the command again.
+
+#### 15\. Copy Paste in Linux terminal
+
+This one is slightly ambiguous because it depends on Linux distributions and terminal applications. But in general, you should be able to copy paste commands with these shortcuts:
+
+ * Select the text for copying and right click for paste (works in Putty and other Windows SSH clients)
+ * Select the text for copying and middle click (scroll button on the mouse) for paste
+ * Ctrl+Shift+C for copy and Ctrl+Shift+V for paste
+
+
+
+#### 16\. Kill a running command/process
+
+This one is perhaps way too obvious. If there is a command running in the foreground and you want to exit it, you can press Ctrl+C to stop that running command.
+
+#### 17\. Using yes command for commands or scripts that need interactive response
+
+If there are some commands or scripts that need user interaction and you know that you have to enter Y each time it requires an input, you can use Yes command.
+
+Just use it in the below fashion:
+
+```
+yes | command_or_script
+```
+
+#### 18\. Empty a file without deleting it
+
+If you just want to empty the contents of a text file without deleting the file itself, you can use a command similar to this:
+
+```
+> filename
+```
+
+#### 19\. Find if there are files containing a particular text
+
+There are multiple ways to search and find in Linux command line. But in the case when you just want to see if there are files that contain a particular text, you can use this command:
+
+```
+grep -Pri Search_Term path_to_directory
+```
+
+I highly advise mastering find command though.
+
+#### 20\. Using help with any command
+
+I’ll conclude this article with one more obvious and yet very important ‘trick’, using help with a command or a command line tool.
+
+Almost all command and command line tool come with a help page that shows how to use the command. Often using help will tell you the basic usage of the tool/command.
+
+Just use it in this fashion:
+
+```
+command_tool --help
+```
+
+#### Your favorite Linux command line tricks?
+
+I have deliberately not included commands like [fuck][13] because those are not standard commands that you’ll find everywhere. The tricks discussed here should be usable almost in all Linux distributions and shell without the need of installing a new tool.
+
+I would also suggest [using alias command in Linux][14] to replace complicated commands with a simple. Saves a lot of time.
+
+I know that there are more Linux command tricks to save time in the terminal. Why not share some of your experiences with Linux and do share your best trick with rest of the community here? The comment section below is at your disposal.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/linux-command-tricks/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://itsfoss.com/learn-linux-for-free/
+[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-Tricks-Save-Time.jpeg?resize=800%2C450&ssl=1
+[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-8.png?ssl=1
+[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-1.png?ssl=1
+[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-2.png?ssl=1
+[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-3.png?ssl=1
+[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-4.png?ssl=1
+[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-5.png?ssl=1
+[9]: http://www.hypexr.org/linux_scp_help.php
+[10]: https://itsfoss.com/read-compressed-log-files-linux/
+[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-6.png?ssl=1
+[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2017/08/Linux-Command-tricks-to-save-time-7.png?ssl=1
+[13]: https://github.com/nvbn/thefuck
+[14]: https://linuxhandbook.com/linux-alias-command/
diff --git a/sources/tech/20191014 How to make a Halloween lantern with Inkscape.md b/sources/tech/20191014 How to make a Halloween lantern with Inkscape.md
deleted file mode 100644
index 0f15fae6e6..0000000000
--- a/sources/tech/20191014 How to make a Halloween lantern with Inkscape.md
+++ /dev/null
@@ -1,188 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to make a Halloween lantern with Inkscape)
-[#]: via: (https://opensource.com/article/19/10/how-make-halloween-lantern-inkscape)
-[#]: author: (Jess Weichler https://opensource.com/users/cyanide-cupcake)
-
-How to make a Halloween lantern with Inkscape
-======
-Use open source tools to make a spooky and fun decoration for your
-favorite Halloween haunt.
-![Halloween - backlit bat flying][1]
-
-The spooky season is almost here! This year, decorate your haunt with a unique Halloween lantern made with open source!
-
-Typically, a portion of a lantern's structure is opaque to block the light from within. What makes a lantern a lantern are the parts that are missing: windows cut from the structure so that light can escape. While it's impractical for lighting, a lantern with windows in spooky shapes and lurking silhouettes can be atmospheric and a lot of fun to create.
-
-This article demonstrates how to create your own lantern using [Inkscape][2]. If you don't have Inkscape, you can install it from your software repository on Linux or download it from the [Inkscape website][3] on MacOS and Windows.
-
-### Supplies
-
- * Template ([A4][4] or [Letter][5] size)
- * Cardstock (black is traditional)
- * Tracing paper (optional)
- * Craft knife, ruler, and cutting mat (a craft cutting machine/laser cutter can be used instead)
- * Craft glue
- * LED tea-light "candle"
-_Safety note:_ Only use battery-operated candles for this project.
-
-
-
-### Understanding the template
-
-To begin, download the correct template for your region (A4 or Letter) from the links above and open it in Inkscape.
-
-* * *
-
-* * *
-
-* * *
-
-**![Lantern template screen][6]**
-
-The gray-and-white checkerboard background is see-through (in technical terms, it's an _alpha channel_.)
-
-The black base forms the lantern. Right now, there are no windows for light to shine through; the lantern is a solid black base. You will use the **Union** and **Difference** options in Inkscape to design the windows digitally.
-
-The dotted blue lines represent fold scorelines. The solid orange lines represent guides. Windows for light should not be placed outside the orange boxes.
-
-To the left of the template are a few pre-made objects you can use in your design.
-
-### To create a window or shape
-
- 1. Create an object that looks like the window style you want. Objects can be created using any of the shape tools in Inkscape's left toolbar. Alternately, you can download Creative Commons- or Public Domain-licensed clipart and import the PNG file into your project.
- 2. When you are happy with the shape of the object, turn it into a **Path** (rather than a **Shape**, which Inkscape sees as two different kinds of objects) by selecting **Object > Object to Path** in the top menu.
-
-
-
-![Object to path menu][7]
-
- 3. Place the object on top of the base shape.
- 4. Select both the object and the black base by clicking one, pressing and holding the Shift key, then selecting the other.
- 5. Select **Object > Difference** from the top menu to remove the shape of the object from the base. This creates what will become a window in your lantern.
-
-
-
-![Object > Difference menu][8]
-
-### To add an object to a window
-
-After making a window, you can add objects to it to create a scene.
-
-**Tips:**
-
- * All objects, including text, must be connected to the base of the lantern. If not, they will fall out after cutting and leave a blank space.
- * Avoid small, intricate details. These are difficult to cut, even when using a machine like a laser cutter or a craft plotter.
-
-
- 1. Create or import an object.
- 2. Place the object inside the window so that it is touching at least two sides of the base.
- 3. With the object selected, choose **Object > Object to Path** from the top menu.
-
-
-
-![Object to path menu][9]
-
- 4. Select the object and the black base by clicking on each one while holding the Shift key).
- 5. Select **Object > Union** to join the object and the base.
-
-
-
-### Add text
-
-Text can either be cut out from the base to create a window (as I did with the stars) or added to a window (which blocks the light from within the lantern). If you're creating a window, only follow steps 1 and 2 below, then use **Difference** to remove the text from the base layer.
-
- 1. Select the Text tool from the left sidebar to create text. Thick, bold fonts work best.
-
-![Text tool][10]
-
- 2. Select your text, then choose **Path > Object to Path** from the top menu. This converts the text object to a path. Note that this step means you can no longer edit the text, so perform this step _only after_ you're sure you have the word or words you want.
-
- 3. After you have converted the text, you can press **F2** on your keyboard to activate the **Node Editor** tool to clearly show the nodes of the text when it is selected with this tool.
-
-
-
-
-![Text selected with Node editor][11]
-
- 4. Ungroup the text.
- 5. Adjust each letter so that it slightly overlaps its neighboring letter or the base.
-
-
-
-![Overlapping the text][12]
-
- 6. To connect all of the letters to one another and to the base, re-select all the text and the base, then select **Path > Union**.
-
-![Connecting letters and base with Path > Union][13]
-
-
-
-
-### Prepare for printing
-
-The following instructions are for hand-cutting your lantern. If you're using a laser cutter or craft plotter, follow the techniques required by your hardware to prepare your files.
-
- 1. In the **Layer** panel, click the **Eye** icon beside the **Safety** layer to hide the safety lines. If you don't see the Layer panel, reveal it by selecting **Layer > Layers** from the top menu.
- 2. Select the black base. In the **Fill and Stroke** panel, set the fill to **X** (meaning _no fill_) and the **Stroke** to solid black (that's #000000ff to fans of hexes).
-
-
-
-![Setting fill and stroke][14]
-
- 3. Print your pattern with **File > Print**.
-
- 4. Using a craft knife and ruler, carefully cut around each black line. Lightly score the dotted blue lines, then fold.
-
-![Cutting out the lantern][15]
-
- 5. To finish off the windows, cut tracing paper to the size of each window and glue it to the inside of the lantern.
-
-![Adding tracing paper][16]
-
- 6. Glue the lantern together at the tabs.
-
- 7. Turn on a battery-powered LED candle and place it inside your lantern.
-
-
-
-
-![Completed lantern][17]
-
-Now your lantern is complete and ready to light up your haunt. Happy Halloween!
-
-How to make Halloween bottle labels with Inkscape, GIMP, and items around the house.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/10/how-make-halloween-lantern-inkscape
-
-作者:[Jess Weichler][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/cyanide-cupcake
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/halloween_bag_bat_diy.jpg?itok=24M0lX25 (Halloween - backlit bat flying)
-[2]: https://opensource.com/article/18/1/inkscape-absolute-beginners
-[3]: http://inkscape.org
-[4]: https://www.dropbox.com/s/75qzjilg5ak2oj1/papercraft_lantern_A4_template.svg?dl=0
-[5]: https://www.dropbox.com/s/8fswdge49jwx91n/papercraft_lantern_letter_template%20.svg?dl=0
-[6]: https://opensource.com/sites/default/files/uploads/lanterntemplate_screen.png (Lantern template screen)
-[7]: https://opensource.com/sites/default/files/uploads/lantern1.png (Object to path menu)
-[8]: https://opensource.com/sites/default/files/uploads/lantern2.png (Object > Difference menu)
-[9]: https://opensource.com/sites/default/files/uploads/lantern3.png (Object to path menu)
-[10]: https://opensource.com/sites/default/files/uploads/lantern4.png (Text tool)
-[11]: https://opensource.com/sites/default/files/uploads/lantern5.png (Text selected with Node editor)
-[12]: https://opensource.com/sites/default/files/uploads/lantern6.png (Overlapping the text)
-[13]: https://opensource.com/sites/default/files/uploads/lantern7.png (Connecting letters and base with Path > Union)
-[14]: https://opensource.com/sites/default/files/uploads/lantern8.png (Setting fill and stroke)
-[15]: https://opensource.com/sites/default/files/uploads/lantern9.jpg (Cutting out the lantern)
-[16]: https://opensource.com/sites/default/files/uploads/lantern10.jpg (Adding tracing paper)
-[17]: https://opensource.com/sites/default/files/uploads/lantern11.jpg (Completed lantern)
diff --git a/sources/tech/20191031 4 Python tools for getting started with astronomy.md b/sources/tech/20191031 4 Python tools for getting started with astronomy.md
deleted file mode 100644
index 79e64651b3..0000000000
--- a/sources/tech/20191031 4 Python tools for getting started with astronomy.md
+++ /dev/null
@@ -1,69 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (4 Python tools for getting started with astronomy)
-[#]: via: (https://opensource.com/article/19/10/python-astronomy-open-data)
-[#]: author: (Gina Helfrich, Ph.D. https://opensource.com/users/ginahelfrich)
-
-4 Python tools for getting started with astronomy
-======
-Explore the universe with NumPy, SciPy, Scikit-Image, and Astropy.
-![Person looking up at the stars][1]
-
-NumFOCUS is a nonprofit charity that supports amazing open source toolkits for scientific computing and data science. As part of the effort to connect Opensource.com readers with the NumFOCUS community, we are republishing some of the most popular articles from [our blog][2]. To learn more about our mission and programs, please visit [numfocus.org][3]. If you're interested in participating in the NumFOCUS community in person, check out a local [PyData event][4] happening near you.
-
-* * *
-
-### Astronomy with Python
-
-Python is a great language for science, and specifically for astronomy. The various packages such as [NumPy][5], [SciPy][6], [Scikit-Image][7] and [Astropy][8] (to name but a few) are all a great testament to the suitability of Python for astronomy, and there are plenty of use cases. [NumPy, Astropy, and SciPy are NumFOCUS fiscally sponsored projects; Scikit-Image is an affiliated project.] Since leaving the field of astronomical research behind more than 10 years ago to start a second career as software developer, I have always been interested in the evolution of these packages. Many of my former colleagues in astronomy used most if not all of these packages for their research work. I have since worked on implementing professional astronomy software packages for instruments for the Very Large Telescope (VLT) in Chile, for example.
-
-It struck me recently that the Python packages have evolved to such an extent that it is now fairly easy for anyone to build [data reduction][9] scripts that can provide high-quality data products. Astronomical data is ubiquitous, and what is more, it is almost all publicly available—you just need to look for it.
-
-For example, ESO, which runs the VLT, offers the data for download on their site. Head over to [www.eso.org/UserPortal][10] and create a user name for their portal. If you look for data from the instrument SPHERE you can download a full dataset for any of the nearby stars that have exoplanet or proto-stellar discs. It is a fantastic and exciting project for any Pythonista to reduce that data and make the planets or discs that are deeply hidden in the noise visible.
-
-I encourage you to download the ESO or any other astronomy imaging dataset and go on that adventure. Here are a few tips:
-
- 1. Start off with a good dataset. Have a look at papers about nearby stars with discs or exoplanets and then search, for example: . Notice that some data on this site is marked as red and some as green. The red data is not publicly available yet — it will say under “release date” when it will be available.
- 2. Read something about the instrument you are using the data from. Try and get a basic understanding of how the data is obtained and what the standard data reduction should look like. All telescopes and instruments have publicly available documents about this.
- 3. You will need to consider the standard problems with astronomical data and correct for them:
- 1. Data comes in FITS files. You will need **pyfits** or **astropy** (which contains pyfits) to read them into **NumPy** arrays. In some cases the data comes in a cube and you should to use **numpy.median **along the z-axis to turn them into 2-D arrays. For some SPHERE data you get two copies of the same piece of sky on the same image (each has a different filter) which you will need to extract using **indexing and slicing.**
- 2. The master dark and bad pixel map. All instruments will have specific images taken as “dark frames” that contain images with the shutter closed (no light at all). Use these to extract a mask of bad pixels using **NumPy masked arrays** for this. This mask of bad pixels will be very important — you need to keep track of it as you process the data to get a clean combined image in the end. In some cases it also helps to subtract this master dark from all scientific raw images.
- 3. Instruments will typically also have a master flat frame. This is an image or series of images taken with a flat uniform light source. You will need to divide all scientific raw images by this (again, using numpy masked array makes this an easy division operation).
- 4. For planet imaging, the fundamental technique to make planets visible against a bright star rely on using a coronagraph and a technique known as angular differential imaging. To that end, you need to identify the optical centre on the images. This is one of the most tricky steps and requires finding some artificial helper images embedded in the images using **skimage.feature.blob_dog**.
- 4. Be patient. It can take a while to understand the data format and how to handle it. Making some plots and histograms of the pixel data can help you to understand it. It is well worth it to be persistent! You will learn a lot about imaging data and processing.
-
-
-
-Using the tools offered by NumPy, SciPy, Astropy, scikit-image and more in combination, with some patience and persistence, it is possible to analyse the vast amount of available astronomical data to produce some stunning results. And who knows, maybe you will be the first one to find a planet that was previously overlooked! Good luck!
-
-_This article was originally published on the NumFOCUS blog and is republished with permission. It is based on [a talk][11] by [Ole Moeller-Nilsson][12], CTO at Pivigo. If you want to support NumFOCUS, you can donate [here][13] or find your local [PyData event][4] happening around the world._
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/10/python-astronomy-open-data
-
-作者:[Gina Helfrich, Ph.D.][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/ginahelfrich
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/space_stars_cosmos_person.jpg?itok=XUtz_LyY (Person looking up at the stars)
-[2]: https://numfocus.org/blog
-[3]: https://numfocus.org
-[4]: https://pydata.org/
-[5]: http://numpy.scipy.org/
-[6]: http://www.scipy.org/
-[7]: http://scikit-image.org/
-[8]: http://www.astropy.org/
-[9]: https://en.wikipedia.org/wiki/Data_reduction
-[10]: http://www.eso.org/UserPortal
-[11]: https://www.slideshare.net/OleMoellerNilsson/pydata-lonon-finding-planets-with-python
-[12]: https://twitter.com/olly_mn
-[13]: https://numfocus.org/donate
diff --git a/sources/tech/20191125 My top 5 Ansible modules.md b/sources/tech/20191125 My top 5 Ansible modules.md
deleted file mode 100644
index 9a76342854..0000000000
--- a/sources/tech/20191125 My top 5 Ansible modules.md
+++ /dev/null
@@ -1,74 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (My top 5 Ansible modules)
-[#]: via: (https://opensource.com/article/19/11/ansible-modules)
-[#]: author: (Mark Phillips https://opensource.com/users/markp)
-
-My top 5 Ansible modules
-======
-Learn how to achieve almost anything with these Ansible modules.
-![][1]
-
-When I was growing up, my grandfather had a shed in his garden. He would spend hours in there, making and fixing things. This was way before we had the internet, so I spent a lot of time studying him creating things in that shed. Although the shed was full of many tools, from drills to lathes to electrical gubbins and lots of things I doubt I could identify even today, he made use of only a tiny subset of what he had at hand. Yet there never seemed to be limits to what he could achieve.
-
-I tell you that story because I feel like my career has been spent in a metaphorical shed. Computers are so many tools, all in a small (virtual?) space. And there are tool sheds within tool sheds—my favourite being Ansible. The recent 2.9 release ships with 3,681 modules! **3,681!** When I first started using Ansible in the summer of 2013, version 1.2.1 had just 113 modules, yet, as [I wrote at the time][2], I could still achieve anything I imagined.
-
-Modules are the backbone of Ansible, the gears to make light of heavy lifting. They're designed to do one job well, thus realising [the Unix philosophy][3]. This is how we've come to bundle so many of them; Ansible as the conductor of the orchestra now has a lot of instruments at its command.
-
-Reviewing a Git repository of my Ansible plays and roles over the years reveals that I have used just 35 modules. This small subset was used to build large infrastructures. I wonder what could be achieved with an even smaller subset, though? As I reviewed those 35, I pondered if I could achieve the same results with only five modules at my disposal. So here are my five favourite modules, in a rather tenuous order of precedence.
-
-### 5. [authorized_key][4]
-
-Secure shell (SSH) is at the heart of Ansible, at least for almost everything besides Windows. Key (no pun intended) to using SSH efficiently with Ansible is… [keys][5]! Slight aside—there are a lot of very cool things you can do for security with SSH keys. It's worth perusing the **authorized_keys** section of the [sshd manual page][6]. Managing SSH keys can become laborious if you're getting into the realms of granular user access, and although we could do it with either of my next two favourites, I prefer to use the module because it [enables easy management through variables][7].
-
-### 4. [file][8]
-
-Besides the obvious function of placing a file somewhere, the **file** module also sets ownership and permissions. I'd say that's a lot of _bang for your buck_ with one module. I'd proffer a substantial portion of security relates to setting permissions too, so the **file** module plays nicely with **authorized_keys**.
-
-### 3. [template][9]
-
-There are so many ways to manipulate the contents of files, and I see lots of folk use **[lineinfile][10]**. I've used it myself for small tasks. However, the **template** module is so much clearer because you maintain the entire file for context. My preference is to write Ansible content in such a way that anyone can understand it _easily_—which to me means not making it hard to understand what is happening. Use of **template** means being able to see the entire file you're putting into place, complete with the variables you are using to change pieces.
-
-### 2. [uri][11]
-
-Many modules in the current distribution leverage Ansible as an orchestrator. They talk to another service, rather than doing something specific like putting a file into place. Usually, that talking is over HTTP too. In the days before many of these modules existed, you _could_ program an API directly using the **uri** module. It's a powerful access tool, enabling you to do a lot. I wouldn't be without it in my fictitious Ansible shed.
-
-### 1. [shell][12]
-
-The joker card in our pack. The Swiss Army Knife. If you're absolutely stuck for how to control something else, use **shell**. Some will argue we're now talking about making Ansible a Bash script—but, I would say it's still better because with the use of the **name** parameter in your plays and roles, you document every step. To me, that's as big a bonus as anything. Back in the days when I was still consulting, I once helped a database administrator (DBA) migrate to Ansible. The DBA wasn't one for change and pushed back at changing working methods. So, to ease into the Ansible way, we called some existing DB management scripts from Ansible using the **shell** module. With an informative **name** statement to accompany the task.
-
-You can achieve a lot with these five modules. Yes, modules designed to do a specific task will make your life even easier. But with a smidgen of engineering simplicity, you can achieve a lot with very little. Ansible developer Brian Coca is a master at it, and [his tips and tricks talk][13] is always worth a watch.
-
-* * *
-
-What do you think about my top five? What five modules would you pick and why, if you were so limited? Let me know in the comments below!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/11/ansible-modules
-
-作者:[Mark Phillips][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/markp
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/mandelbrot_set.png?itok=bmPc0np5
-[2]: http://probably.co.uk/post/puppet-vs-chef-vs-ansible/
-[3]: https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well
-[4]: https://docs.ansible.com/ansible/latest/modules/authorized_key_module.html
-[5]: https://linux.die.net/man/1/ssh-keygen
-[6]: https://linux.die.net/man/8/sshd
-[7]: https://github.com/phips/ansible-demos/blob/3bf59df1eb2390b31b5c42333197e2fbb7fec93f/roles/ansible-users/tasks/main.yml#L35
-[8]: https://docs.ansible.com/ansible/latest/modules/file_module.html
-[9]: https://docs.ansible.com/ansible/latest/modules/template_module.html
-[10]: https://docs.ansible.com/ansible/latest/modules/lineinfile_module.html
-[11]: https://docs.ansible.com/ansible/latest/modules/uri_module.html
-[12]: https://docs.ansible.com/ansible/latest/modules/shell_module.html
-[13]: https://www.ansible.com/ansible-tips-and-tricks
diff --git a/sources/tech/20191209 Use the Fluxbox Linux desktop as your window manager.md b/sources/tech/20191209 Use the Fluxbox Linux desktop as your window manager.md
deleted file mode 100644
index 8c7ddcb1e5..0000000000
--- a/sources/tech/20191209 Use the Fluxbox Linux desktop as your window manager.md
+++ /dev/null
@@ -1,164 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Use the Fluxbox Linux desktop as your window manager)
-[#]: via: (https://opensource.com/article/19/12/fluxbox-linux-desktop)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-Use the Fluxbox Linux desktop as your window manager
-======
-This article is part of a special series of 24 days of Linux desktops.
-Fluxbox is very light on system resources, yet it has vital Linux
-desktop features to make your user experience easy, blazingly efficient,
-and unduly fast.
-![Text editor on a browser, in blue][1]
-
-The concept of a desktop may differ from one computer user to another. Many people see the desktop as a home base, or a comfy living room, or even a literal desktop where they place frequently used notepads, their best pens and pencils, and their favorite coffee mug. KDE, GNOME, Pantheon (and so on) provide that kind of comfort on Linux.
-
-But for some users, the desktop is just empty monitor space, a side effect of not yet having any free-floating application windows projected directly onto their retina. For these users, the desktop is a void over which they can run applications—whether big office and graphic suites, or a simple terminal window, or docked applets—to manage services. This model of operating a [POSIX][2] computer has a long history, and one branch of that family tree is the *box window managers: Blackbox, Fluxbox, and Openbox.
-
-[Fluxbox][3] is a window manager for X11 systems that's based on an older project called Blackbox. Blackbox development was waning when I discovered Linux, so I fell into Fluxbox, and I've used it ever since on at least one of my active systems. It is written in C++ and is licensed under the MIT open source license.
-
-### Installing Fluxbox
-
-You are likely to find Fluxbox included in the software repository of your Linux distribution, but you can also find it on [Fluxbox.org][4]. If you're already running a different desktop, it's safe to install Fluxbox on the same system because Fluxbox doesn't predetermine any configuration or accompanying applications.
-
-After installing Fluxbox, log out of your current desktop session so you can log into your new one. By default, your session manager (KDM, GDM, LightDM, or XDM, depending on your setup) will continue to log you into your previous desktop, so you must override that before logging in.
-
-To override the desktop with GDM:
-
-![Select your desktop session in GDM][5]
-
-Or with KDM:
-
-![Select your desktop session with KDM][6]
-
-### Configuring the Fluxbox desktop
-
-When you first log in, the screen is mostly empty because all Fluxbox provides are panels (for a taskbar, system tray, and so on) and window decoration for application windows.
-
-![Default Fluxbox configuration on CentOS 7][7]
-
-If your distribution delivers a plain Fluxbox desktop, you can set a background for your desktop using the **feh** command (you may need to install it from your distribution's repository). This command has a few options for setting the background, including **\--bg-fill** to fill the screen with your wallpaper of choice, **\--bg-scale** to scale it to fit, and so on.
-
-
-```
-`$ feh --bg-fill ~/photo/oamaru/leaf-spiral.jpg`
-```
-
-![Fluxbox with a theme applied][8]
-
-By default, Fluxbox auto-generates a menu, available with a right-click anywhere on the desktop, that gives you access to applications. Depending on your distribution, this menu may be very minimal, or it may list all the launchers in your **/usr/share/applications** directory.
-
-Fluxbox configuration is set in text files, and those text files are contained in the **$HOME/.fluxbox** directory. You can:
-
- * Set keyboard shortcuts in **keys**
- * Set startup services and applications in **startup**
- * Set desktop preferences (such as the number of workspaces, locations of panels, and so on) in **init**
- * Set menu items in **menu**
-
-
-
-The text configuration files are easy to reverse-engineer, but you also can (and should) read the Fluxbox [documentation][9].
-
-For example, this is my typical menu (or at least the basic structure of it):
-
-
-```
-# to use your own menu, copy this to ~/.fluxbox/menu, then edit
-# ~/.fluxbox/init and change the session.menuFile path to ~/.fluxbox/menu
-
-[begin] (fluxkbox)
- [submenu] (apps) {}
- [submenu] (txt) {}
- [exec] (Emacs 23 (text\\)) { x-terminal-emulator -T "Emacs (text)" -e /usr/bin/emacs -nw} <>
- [exec] (Emacs (X11\\)) {/usr/bin/emacs} <>
- [exec] (LibreOffice) {/usr/bin/libreoffice}
- [end]
- [submenu] (code) {}
- [exec] (qtCreator) {/usr/bin/qtcreator}
- [exec] (eclipse) {/usr/bin/eclipse}
- [end]
- [submenu] (graphics) {}
- [exec] (ksnapshot) {/usr/bin/ksnapshot}
- [exec] (gimp) {/usr/bin/gimp}
- [exec] (blender) {/usr/bin/blender}
- [end]
- [submenu] (files) {}
- [exec] (dolphin) {/usr/bin/dolphin}
- [exec] (konqueror) { /usr/bin/kfmclient openURL $HOME }
- [end]
- [submenu] (network) {}
- [exec] (firefox) {/usr/bin/firefox}
- [exec] (konqueror) {/usr/bin/konqueror}
- [end]
- [end]
-## change window manager or work env
-[submenu] (environments) {}
- [restart] (flux) {/usr/bin/startfluxbox}
- [restart] (ratpoison) {/usr/bin/ratpoison}
- [exec] (openIndiana) {/home/kenlon/qemu/startSolaris.sh}
-[end]
-
-[config] (config)
- [submenu] (styles) {}
- [stylesdir] (/usr/share/fluxbox/styles)
- [stylesdir] (~/.fluxbox/styles)
- [end]
-[workspaces] (workspaces)
-[reconfig] (reconfigure)
-[restart] (restart)
-[exit] (exeunt)
-[end]
-```
-
-The menu also provides a few preference settings, such as the ability to pick a theme and restart or log out from your Fluxbox session.
-
-I launch most applications using keyboard shortcuts, which are entered into the **keys** configuration file. Here are some examples (the **Mod4** key is the Super key, which I use to designate global shortcuts):
-
-
-```
-# open apps
-Mod4 t :Exec konsole
-Mod4 k :Exec konqueror
-Mod4 z :Exec fbrun
-Mod4 e :Exec emacs
-Mod4 f :Exec firefox
-Mod4 x :Exec urxvt
-Mod4 d :Exec dolphin
-Mod4 q :Exec xscreensaver-command -activate
-Mod4 3 :Exec ksnapshot
-```
-
-Between these shortcuts and an open terminal, I have little use for a mouse during most of my workday, so there's no wasted time switching from one controller to another. And because Fluxbox stays well out of the way, there's little distraction.
-
-### Why you should use Fluxbox
-
-Fluxbox is very light on system resources, yet it has vital features to make your user experience easy, blazingly efficient, and unduly fast. It's simple to customize, and it allows you to define your own workflow. You don't have to use Fluxbox's panels, because there are other excellent panels out there. You can even middle-click and drag two separate application windows into one another so that they become one window, each in its own tab.
-
-The possibilities are endless, so try the steady simplicity that is Fluxbox on your Linux box today!
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/fluxbox-linux-desktop
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_blue_text_editor_web.png?itok=lcf-m6N7 (Text editor on a browser, in blue)
-[2]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
-[3]: http://fluxbox.org
-[4]: http://fluxbox.org/download/
-[5]: https://opensource.com/sites/default/files/advent-gdm_0.jpg (Select your desktop session in GDM)
-[6]: https://opensource.com/sites/default/files/advent-kdm.jpg (Select your desktop session with KDM)
-[7]: https://opensource.com/sites/default/files/advent-fluxbox-default.jpg (Default Fluxbox configuration on CentOS 7)
-[8]: https://opensource.com/sites/default/files/advent-fluxbox-green.jpg (Fluxbox with a theme applied)
-[9]: http://fluxbox.org/features/
diff --git a/sources/tech/20191216 Relive Linux history with the ROX desktop.md b/sources/tech/20191216 Relive Linux history with the ROX desktop.md
deleted file mode 100644
index 215006514f..0000000000
--- a/sources/tech/20191216 Relive Linux history with the ROX desktop.md
+++ /dev/null
@@ -1,104 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Relive Linux history with the ROX desktop)
-[#]: via: (https://opensource.com/article/19/12/linux-rox-desktop)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-Relive Linux history with the ROX desktop
-======
-This article is part of a special series of 24 days of Linux desktops.
-If you're looking for a fun trip back in time, the ROX desktop is well
-worth a go.
-![Person typing on a 1980's computer][1]
-
-The [ROX][2] desktop is no longer being actively developed, but its legacy resounds today, and even when it was active, it was a unique take on what a Linux desktop could be. While other desktops felt roughly similar to old Unix or Windows interfaces, ROX belongs solidly in the BeOS, AmigaOS, and [RISC OS][3] desktop camps.
-
-It focuses on drag-and-drop actions (which makes its accessibility non-optimal for some users), point-and-click actions, pop-up contextual menus, and a unique system of app directories for running local applications with no installation required.
-
-### Installing ROX
-
-Today, ROX is mostly abandoned and left in fragments that the user is left to sort out. Luckily, the puzzle is relatively easy to solve, but don't get confused when you find bits and pieces of the ROX desktop in your distribution's repository—but not _every_ bit of the ROX desktop. The popular parts of ROX—the file manager ([ROX-Filer][4]) and the terminal ([ROXTerm][5])—seem to have endured in most of the popular distribution repositories, and you can install (and use) them as standalone applications. However, to run the ROX desktop, you must also install ROX-Session and the libraries it depends on.
-
-I installed ROX on Slackware 14.2, but it should work on any Linux or BSD system.
-
-First, you must install [ROX-lib2][6] from its repository. True to its philosophy of minimal installs, all you have to do to install ROX-lib2 is download the tarball, [unarchive it][7], and move the **ROX-Lib** directory to **/usr/local/lib**.
-
-Next, you have to install [ROX-Session][8]. This probably needs to be compiled from source code, as it's not likely to be in your software repository. The compile process requires build tools, which ship by default on Slackware but are often omitted in other distributions to save space on the initial download. The names of the packages you must install to build from source code vary depending on your distro, so refer to the documentation for specifics. For example, on Debian-based distributions, you can learn about build requirements in [Debian's wiki][9], and on Fedora-based distributions, refer to [Fedora's docs][10]. Once you have the build tools installed, execute the custom ROX-Session build script:
-
-
-```
-`$ ./AppRun`
-```
-
-This manages its own build and installation and prompts you for root permissions to add itself as an option on your login screen.
-
-If you have not installed ROX-Filer from your software repository, do that before continuing.
-
-Together, these components create a complete ROX desktop. To log into your new desktop, log out of your current desktop session. By default, your session manager (KDM, GDM, LightDM, or XDM, depending on your setup) will continue to log you into your previous desktop, so you must override that before logging in.
-
-With SDDM:
-
-![][11]
-
-With GDM:
-
-![][12]
-
-### ROX desktop features
-
-The ROX desktop is simple by default, with a single panel at the bottom of the screen and a shortcut icon to your home directory on the desktop. The panel contains shortcuts to common locations. That's all there is to the ROX desktop, at least as it's configured out of the box. If you want a clock or a calendar or a system tray, you need to find applications that provide them.
-
-![Default ROX desktop][13]
-
-There is no taskbar, as such, but when you minimize a window, it becomes a temporary icon on your desktop. You can click the icon to bring its window back to its former size and placement.
-
-The panel can be modified some, as well. You can place different shortcuts into it and even create your own applets.
-
-There's no application menu, either, nor are there shortcuts to applications in a contextual menu. Instead, you can navigate manually to **/usr/share/applications**, or you can add your application directory or directories to the ROX panel.
-
-![ROX desktop][14]
-
-The ROX desktop's workflow concentrates on being mouse-driven, reminiscent of Mac OS 7.5 and 8. With ROX-filer, you can manage permissions, file management, introspection, script launching, background setting, and nearly anything else you can think of, provided that you're patient enough for the point-and-click style of interaction. For power users, this seems slow, but ROX manages to make it relatively painless and very intuitive.
-
-### App directories, AppRun, and AppImage
-
-The ROX desktop has an elegant convention by which a directory containing a script named **AppRun** is executed as if it were an application. This means that in order to make a ROX app, all you have to do is compile code into a directory, place a script called **AppRun** at the root of that directory to execute the binary you've compiled, and then mark the directory executable. ROX-Filer displays a directory configured in the manner you set with a special icon and color. When you click on an app directory, ROX-Filer automatically runs the **AppRun** script inside. It looks and behaves exactly like an application that has been installed, but it's local to the user's home directory and requires no special permissions.
-
-This is a convenience feature, but it's one of those small features that feels great when you use it because it's so easy to implement. It's by no means essential, and it's only a few steps ahead of building an application locally, hiding the directory somewhere out of the way, and drumming up a quick **.desktop** file to act as your launcher. However, the concept of an application directory has been [cited][15] as an inspiration for the [AppImage][16] packaging system.
-
-### Why you should try ROX desktop
-
-Getting ROX set up and usable is somewhat difficult, and it appears to truly be abandoned. However, its legacy lives on in many ways today, and it's a fascinating and fun bit of Linux history. It may not become your primary desktop, but if you're looking for a fun trip back in time, then ROX is well worth a go. Explore it, customize it, and see what clever ideas it contains. There may yet be hidden gems that the open source community can benefit from.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/19/12/linux-rox-desktop
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/1980s-computer-yearbook.png?itok=eGOYEKK- (Person typing on a 1980's computer)
-[2]: http://rox.sourceforge.net/desktop/
-[3]: https://www.riscosopen.org/content/
-[4]: http://rox.sourceforge.net/desktop/ROX-Filer
-[5]: http://roxterm.sourceforge.net/
-[6]: http://rox.sourceforge.net/desktop/ROX-Lib
-[7]: https://opensource.com/article/17/7/how-unzip-targz-file
-[8]: http://rox.sourceforge.net/desktop/ROX-Session.html
-[9]: https://wiki.debian.org/BuildingTutorial
-[10]: https://docs.pagure.org/docs-fedora/installing-software-from-source.html
-[11]: https://opensource.com/sites/default/files/advent-kdm_0.jpg
-[12]: https://opensource.com/sites/default/files/advent-gdm_1.jpg
-[13]: https://opensource.com/sites/default/files/uploads/advent-rox.jpg (Default ROX desktop)
-[14]: https://opensource.com/sites/default/files/uploads/advent-rox-custom.jpg (ROX desktop)
-[15]: https://github.com/AppImage/AppImageKit/wiki/AppDir
-[16]: https://appimage.org/
diff --git a/sources/tech/20200211 Navigating man pages in Linux.md b/sources/tech/20200211 Navigating man pages in Linux.md
deleted file mode 100644
index 662a1d48af..0000000000
--- a/sources/tech/20200211 Navigating man pages in Linux.md
+++ /dev/null
@@ -1,179 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Navigating man pages in Linux)
-[#]: via: (https://www.networkworld.com/article/3519853/navigating-man-pages-in-linux.html)
-[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
-
-Navigating man pages in Linux
-======
-The man pages on a Linux system can do more than provide information on particular commands. They can help discover commands you didn't realize were available.
-[Hello I'm Nik][1] [(CC0)][2]
-
-Man pages provide essential information on Linux commands and many users refer to them often, but there’s a lot more to the man pages than many of us realize.
-
-You can always type a command like “man who” and get a nice description of how the man command works, but exploring commands that you might not know could be even more illuminating. For example, you can use the man command to help identify commands to handle some unusually challenging task or to show options that can help you use a command you already know in new and better ways.
-
-Let’s navigate through some options and see where we end up.
-
-[MORE ON NETWORK WORLD: Linux: Best desktop distros for newbies][3]
-
-### Using man to identify commands
-
-The man command can help you find commands by topic. If you’re looking for a command to count the lines in a file, for example, you can provide a keyword. In the example below, we’ve put the keyword in quotes and added blanks so that we don’t get commands that deal with “accounts” or “accounting” along with those that do some counting for us.
-
-```
-$ man -k ' count '
-anvil (8postfix) - Postfix session count and request rate control
-cksum (1) - checksum and count the bytes in a file
-sum (1) - checksum and count the blocks in a file
-timer_getoverrun (2) - get overrun count for a POSIX per-process timer
-```
-
-To show commands that relate to new user accounts, we might try a command like this:
-
-```
-$ man -k "new user"
-newusers (8) - update and create new users in batch
-useradd (8) - create a new user or update default new user information
-zshroadmap (1) - informal introduction to the zsh manual The Zsh Manual, …
-```
-
-Just to be clear, the third item in the list above makes a reference to “new users” liking the material and is not a command for setting up, removing or configuring user accounts. The man command is simply matching words in the command description, acting very much like the apropos command. Notice the numbers in parentheses after each command listed above. These relate to the man page sections that contain the commands.
-
-### Identifying the manual sections
-
-The man command sections divide the commands into categories. To list these categories, type “man man” and look for descriptions like those below. You very likely won’t have Section 9 commands on your system.
-
-[][4]
-
-```
-1 Executable programs or shell commands
-2 System calls (functions provided by the kernel)
-3 Library calls (functions within program libraries)
-4 Special files (usually found in /dev)
-5 File formats and conventions eg /etc/passwd
-6 Games
-7 Miscellaneous (including macro packages and conventions), e.g.
- man(7), groff(7)
-8 System administration commands (usually only for root)
-9 Kernel routines [Non standard]
-```
-
-Man pages cover more than what we typically think of as “commands”. As you can see from the above descriptions, they cover system calls, library calls, special files and more.
-
-The listing below shows where man pages are actually stored on Linux systems. The dates on these directories will vary because, with updates, some of these sections will get new content while others will not.
-
-```
-$ ls -ld /usr/share/man/man?
-drwxr-xr-x 2 root root 98304 Feb 5 16:27 /usr/share/man/man1
-drwxr-xr-x 2 root root 65536 Oct 23 17:39 /usr/share/man/man2
-drwxr-xr-x 2 root root 270336 Nov 15 06:28 /usr/share/man/man3
-drwxr-xr-x 2 root root 4096 Feb 4 10:16 /usr/share/man/man4
-drwxr-xr-x 2 root root 28672 Feb 5 16:25 /usr/share/man/man5
-drwxr-xr-x 2 root root 4096 Oct 23 17:40 /usr/share/man/man6
-drwxr-xr-x 2 root root 20480 Feb 5 16:25 /usr/share/man/man7
-drwxr-xr-x 2 root root 57344 Feb 5 16:25 /usr/share/man/man8
-```
-
-Note that the man page files are generally **gzipped** to save space. The man command unzips them as needed whenever you use the man command.
-
-```
-$ ls -l /usr/share/man/man1 | head -10
-total 12632
-lrwxrwxrwx 1 root root 9 Sep 5 06:38 [.1.gz -> test.1.gz
--rw-r--r-- 1 root root 563 Nov 7 05:07 2to3-2.7.1.gz
--rw-r--r-- 1 root root 592 Apr 23 2016 411toppm.1.gz
--rw-r--r-- 1 root root 2866 Aug 14 10:36 a2query.1.gz
--rw-r--r-- 1 root root 2361 Sep 9 15:13 aa-enabled.1.gz
--rw-r--r-- 1 root root 2675 Sep 9 15:13 aa-exec.1.gz
--rw-r--r-- 1 root root 1142 Apr 3 2018 aaflip.1.gz
--rw-r--r-- 1 root root 3847 Aug 14 10:36 ab.1.gz
--rw-r--r-- 1 root root 2378 Aug 23 2018 ac.1.gz
-```
-
-### Listing man pages by section
-
-Even just looking at the first 10 man pages in Section 1 (as shown above), you are likely to see some commands that are new to you – maybe **a2query** or **aaflip** (shown above).
-
-An even better strategy for exploring commands is to list commands by section without looking at the files themselves but, instead, using a man command that shows you the commands and provides a brief description of each.
-
-In the command below, the **-s 1** instructs man to display information on commands in section 1. The **-k .** makes the command work for all commands rather than specifying a particular keyword; without this, the man command would come back and ask “What manual page do you want?” So, use a keyword to select a group of related commands or a dot to show all commands in a section.
-
-```
-$ man -s 1 -k .
-2to3-2.7 (1) - Python2 to Python3 converter
-411toppm (1) - convert Sony Mavica .411 image to ppm
-as (1) - the portable GNU assembler.
-baobab (1) - A graphical tool to analyze disk usage
-busybox (1) - The Swiss Army Knife of Embedded Linux
-cmatrix (1) - simulates the display from "The Matrix"
-expect_dislocate (1) - disconnect and reconnect processes
-red (1) - line-oriented text editor
-enchant (1) - a spellchecker
-…
-```
-
-### How many man pages are there?
-
-If you’re curious about how many man pages there are in each section, you can count them by section with a command like this:
-
-```
-$ for num in {1..8}
-> do
-> man -s $num -k . | wc -l
-> done
-2382
-493
-2935
-53
-441
-11
-245
-919
-```
-
-The exact number may vary, but most Linux systems will have a similar number of commands. If we use a command that adds these numbers together, we can see that the system that this command is running on has nearly 7,500 man pages. That’s a lot of commands, system calls, etc.
-
-```
-$ for num in {1..8}
-> do
-> num=`man -s $num -k . | wc -l`
-> tot=`expr $num + $tot`
-> echo $tot
-> done
-2382
-2875
-5810
-5863
-6304
-6315
-6560
-7479 <=== total
-```
-
-There’s a lot you can learn by reading man pages, but exploring them in other ways can help you become aware of commands you may not have known were available on your system.
-
-Join the Network World communities on [Facebook][5] and [LinkedIn][6] to comment on topics that are top of mind.
-
---------------------------------------------------------------------------------
-
-via: https://www.networkworld.com/article/3519853/navigating-man-pages-in-linux.html
-
-作者:[Sandra Henry-Stocker][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
-[b]: https://github.com/lujun9972
-[1]: https://unsplash.com/photos/YiRQIglwYig
-[2]: https://creativecommons.org/publicdomain/zero/1.0/
-[3]: https://www.networkworld.com/slideshow/153439/linux-best-desktop-distros-for-newbies.html#tk.nww-infsb
-[4]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
-[5]: https://www.facebook.com/NetworkWorld/
-[6]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200213 Manage complex Git workspaces with Great Teeming Workspaces.md b/sources/tech/20200213 Manage complex Git workspaces with Great Teeming Workspaces.md
deleted file mode 100644
index ef41241e35..0000000000
--- a/sources/tech/20200213 Manage complex Git workspaces with Great Teeming Workspaces.md
+++ /dev/null
@@ -1,1169 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Manage complex Git workspaces with Great Teeming Workspaces)
-[#]: via: (https://opensource.com/article/20/2/git-great-teeming-workspaces)
-[#]: author: (Daniel Gryniewicz https://opensource.com/users/dang)
-
-Manage complex Git workspaces with Great Teeming Workspaces
-======
-GTWS is a set of scripts that make it easy to have development
-environments for different projects and different versions of a project.
-![Coding on a computer][1]
-
-Great Teeming Workspaces ([GTWS][2]) is a complex workspace management package for Git that makes it easy to have development environments for different projects and different versions of a project.
-
-Somewhat like Python [venv][3], but for languages other than Python, GTWS handles workspaces for multiple versions of multiple projects. You can create, update, enter, and leave workspaces easily, and each project or version combination has (at most) one local origin that syncs to and from the upstream—all other workspaces update from the local origin.
-
-### Layout
-
-
-```
-${GTWS_ORIGIN}/<project>/<repo>[/<version>]
-${GTWS_BASE_SRCDIR}/<project>/<version>/<workspacename>/{<repo>[,<repo>...]}
-```
-
-Each level in the source tree (plus the homedir for globals) can contain a **.gtwsrc** file that maintains settings and Bash code relevant to that level. Each more specific level overrides the higher levels.
-
-### Setup
-
-Check out GTWS with:
-
-
-```
-`git clone https://github.com/dang/gtws.git`
-```
-
-Set up your **${HOME}/.gtwsrc**. It should include **GTWS_ORIGIN** and optionally **GTWS_SETPROMPT**.
-
-Add the repo directory to your path:
-
-
-```
-`export PATH="${PATH}:/path/to/gtws`
-```
-
-### Configuration
-
-Configuration is via cascading **.gtwsrc** files. It walks the real path down from the root, and each **.gtwsrc** file it finds is sourced in turn. More specific files override less specific files.
-
-Set the following in your top-level **~/.gtws/.gtwsrc**:
-
- * **GTWS_BASE_SRCDIR:** This is the base of all the projects' source trees. It defaults to **$HOME/src**.
- * **GTWS_ORIGIN:** This sets the location of the origin Git trees. It defaults to **$HOME/origin**.
- * **GTWS_SETPROMPT:** This is optional. If it's set, the shell prompt will have the workspace name in it.
- * **GTWS_DEFAULT_PROJECT:** This is the project used when no project is given or known. If it is not given, projects must be specified on the command line.
- * **GTWS_DEFAULT_PROJECT_VERSION:** This is the default version to check out. It defaults to **master**.
-
-
-
-Set the following at the project level of each project:
-
- * **GTWS_PROJECT:** The name (and base directory) of the project.
- * **gtws_project_clone:** This function is used to clone a specific version of a project. If it is not defined, then it is assumed that the origin for the project contains a single directory per version, and that contains a set of Git repos to clone.
- * **gtws_project_setup:** This optional function is called after all cloning is done and allows any additional setup necessary for the project, such as setting up workspaces in an IDE.
-
-
-
-Set this at the project version level:
-
- * **GTWS_PROJECT_VERSION:** This is the version of the project. It's used to pull from the origin correctly. In Git, this is likely the branch name.
-
-
-
-These things can go anywhere in the tree and can be overridden multiple times, if it makes sense:
-
- * **GTWS_PATH_EXTRA:** These are extra path elements to be added to the path inside the workspace.
- * **GTWS_FILES_EXTRA:** These are extra files not under version control that should be copied into each checkout in the workspace. This includes things like **.git/info/exclude**, and each file is relative to the base of its repo.
-
-
-
-### Origin directories
-
-**GTWS_ORIGIN** (in most scripts) points to the pristine Git checkouts to pull from and push to.
-
-Layout of **${GTWS_ORIGIN}**:
-
- * **/<project>**
- * This is the base for repos for a project.
- * If **gtws_project_clone** is given, this can have any layout you desire.
- * If **gtws_project_clone** is not given, this must contain a single subdirectory named **git** that contains a set of bare Git repos to clone.
-
-
-
-### Workflow example
-
-Suppose you have a project named **Foo** that has an upstream repository at **github.com/foo/foo.git**. This repo has a submodule named **bar** with an upstream at **github.com/bar/bar.git**. The Foo project does development in the master branch and uses stable version branches.
-
-Before you can use GTWS with Foo, first you must set up the directory structure. These examples assume you are using the default directory structure.
-
- * Set up your top level **.gtwsrc**:
- * **cp ${GTWS_LOC}/examples/gtwsrc.top ~/.gtwsrc**
- * Edit **~/.gtwsrc** and change as necessary.
- * Create top-level directories:
- * **mkdir -p ~/origin ~/src**
- * Create and set up the project directory:
- * **mkdir -p ~/src/foo**
-**cp ${GTWS_LOC}/examples/gtwsrc.project ~/src/foo/.gtwsrc**
- * Edit **~/src/foo/.gtwsrc** and change as necessary.
- * Create and set up the master version directory:
- * **mkdir -p ~/src/foo/master**
-**cp ${GTWS_LOC}/examples/gtwsrc.version ~/src/foo/master/.gtwsrc**
- * Edit **~/src/foo/master/.gtwsrc** and change as necessary.
- * Go to the version directory and create a temporary workspace to set up the mirrors:
- * **mkdir -p ~/src/foo/master/tmp**
-**cd ~/src/foo/master/tmp
-git clone --recurse-submodules git://github.com/foo/foo.git
-cd foo
-gtws-mirror -o ~/origin -p foo**
- * This will create **~/origin/foo/git/foo.git** and **~/origin/foo/submodule/bar.git**.
- * Future clones will clone from these origins rather than from upstream.
- * This workspace can be deleted now.
-
-
-
-At this point, work can be done on the master branch of Foo. Suppose you want to fix a bug named **bug1234**. You can create a workspace for this work to keep it isolated from anything else you're working on, and then work within this workspace.
-
- * Go to the version directory, and create a new workspace:
- * **cd ~/src/foo/master
-mkws bug1234**
- * This creates **bug1234/**, and inside it checks out Foo (and its submodule **bar**) and makes **build/foo** for building it.
- * Enter the workspace. There are two ways to do this:
- * **cd ~/src/foo/master/bug1234
-startws**
-or
-**cd ~/src/foo/master/**
-**startws bug1234**
- * This starts a subshell within the bug1234 workspace. This shell has the GTWS environment plus any environment you set up in your stacked **.gtwsrc** files. It also adds the base of the workspace to your CD path, so you can **cd** into relative paths from that base.
- * At this point, you can do work on bug1234, build it, test it, and commit your changes. When you're ready to push to upstream, do this:
-**cd foo
-wspush**
- * **wspush** will push the branch associated with your workspace—first to your local origin and then to the upstream.
- * If upstream changes. you can sync your local checkout using:
-**git sync**
- * This envokes the **git-sync** script in GTWS, which will update your checkout from the local origin. To update the local origin, use:
-**git sync -o**
- * This will update your local origin and submodules' mirrors, then use those to update your checkout. **git-sync** has other nice features.
- * When you're done using the workspace, just exit the shell:
-**exit**
- * You can re-enter the workspace at any time and have multiple shells in the same workspace at the same time.
- * When you're done with a workspace, you can remove it using the **rmws** command or just remove its directory tree.
- * There is a script named **tmws** that enters a workspace within tmux, creating a set of windows/panes that are fairly specific to my workflow. Feel free to modify it to suit your needs.
-
-
-
-### The script
-
-
-```
-#!/bin/bash
-# Functions for gtws
-#
-
-GTWS_LOC=$(readlink -f $(dirname "${BASH_SOURCE[0]}"))
-export GTWS_LOC
-
-# if is_interactive; then echo "interactive" fi
-#
-# Check for an interactive shell
-is_interactive() {
- case $- in
- *i*)
- # Don't die in interactive shells
- return 0
- ;;
- *)
- return 1
- ;;
- esac
-}
-
-# if can_die; then exit
-#
-# Check to see if it's legal to exit during die
-can_die() {
- if (( BASH_SUBSHELL > 0 )); then
- debug_print "\t\tbaby shell; exiting"
- return 0
- fi
- if ! is_interactive; then
- debug_print "\t\tNot interactive; exiting"
- return 0
- fi
- debug_print "\t\tParent interactive; not exiting"
- return 1
-}
-
-# In a function:
-# command || die "message" || return 1
-# Outside a function:
-# command || die "message"
-#
-# Print a message and exit with failure
-die() {
- echo -e "Failed: $1" >&2
- if [ ! -z "$(declare -F | grep "GTWScleanup")" ]; then
- GTWScleanup
- fi
- if can_die; then
- exit 1
- fi
- return 1
-}
-
-# Alternativess for using die properly to handle both interactive and script useage:
-#
-# Version 1:
-#
-#testfunc() {
-# command1 || die "${FUNCNAME}: command1 failed" || return 1
-# command2 || die "${FUNCNAME}: command2 failed" || return 1
-# command3 || die "${FUNCNAME}: command3 failed" || return 1
-#}
-#
-# Version 2:
-#
-#testfunc() {
-# (
-# command1 || die "${FUNCNAME}: command1 failed"
-# command2 || die "${FUNCNAME}: command2 failed"
-# command3 || die "${FUNCNAME}: command3 failed"
-# )
-# return $?
-#}
-#
-# Optionally, the return can be replaced with this:
-# local val=$?
-# [[ "${val}" == "0" ]] || die
-# return ${val}
-# This will cause the contaning script to abort
-
-# usage "You need to provide a frobnicator"
-#
-# Print a message and the usage for the current script and exit with failure.
-usage() {
- local myusage;
- if [ -n "${USAGE}" ]; then
- myusage=${USAGE}
- else
- myusage="No usage given"
- fi
- local me;
- if [ -n "${ME}" ]; then
- me=${ME}
- else
- me=$(basename $0)
- fi
- if [ -n "$1" ]; then
- echo "$@"
- fi
- echo ""
- if [ -n "${DESCRIPTION}" ]; then
- echo -e "${me}: ${DESCRIPTION}"
- echo ""
- fi
- echo "Usage:"
- echo "${me} ${myusage}"
- if [ -n "${LONGUSAGE}" ]; then
- echo -e "${LONGUSAGE}"
- fi
- exit 1
-}
-
-# debug_print "Print debug information"
-#
-# Print debug information based on GTWS_VERBOSE
-debug_print() {
- if [ -n "${GTWS_VERBOSE}" ]; then
- echo -e "${GTWS_INDENT}$@" >&2
- fi
-}
-
-# debug_trace_start
-#
-# Start tracing all commands
-debug_trace_start() {
- if [ -n "${GTWS_VERBOSE}" ]; then
- set -x
- fi
-}
-
-# debug_trace_stop
-#
-# Stop tracing all commands
-debug_trace_stop() {
- set +x
-}
-
-# cmd_exists ${cmd}
-#
-# Determine if a command exists on the system
-function cmd_exists {
- which $1 > /dev/null 2>&1
- if [ "$?" == "1" ]; then
- die "You don't have $1 installed, sorry" || return 1
- fi
-}
-
-# is_git_repo ${dir}
-#
-# return success if ${dir} is in a git repo, or failure otherwise
-is_git_repo() {
- debug_print "is_git_repo $1"
- if [[ $1 == *:* ]]; then
- debug_print " remote; assume good"
- return 0
- elif [ ! -d "$1" ]; then
- debug_print " fail: not dir"
- return 1
- fi
- cd "$1"
- git rev-parse --git-dir >/dev/null 2>&1
- local ret=$?
- cd - > /dev/null
- debug_print " retval: $ret"
- return $ret
-}
-
-# find_git_repo ${basedir} ${repo_name} repo_dir
-#
-# Find the git repo for ${repo_name} in ${basedir}. It's one of ${repo_name}
-# or ${repo_name}.git
-#
-# Result will be in the local variable repo_dir Or:
-#
-# repo_dir=$(find_git_repo ${basedir} ${repo_name})
-#
-function find_git_repo {
- local basedir=$1
- local repo_name=$2
- local __resultvar=$3
- local try="${basedir}/${repo_name}"
-
- if ! is_git_repo "${try}" ; then
- try=${try}.git
- fi
-
- is_git_repo "${try}" || die "${repo_name} in ${basedir} is not a git repository" || return 1
-
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$try'"
- else
- echo "$try"
- fi
-}
-
-# git_top_dir top
-#
-# Get the top level of the git repo contaning PWD, or return failure;
-#
-# Result will be in local variable top Or:
-#
-# top = $(git_top_dir)
-#
-# Result will be in local variable top
-function git_top_dir {
- local __resultvar=$1
- local __top="$(git rev-parse --show-toplevel 2>/dev/null)"
-
- if [ -z "${__top}" ]; then
- die "${PWD} is not a git repo" || return 1
- fi
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$__top'"
- else
- echo "$__top"
- fi
-}
-
-# is_git_rebase
-#
-# return success if git repo is in a rebase
-is_git_rebase() {
- debug_print "is_git_rebase $1"
- (test -d "$(git rev-parse --git-path rebase-merge)" || \
- test -d "$(git rev-parse --git-path rebase-apply)" )
- local ret=$?
- debug_print " retval: $ret"
- return $ret
-}
-
-# is_docker
-#
-# return success if process is running inside docker
-is_docker() {
- debug_print "is_docker"
- grep -q docker /proc/self/cgroup
- return $?
-}
-
-# is_gtws
-#
-# return success if process is running inside a workspace
-is_gtws() {
- if [ -n "${GTWS_WS_GUARD}" ]; then
- return 0
- fi
- return 1
-}
-
-function gtws_rcp {
- rsync --rsh=ssh -avzS --progress --ignore-missing-args --quiet "$@"
-}
-
-function gtws_cpdot {
- local srcdir=$1
- local dstdir=$2
-
- debug_print "${FUNCNAME} - ${srcdir} to ${dstdir}"
- if [ -d "${srcdir}" ] && [ -d "${dstdir}" ]; then
- shopt -s dotglob
- cp -a "${srcdir}"/* "${dstdir}"/
- shopt -u dotglob
- fi
-}
-
-# gtws_find_dockerfile dockerfile
-#
-# Result will be in local variable dockerfile Or:
-#
-# dockerfile = $(gtws_find_dockerfile)
-#
-# Result will be in local variable dockerfile
-#
-# Get the path to the most-specific Dockerfile
-function gtws_find_dockerfile {
- local __resultvar=$1
- local __dir="${GTWS_WSPATH}"
- local __file="Dockerfile"
-
- debug_print "${FUNCNAME} - trying ${__dir}/${__file}"
- if [ ! -f "${__dir}/${__file}" ]; then
- # Version dir
- __dir=$(dirname "${__dir}")
- debug_print "${FUNCNAME} - trying ${__dir}/${__file}"
- fi
- if [ ! -f "${__dir}/${__file}" ]; then
- # Project dir
- __dir=$(dirname "${__dir}")
- debug_print "${FUNCNAME} - trying ${__dir}/${__file}"
- fi
- if [ ! -f "${__dir}/${__file}" ]; then
- # Top level, flavor
- __dir="${GTWS_LOC}/dockerfiles"
- __file="Dockerfile-${FLAVOR}"
- debug_print "${FUNCNAME} - trying ${__dir}/${__file}"
- fi
- if [ ! -f "${__dir}/${__file}" ]; then
- # Top level, base
- __dir="${GTWS_LOC}/dockerfiles"
- __file="Dockerfile-base"
- debug_print "${FUNCNAME} - trying ${__dir}/${__file}"
- fi
- if [ ! -f "${__dir}/${__file}" ]; then
- die "Could not find a Dockerfile" || return 1
- fi
-
- debug_print "${FUNCNAME} - found ${__dir}/${__file}"
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'${__dir}/${__file}'"
- else
- echo "$__dir"
- fi
-}
-
-# gtws_smopvn ${GTWS_SUBMODULE_ORIGIN:-${GTWS_ORIGIN}} ${GTWS_PROJECT} ${GTWS_PROJECT_VERSION} ${GTWS_WSNAME} smopvn
-#
-# Result will be in local variable smopvn. Or:
-#
-# smopvn = $(gtws_smopvn ${GTWS_SUBMODULE_ORIGIN:-${GTWS_ORIGIN}} ${GTWS_PROJECT} ${GTWS_PROJECT_VERSION} ${GTWS_WSNAME})
-#
-# Result will be in local variable smovpn
-#
-# Get the path to submodules for this workspace
-function gtws_smopvn {
- local origin=$1
- local project=$2
- local version=$3
- local name=$4
- local __resultvar=$5
- local __smopv="${origin}/${project}/submodule"
-
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$__smopv'"
- else
- echo "$__smopv"
- fi
-}
-
-# gtws_opvn ${GTWS_ORIGIN} ${GTWS_PROJECT} ${GTWS_PROJECT_VERSION} ${GTWS_WSNAME} opvn
-#
-# Result will be in local variable opvn. Or:
-#
-# opvn = $(gtws_opvn ${GTWS_ORIGIN} ${GTWS_PROJECT} ${GTWS_PROJECT_VERSION} ${GTWS_WSNAME})
-#
-# Result will be in local variable opvn.
-#
-# Get the path to git repos for this workspace
-function gtws_opvn {
- local origin=$1
- local project=$2
- local version=$3
- local name=$4
- local __resultvar=$5
- local __opv="${origin}/${project}/${version}"
-
- if [[ $__opv == *:* ]]; then
- __opv="${__opv}/${name}"
- debug_print "remote; using opvn $__opv"
- elif [ ! -d "${__opv}" ]; then
- __opv="${origin}/${project}/git"
- if [ ! -d "${__opv}" ]; then
- die "No opvn for ${origin} ${project} ${version}" || return 1
- fi
- fi
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$__opv'"
- else
- echo "$__opv"
- fi
-}
-
-# gtws_submodule_url ${submodule} url
-#
-# Result will be in local variable url Or:
-#
-# url = $(gtws_submodule_url ${submodule})
-#
-# Result will be in local variable url
-#
-# Get the URL for a submodule
-function gtws_submodule_url {
- local sub=$1
- local __resultvar=$2
- local __url=$(git config --list | grep "submodule.*url" | grep "\<${sub}\>" | cut -d = -f 2)
-
- if [ -z "${__url}" ]; then
- local rpath=${PWD}
- local subsub=$(basename "${sub}")
- cd "$(dirname "${sub}")"
- debug_print "${FUNCNAME} trying ${PWD}"
- __url=$(git config --list | grep submodule | grep "\<${subsub}\>" | cut -d = -f 2)
- cd "${rpath}"
- fi
-
- debug_print "${FUNCNAME} $sub url: $__url"
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$__url'"
- else
- echo "$__url"
- fi
-}
-
-# gtws_submodule_mirror ${smopv} ${submodule} ${sub_sub_basename} mloc
-#
-# Result will be in local variable mloc Or:
-#
-# mloc = $(gtws_submodule_mirror ${smopv} ${submodule} ${sub_sub_basename})
-#
-# Result will be in local variable mloc
-#
-# Get the path to a local mirror of the submodule, if it exists
-function gtws_submodule_mirror {
- local smopv=$1
- local sub=$2
- local sub_sub=$3
- local __resultvar=$4
- local __mloc=""
- local url=$(gtws_submodule_url ${sub})
- if [ -n "${url}" ]; then
- local urlbase=$(basename ${url})
- # XXX TODO - handle remote repositories
- #if [[ ${smopv} == *:* ]]; then
- ## Remote SMOPV means clone from that checkout; I don't cm
- #refopt="--reference ${smopv}/${name}/${sub}"
- if [ -d "${smopv}/${urlbase}" ]; then
- __mloc="${smopv}/${urlbase}"
- fi
- fi
-
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$__mloc'"
- else
- echo "$__mloc"
- fi
-}
-
-# gtws_submodule_paths subpaths
-#
-# Result will be in local variable subpaths Or:
-#
-# subpaths = $(gtws_submodule_paths)
-#
-# Result will be in local variable subpaths
-#
-# Get the paths to submodules in a get repo. Does not recurse
-function gtws_submodule_paths {
- local __resultvar=$1
- local __subpaths=$(git submodule status | sed 's/^ *//' | cut -d ' ' -f 2)
-
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$__subpaths'"
- else
- echo "$__subpaths"
- fi
-}
-
-# gtws_submodule_clone [<base-submodule-path>] [<sub-sub-basename>]
-#
-# This will set up all the submodules in a repo. Should be called from inside
-# the parent repo
-function gtws_submodule_clone {
- local smopv=$1
- local sub_sub=$2
- local sub_paths=$(gtws_submodule_paths)
- local rpath="${PWD}"
-
- if [ -z "${smopv}" ]; then
- smopv=$(gtws_smopvn "${GTWS_SUBMODULE_ORIGIN:-${GTWS_ORIGIN}}" "${GTWS_PROJECT}" "${GTWS_PROJECT_VERSION}" "${GTWS_WSNAME}")
- fi
- git submodule init || die "${FUNCNAME}: Failed to init submodules" || return 1
- for sub in ${sub_paths}; do
- local refopt=""
- local mirror=$(gtws_submodule_mirror "${smopv}" "${sub}" "${sub_sub}")
- debug_print "${FUNCNAME} mirror: ${mirror}"
- if [ -n "${mirror}" ]; then
- refopt="--reference ${mirror}"
- fi
- git submodule update ${refopt} "${sub}"
- # Now see if there are recursive submodules
- cd "${sub}"
- gtws_submodule_clone "${smopv}/${sub}_submodule" "${sub}" || return 1
- cd "${rpath}"
- done
-}
-
-# gtws_repo_clone <base-repo-path> <repo> <branch> [<base-submodule-path>] [<target-directory>]
-function gtws_repo_clone {
- local baserpath=${1%/}
- local repo=$2
- local branch=$3
- local basesmpath=$4
- local rname=${5:-${repo%.git}}
- local rpath="${baserpath}/${repo}"
- local origpath=${PWD}
-
- if [[ ${rpath} != *:* ]]; then
- if [ ! -d "${rpath}" ]; then
- rpath="${rpath}.git"
- fi
- fi
- if [ -z "${basesmpath}" ]; then
- basesmpath="${baserpath}"
- fi
- debug_print "${FUNCNAME}: cloning ${baserpath} - ${repo} : ${branch} into ${GTWS_WSNAME}/${rname} submodules: ${basesmpath}"
-
- # Main repo
- #git clone --recurse-submodules -b "${branch}" "${rpath}" || die "failed to clone ${rpath}:${branch}" || return 1
- git clone -b "${branch}" "${rpath}" ${rname} || die "${FUNCNAME}: failed to clone ${rpath}:${branch}" || return 1
-
- # Update submodules
- cd "${rname}" || die "${FUNCNAME}: failed to cd to ${rpath}" || return 1
- gtws_submodule_clone "${basesmpath}" || return 1
- cd "${origpath}" || die "${FUNCNAME}: Failed to cd to ${origpath}" || return 1
-
- # Copy per-repo settings, if they exist
- gtws_cpdot "${baserpath%/git}/extra/repo/${rname}" "${origpath}/${rname}"
-
- # Extra files
- for i in ${GTWS_FILES_EXTRA}; do
- local esrc=
-
- IFS=':' read -ra ARR <<< "$i"
- if [ -n "${ARR[1]}" ]; then
- dst="${rname}/${ARR[1]}"
- else
- dst="${rname}/${ARR[0]}"
- fi
-
- if [ -n "${GTWS_REMOTE_IS_WS}" ]; then
- esrc="${baserpath}/${dst}"
- else
- esrc="${baserpath%/git}"
- fi
-
- gtws_rcp "${esrc}/${ARR[0]}" "${dst}"
- done
-}
-
-# gtws_project_clone_default ${GTWS_ORIGIN} ${GTWS_PROJECT} ${GTWS_PROJECT_VERSION} ${GTWS_WSNAME} [${SUBMODULE_BASE}]
-#
-# Clone a version of a project into ${GTWS_WSPATH} (which is the current working directory). This is the default version of this that clones <origin>/<project>/<version>/*
-function gtws_project_clone_default {
- local origin=$1
- local project=$2
- local version=$3
- local name=$4
- local basesmpath=$5
- local opv=$(gtws_opvn "${origin}" "${project}" "${version}" "${name}")
- local wspath=${PWD}
- local repos=
- local -A branches
-
- if [ -z "${GTWS_PROJECT_REPOS}" ]; then
- for i in "${opv}"/*; do
- repos="$(basename $i) $repos"
- branches[$i]=${version}
- done
- else
- for i in ${GTWS_PROJECT_REPOS}; do
- IFS=':' read -ra ARR <<< "$i"
- repos="${ARR[0]} $repos"
- if [ -n "${ARR[1]}" ]; then
- branches[${ARR[0]}]=${ARR[1]}
- else
- branches[${ARR[0]}]=${version}
- fi
- done
- fi
-
- if [ -z "${basesmpath}" ] || [ ! -d "${basesmpath}" ]; then
- basesmpath="${opv}"
- fi
-
- for repo in ${repos}; do
- gtws_repo_clone "${opv}" "${repo}" "${branches[${repo}]}" "${basesmpath}"
- done
-
- # Copy per-WS settings, if they exist
- gtws_cpdot "${opv%/git}/extra/ws" "${wspath}"
-}
-
-# gtws_repo_setup ${wspath} ${repo_path}
-#
-# The project can define gtws_repo_setup_local taking the same args to do
-# project-specific setup. It will be called last.
-#
-# Post-clone setup for an individual repo
-function gtws_repo_setup {
- local wspath=$1
- local rpath=$2
- local savedir="${PWD}"
-
- if [ ! -d "${rpath}" ]; then
- return 0
- fi
-
- cd "${rpath}/src" 2>/dev/null \
- || cd ${rpath} \
- || die "Couldn't cd to ${rpath}" || return 1
-
- maketags ${GTWS_MAKETAGS_OPTS} > /dev/null 2> /dev/null &
-
- cd ${wspath} || die "Couldn't cd to ${wspath}" || return 1
-
- mkdir -p "${wspath}/build/$(basename ${rpath})"
-
- cd "${savedir}"
-
- if [ -n "$(declare -F | grep "\<gtws_repo_setup_local\>")" ]; then
- gtws_repo_setup_local "${wspath}" "${rpath}" \
- || die "local repo setup failed" || return 1
- fi
-}
-
-# gtws_project_setup${GTWS_WSNAME} ${GTWS_ORIGIN} ${GTWS_PROJECT} ${GTWS_PROJECT_VERSION}
-#
-# The project can define gtws_project_setup_local taking the same args to do
-# project-specific setup. It will be called last.
-#
-# Post clone setup of a workspace in ${GTWS_WSPATH} (which is PWD)
-function gtws_project_setup {
- local wsname=$1
- local origin=$2
- local project=$3
- local version=$4
- local wspath=${PWD}
- local opv=$(gtws_opvn "${origin}" "${project}" "${version}" "placeholder")
-
- for i in "${wspath}"/*; do
- gtws_repo_setup "${wspath}" "${i}"
- done
-
- mkdir "${wspath}"/install
- mkdir "${wspath}"/chroots
- mkdir "${wspath}"/patches
-
- if [ -n "$(declare -F | grep "\<gtws_project_setup_local\>")" ]; then
- gtws_project_setup_local "${wsname}" "${origin}" "${project}" \
- "${version}" || die "local project setup failed" || return 1
- fi
-}
-
-# load_rc /path/to/workspace
-#
-# This should be in the workspace-level gtwsrc file
-# Recursively load all RC files, starting at /
-function load_rc {
- local BASE=$(readlink -f "${1}")
- # Load base RC first
- debug_print "load_rc: Enter + Top: ${BASE}"
- source "${HOME}"/.gtwsrc
- while [ "${BASE}" != "/" ]; do
- if [ -f "${BASE}"/.gtwsrc ]; then
- load_rc "$(dirname ${BASE})"
- debug_print "\tLoading ${BASE}/.gtwsrc"
- source "${BASE}"/.gtwsrc
- return 0
- fi
- BASE=$(readlink -f $(dirname "${BASE}"))
- done
- # Stop at /
-
- return 1
-}
-
-# clear_env
-#
-# Clear the environment of GTWS_* except for the contents of GTWS_SAVEVARS.
-# The default values for GTWS_SAVEVARS are below.
-function clear_env {
- local savevars=${GTWS_SAVEVARS:-"LOC PROJECT PROJECT_VERSION VERBOSE WSNAME"}
- local verbose="${GTWS_VERBOSE}"
- debug_print "savevars=$savevars"
-
- # Reset prompt
- if [ -n "${GTWS_SAVEPS1}" ]; then
- PS1="${GTWS_SAVEPS1}"
- fi
- if [ -n "${GTWS_SAVEPATH}" ]; then
- export PATH=${GTWS_SAVEPATH}
- fi
- unset LD_LIBRARY_PATH
- unset PYTHONPATH
- unset PROMPT_COMMAND
- unset CDPATH
- unset SDIRS
-
- # Save variables
- for i in ${savevars}; do
- SRC=GTWS_${i}
- DST=SAVE_${i}
- debug_print "\t $i: ${DST} = ${!SRC}"
- eval ${DST}=${!SRC}
- done
-
- # Clear GTWS evironment
- for i in ${!GTWS*} ; do
- if [ -n "${verbose}" ]; then
- echo -e "unset $i" >&2
- fi
- unset $i
- done
-
- # Restore variables
- for i in ${savevars}; do
- SRC=SAVE_${i}
- DST=GTWS_${i}
- if [ -n "${verbose}" ]; then
- echo -e "\t $i: ${DST} = ${!SRC}" >&2
- fi
- if [ -n "${!SRC}" ]; then
- eval export ${DST}=${!SRC}
- fi
- unset ${SRC}
- done
-}
-
-# save_env ${file} ${nukevars}
-#
-# Save the environment of GTWS_* to the give file, except for the variables
-# given to nuke. The default values to nuke are given below.
-function save_env {
- local fname=${1}
- local nukevars=${2:-"SAVEPATH ORIGIN WS_GUARD LOC SAVEPS1"}
- debug_print "nukevars=$nukevars"
-
- for i in ${!GTWS*} ; do
- for j in ${nukevars}; do
- if [ "${i}" == "GTWS_${j}" ]; then
- debug_print "skipping $i"
- continue 2
- fi
- done
- debug_print "saving $i"
- echo "export $i=\"${!i}\"" >> "${fname}"
- done
-}
-
-# gtws_tmux_session_name ${PROJECT} ${VERSION} ${WSNAME} sesname
-#
-# Result will be in local variable sesname Or:
-#
-# sesname = $(gtws_tmux_session_name ${PROJECT} ${VERSION} ${WSNAME})
-#
-# Result will be in local variable sesname
-#
-# Get the tmux session name for a given workspace
-function gtws_tmux_session_name {
- local project=$1
- local version=$2
- local wsname=$3
- local __resultvar=$4
- local sesname="${project//./_}/${version//./_}/${wsname//./_}"
-
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$sesname'"
- else
- echo "$sesname"
- fi
-}
-
-# gtws_tmux_session_info ${SESSION_NAME} running attached
-#
-# Determine if a session is running, and if it is attached
-#
-# Result will be in local variables running and attached
-#
-# Test with:
-# if $running ; then
-# echo "is running"
-# fi
-
-function gtws_tmux_session_info {
- local ses_name=$1
- local __result_running=$2
- local __result_attached=$3
-
- local __num_ses=$(tmux ls | grep "^${ses_name}" | wc -l)
- local __attached=$(tmux ls | grep "^${ses_name}" | grep attached)
-
- echo "$ses_name ses=${__num_ses}"
-
- if [[ "$__result_running" ]]; then
- if [ "${__num_ses}" != "0" ]; then
- eval $__result_running="true"
- else
- eval $__result_running="false"
- fi
- fi
- if [[ "$__result_attached" ]]; then
- if [ -n "${__attached}" ]; then
- eval $__result_attached="true"
- else
- eval $__result_attached="false"
- fi
- fi
-}
-
-# gtws_tmux_kill ${BASENAME}
-#
-# Kill all sessiont matching a pattern
-function gtws_tmux_kill {
- local basename=$1
- local old_sessions=$(tmux ls 2>/dev/null | fgrep "${basename}" | cut -f 1 -d:)
- for session in ${old_sessions}; do
- tmux kill-session -t "${session}"
- done
-}
-
-# gtws_tmux_cleanup
-#
-# Clean up defunct tmux sessions
-function gtws_tmux_cleanup {
- local old_sessions=$(tmux ls 2>/dev/null | egrep "^[0-9]{14}.*[0-9]+\\)$" | cut -f 1 -d:)
- for session in ${old_sessions}; do
- tmux kill-session -t "${session}"
- done
-}
-
-# gtws_tmux_attach ${SESSION_NAME}
-#
-# Attach to a primary session. It will remain after detaching.
-function gtws_tmux_attach {
- local ses_name=$1
-
- tmux attach-session -t "${ses_name}"
-}
-
-# gtws_tmux_slave ${SESSION_NAME}
-#
-# Create a secondary session attached to the primary session. It will exit it
-# is detached.
-function gtws_tmux_slave {
- local ses_name=$1
-
- # Session is is date and time to prevent conflict
- local session=`date +%Y%m%d%H%M%S`
- # Create a new session (without attaching it) and link to base session
- # to share windows
- tmux new-session -d -t "${ses_name}" -s "${session}"
- # Attach to the new session
- gtws_tmux_attach "${session}"
- # When we detach from it, kill the session
- tmux kill-session -t "${session}"
-}
-
-function cdorigin() {
- if [ -n "$(declare -F | grep "gtws_project_cdorigin")" ]; then
- gtws_project_cdorigin $@
- else
- gtws_cdorigin $@
- fi
-}
-
-function gtws_get_origin {
- local opv=$1
- local target=$2
- local __origin=
- local __resultvar=$3
-
- # If it's a git repo with a local origin, use that.
- __origin=$(git config --get remote.origin.url)
- if [ ! -d "${__origin}" ]; then
- __origin="${__origin}.git"
- fi
- if [ ! -d "${__origin}" ]; then
- # Try to figure it out
- if [ ! -d "${opv}" ]; then
- die "No opv for $target" || return 1
- fi
- find_git_repo "${opv}" "${target}" __origin || return 1
- fi
-
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$__origin'"
- else
- echo "$__origin"
- fi
-}
-
-function gtws_cdorigin() {
- local opv=$(gtws_opvn "${GTWS_ORIGIN}" "${GTWS_PROJECT}" "${GTWS_PROJECT_VERSION}" "${GTWS_WSNAME}")
- local gitdir=""
- local target=""
- if [ -n "$1" ]; then
- target="$@"
- else
- git_top_dir gitdir || return 1
- target=$(basename $gitdir)
- fi
-
- gtws_get_origin $opv $target origin || return 1
- cd "${origin}"
-}
-
-# Copy files to another machine in the same workspace
-function wsrcp {
- local target="${!#}"
- local length=$(($#-1))
- local base=${PWD}
-
- if [ -z "${1}" -o -z "${2}" ]; then
- echo "usage: ${FUNCNAME} <path> [<path>...] <target>"
- return 1
- fi
-
- for path in "${@:1:$length}"; do
- gtws_rcp "${path}" "${target}:${base}/${path}"
- done
-}
-
-# Override "cd" inside the workspace to go to GTWS_WSPATH by default
-function cd {
- if [ -z "$@" ]; then
- cd "${GTWS_WSPATH}"
- else
- builtin cd $@
- fi
-}
-
-# Generate diffs/interdiffs for changes and ship to WS on other boxes
-function gtws_interdiff {
- local targets=$@
- local target=
- local savedir=${PWD}
- local topdir=$(git_top_dir)
- local repo=$(basename ${topdir})
- local mainpatch="${GTWS_WSPATH}/patches/${repo}-full.patch"
- local interpatch="${GTWS_WSPATH}/patches/${repo}-incremental.patch"
-
- if [ -z "${targets}" ]; then
- echo "Usage: ${FUNCNAME} <targethost>"
- die "Must give targethost" || return 1
- fi
- cd "${topdir}"
- if [ -f "${mainpatch}" ]; then
- git diff | interdiff "${mainpatch}" - > "${interpatch}"
- fi
- git diff > "${mainpatch}"
- for target in ${targets}; do
- gtws_rcp "${mainpatch}" "${interpatch}" \
- "${target}:${GTWS_WSPATH}/patches"
- done
- cd "${savedir}"
-}
-
-function gtws_debug {
- local cmd=$1
- if [ -z "${cmd}" ]; then
- echo "Must give a command"
- echo
- die "${FUNCNAME} <cmd-path>" || return 1
- fi
- local cmdbase=$(basename $cmd)
- local pid=$(pgrep "${cmdbase}")
-
- ASAN_OPTIONS="abort_on_error=1" cgdb ${cmd} ${pid}
-}
-
-# remote_cmd "${target}" "${command}" output
-#
-# Result will be in local variable output Or:
-#
-# output = $(remote_cmd "${target}" "${command}")
-#
-# Result will be in local variable output
-#
-# Run a command remotely and capture sdtout. Make sure to quote the command
-# appropriately.
-remote_cmd() {
- local target=$1
- local cmd=$2
- local __resultvar=$3
- local output=
-
- if [ -z "${GTWS_VERBOSE}" ]; then
- output=$(ssh "${target}" "${cmd}" 2>/dev/null)
- else
- output=$(ssh "${target}" "${cmd}")
- fi
- local ret=$?
-
- if [[ "$__resultvar" ]]; then
- eval $__resultvar="'$output'"
- else
- echo "${output}"
- fi
- return ${ret}
-}
-```
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/git-great-teeming-workspaces
-
-作者:[Daniel Gryniewicz][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/dang
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_laptop_hack_work.png?itok=aSpcWkcl (Coding on a computer)
-[2]: https://github.com/dang/gtws
-[3]: https://docs.python.org/3/library/venv.html
diff --git a/sources/tech/20200219 Basic Vim Commands You Need to Know to Work in Vim Editor.md b/sources/tech/20200219 Basic Vim Commands You Need to Know to Work in Vim Editor.md
deleted file mode 100644
index 6b959364b7..0000000000
--- a/sources/tech/20200219 Basic Vim Commands You Need to Know to Work in Vim Editor.md
+++ /dev/null
@@ -1,168 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (mengxinayan)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Basic Vim Commands You Need to Know to Work in Vim Editor)
-[#]: via: (https://www.2daygeek.com/basic-vim-commands-cheat-sheet-quick-start-guide/)
-[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
-
-Basic Vim Commands You Need to Know to Work in Vim Editor
-======
-
-If you are a system administrator or developer, you may need to edit a file while working on the Linux terminal.
-
-There are several file editors on Linux, and how to choose the right one for your needs.
-
-I would like to recommend Vim editor.
-
-### You may ask, why?
-
-You may spend more time in the editor to modify an existing file than writing new text.
-
-In this case, Vim Keyboard shortcuts allow you to efficiently meet your needs.
-
-The following articles may help you learn about file and directory manipulation.
-
- * [**L**][1]**[inux Basic – Linux and Unix Commands for File and Directory Manipulation][1]**
- * **[10 Methods to View Different File Formats in Linux][2]**
-
-
-
-### What’s vim?
-
-Vim is one of the most popular and powerful text editor that widely used by Linux administrators and developers.
-
-It’s highly configurable text editor which enables efficient text editing. This is an updated version of the vi editor, which is already installed on most Unix systems.
-
-Vim is often called a “programmer’s editor,” but it is not limited to it, and is suitable for all types of text editing.
-
-It comes with many features like multi level undo, multi windows and buffers, syntax highlighting, command line editing, file name completion, visual selection.
-
-You can easily obtain online help with the “:help” command.
-
-### Understanding Vim Modes
-
-Vim has two modes, the details are below:
-
-**Command Mode:** When you launch Vim Editor, you will default to Command Mode. You can move around the file, and modify some parts of the text, cut, copy, and paste parts of the text and issue commands to do more (press ESC for Command Mode).
-
-**Insert Mode:** The nsert mode is used to type text in a given given document (Press i for insert mode).
-
-### How do I know which Vim mode I am on?
-
-If you are in insert mode, you will see **“INSERT”** at the bottom of the editor. If nothing is shown, or if it shows the file name at the bottom of the editor, you are in “Command Mode”.
-
-### Cursor Movement in Normal Mode
-
-These Vim keyboard shortcuts allow you to move your cursor around a file in different ways.
-
- * `G` – Go to the last line of the file
- * `gg` – Go to the first line of the file
- * `$` – Go to the end of line.
- * `0` (zero) – Go to the beginning of line.
-
-
- * `w` – Jump by start of words
- * `W` – Jump by words (spaces separate words)
- * `b` – Jump backward by words
- * `B` – Jump backward by words (spaces separate words)
-
-
- * `PgDn` Key – Move down page-wise
- * `PgUp` Key – Move up page-wise
- * `Ctrl+d` – Move half-page down
- * `Ctrl+u` – Move half-page up
-
-
-
-### Insert mode – insert a text
-
-These vim keyboard shortcuts allows you to insert a cursor in varies position based on your needs.
-
- * `i` – Insert before the cursor
- * `a` – Insert after the cursor
- * `I` – Insert at the beginning of the line, this is useful when you are in the middle of the line.
- * `A` – Insert at the end of the line
- * `o` – Open a new line below the current line
- * `O` – Append a new line above the current line
- * `ea` – Insert at the end of the word
-
-
-
-### Copy, Paste and Delete a Line
-
- * `yy` – yank (copy) a line
- * `p/P` – Paste after cursor/ put before cursor
- * `dd` – delete a line
- * `dw` – delete the word
-
-
-
-### Search and Replace Pattern in Vim
-
- * `/pattern` – To search a given pattern
- * `?pattern` – To search backward a given pattern
- * `n` – To repeat search
- * `N` – To repeat backward search
-
-
- * `:%s/old-pattern/new-pattern/g` – Replace all old formats with the new format across the file.
- * `:s/old-pattern/new-pattern/g` – Replace all old formats with the new format in the current line.
- * `:%s/old-pattern/new-pattern/gc` – Replace all old formats with the new format across the file with confirmations.
-
-
-
-### How do I go to a particular line in Vim Editor
-
-You can do this in two ways, depending on your need. If you don’t know the line number I suggest you go with the first method.
-
-Add line number by opening a file and running the command below.
-
-```
-:set number
-```
-
-Once you have set the line number, press **“: n”** to go to the corresponding line number. For example, if you want to go to **line 15**, enter.
-
-```
-:15
-```
-
-If you already know the line number, use the following method to go directly to the corresponding line. For example, if you want to move to line 20, enter the command below.
-
-```
-$ vim +20 [File_Name]
-```
-
-### Undo/Redo/Repeat Operation
-
- * `u` – Undo the changes
- * `Ctrl+r` – Redo the changes
- * `.` – Repeat last command
-
-
-
-### Saving and Exiting Vim
-
- * `:w` – Save the changes but don’t exit
- * `:wq` – Write and quit
- * `:q!` – Force quit
-
-
-
---------------------------------------------------------------------------------
-
-via: https://www.2daygeek.com/basic-vim-commands-cheat-sheet-quick-start-guide/
-
-作者:[Magesh Maruthamuthu][a]
-选题:[lujun9972][b]
-译者:[萌新阿岩](https://github.com/mengxinayan)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://www.2daygeek.com/author/magesh/
-[b]: https://github.com/lujun9972
-[1]: https://www.2daygeek.com/linux-basic-commands-file-directory-manipulation/
-[2]: https://www.2daygeek.com/unix-linux-command-to-view-file/
diff --git a/sources/tech/20200222 How to install TT-RSS on a Raspberry Pi.md b/sources/tech/20200222 How to install TT-RSS on a Raspberry Pi.md
deleted file mode 100644
index ec5a177314..0000000000
--- a/sources/tech/20200222 How to install TT-RSS on a Raspberry Pi.md
+++ /dev/null
@@ -1,245 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to install TT-RSS on a Raspberry Pi)
-[#]: via: (https://opensource.com/article/20/2/ttrss-raspberry-pi)
-[#]: author: (Patrick H. Mullins https://opensource.com/users/pmullins)
-
-How to install TT-RSS on a Raspberry Pi
-======
-Read your news feeds while keeping your privacy intact with Tiny Tiny
-RSS.
-![Raspberries with pi symbol overlay][1]
-
-[Tiny Tiny RSS][2] (TT-RSS) is a free and open source web-based news feed (RSS/Atom) reader and aggregator. It's ideally suited to those who are privacy-focused and still rely on RSS for their daily news. Tiny Tiny RSS is self-hosted software, so you have 100% control of the server, your data, and your overall privacy. It also supports a wide range of plugins, add-ons, and themes, Want a dark mode interface? No problem. Want to filter your incoming news based on keywords? TT-RSS has you covered there, as well.
-
-![Tiny Tiny RSS screenshot][3]
-
-Now that you know what TT-RSS is and why you may want to use it, I'll explain everything you need to know about installing it on a Raspberry Pi or a Debian 10 server.
-
-### Install and configure TT-RSS
-
-To install TT-RSS on a Raspberry Pi, you must also install and configure the latest version of PHP (7.3 as of this writing), PostgreSQL for the database backend, the Nginx web server, Git, and finally, TT-RSS.
-
-#### 1\. Install PHP 7
-
-Installing PHP 7 is, by far, the most involved part of this process. Thankfully, it's not as difficult as it might appear. Start by installing the following support packages:
-
-
-```
-`$ sudo apt install -y ca-certificates apt-transport-https`
-```
-
-Now, add the repository PGP key:
-
-
-```
-`$ wget -q https://packages.sury.org/php/apt.gpg -O- | sudo apt-key add -`
-```
-
-Next, add the PHP repository to your apt sources:
-
-
-```
-`$ echo "deb https://packages.sury.org/php/ buster main" | sudo tee /etc/apt/sources.list.d/php.list`
-```
-
-Then update your repository index:
-
-
-```
-`$ sudo apt update`
-```
-
-Finally, install PHP 7.3 (or the latest version) and some common components:
-
-
-```
-`$ sudo apt install -y php7.3 php7.3-cli php7.3-fpm php7.3-opcache php7.3-curl php7.3-mbstring php7.3-pgsql php7.3-zip php7.3-xml php7.3-gd php7.3-intl`
-```
-
-The command above assumes you're using PostgreSQL as your database backend and installs **php7.3-pgsql**. If you'd rather use MySQL or MariaDB, you can easily change this to **php7.3-mysql**.
-
-Next, verify that PHP is installed and running on your Raspberry Pi:
-
-
-```
-`$ php -v`
-```
-
-Now it's time to install and configure the webserver.
-
-#### 2\. Install Nginx
-
-Nginx can be installed via apt with:
-
-
-```
-`$ sudo apt install -y nginx`
-```
-
-Modify the default Nginx virtual host configuration so that the webserver will recognize PHP files and know what to do with them:
-
-
-```
-`$ sudo nano /etc/nginx/sites-available/default`
-```
-
-You can safely delete everything in the original file and replace it with:
-
-
-```
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
-
- root /var/www/html;
- index index.html index.htm index.php;
- server_name _;
-
- location / {
- try_files $uri $uri/ =404;
- }
-
- location ~ \\.php$ {
- include snippets/fastcgi-php.conf;
- fastcgi_pass unix:/run/php/php7.3-fpm.sock;
- }
-
-}
-```
-
-Use **Ctrl+O** to save your new configuration file and then **Ctrl+X** to exit Nano. You can test your new configuration with:
-
-
-```
-`$ nginx -t`
-```
-
-If there are no errors, restart the Nginx service:
-
-
-```
-`$ systemctl restart nginx`
-```
-
-#### 3\. Install PostgreSQL
-
-Next up is installing the database server. Installing PostgreSQL on the Raspberry Pi is super easy:
-
-
-```
-`$ sudo apt install -y postgresql postgresql-client postgis`
-```
-
-Check to see if the database server was successfully installed by entering:
-
-
-```
-`$ psql --version`
-```
-
-#### 4\. Create the Tiny Tiny RSS database
-
-Before you can do anything else, you need to create a database that the TT-RSS software will use to store data. First, log into the PostgreSQL server:
-
-
-```
-`sudo -u postgres psql`
-```
-
-Next, create a new user and assign a password:
-
-
-```
-`CREATE USER username WITH PASSWORD 'your_password' VALID UNTIL 'infinity';`
-```
-
-Then create the database that will be used by TT-RSS:
-
-
-```
-`CREATE DATABASE tinyrss;`
-```
-
-Finally, grant full permissions to the new user:
-
-
-```
-`GRANT ALL PRIVILEGES ON DATABASE tinyrss to user_name;`
-```
-
-That's it for the database. You can exit the **psql** app by typing **\q**.
-
-#### 5\. Install Git
-
-Installing TT-RSS requires Git, so install Git with:
-
-
-```
-`$ sudo apt install git -y`
-```
-
-Now, change directory to wherever Nginx serves web pages:
-
-
-```
-`$ cd /var/www/html`
-```
-
-Then download the latest source for TT-RSS:
-
-
-```
-`$ git clone https://git.tt-rss.org/fox/tt-rss.git tt-rss`
-```
-
-Note that this process creates a new **tt-rss** folder.
-
-#### 6\. Install and configure Tiny Tiny RSS
-
-It's finally time to install and configure your new TT-RSS server. First, verify that you can open **** in a web browser. If you get a **403 Forbidden** error, your permissions are not set properly on the **/var/www/html** folder. The following will usually fix this issue:
-
-
-```
-`$ chmod 755 /var/www/html/ -v`
-```
-
-If everything goes as planned, you'll see the TT-RSS Installer page, and it will ask you for some database information. Just tell it the database username and password that you created earlier; the database name; **localhost** for the hostname; and **5432** for the port.
-
-Click **Test Configuration** to continue. If all went well, you should see a red button labeled **Initialize Database.** Click on it to begin the installation. Once finished, you'll have a configuration file that you can copy and save as **config.php** in the TT-RSS directory.
-
-After finishing with the installer, open your TT-RSS installation at **** and log in with the default credentials (username: **admin**, password: **password**). The system will recommend that you change the admin password as soon as you log in. I highly recommend that you follow that advice and change it as soon as possible.
-
-### Set up TT-RSS
-
-If all went well, you can start using TT-RSS right away. It's recommended that you create a new non-admin user, log in as the new user, and start importing your feeds, subscribing, and configuring it as you see fit.
-
-Finally, and this is super important, don't forget to read the [Updating Feeds][4] section on TT-RSS's wiki. It describes how to create a simple systemd service that will update your feeds. If you skip this step, your RSS feeds will not update automatically.
-
-### Conclusion
-
-Whew! That was a lot of work, but you did it! You now have your very own RSS aggregation server. Want to learn more about TT-RSS? I recommend checking out the official [FAQ][5], the [support][6] forum, and the detailed [installation][7] notes. Feel free to comment below if you have any questions or issues.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/ttrss-raspberry-pi
-
-作者:[Patrick H. Mullins][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/pmullins
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/life-raspberrypi_0.png?itok=Kczz87J2 (Raspberries with pi symbol overlay)
-[2]: https://tt-rss.org/
-[3]: https://opensource.com/sites/default/files/uploads/tt-rss.jpeg (Tiny Tiny RSS screenshot)
-[4]: https://tt-rss.org/wiki/UpdatingFeeds
-[5]: https://tt-rss.org/wiki/FAQ
-[6]: https://community.tt-rss.org/c/tiny-tiny-rss/support
-[7]: https://tt-rss.org/wiki/InstallationNotes
diff --git a/sources/tech/20200223 The Zen of Go.md b/sources/tech/20200223 The Zen of Go.md
new file mode 100644
index 0000000000..c4143aed32
--- /dev/null
+++ b/sources/tech/20200223 The Zen of Go.md
@@ -0,0 +1,414 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (The Zen of Go)
+[#]: via: (https://dave.cheney.net/2020/02/23/the-zen-of-go)
+[#]: author: (Dave Cheney https://dave.cheney.net/author/davecheney)
+
+The Zen of Go
+======
+
+_This article was derived from my [GopherCon Israel 2020][1] presentation. It’s also quite long. If you’d prefer a shorter version, head over to [the-zen-of-go.netlify.com][2]_.
+
+_A recording of the presentation is available on [YouTube][3]._
+
+* * *
+
+### How should I write good code?
+
+Something that I’ve been thinking about a lot recently, when reflecting on the body of my own work, is a common subtitle, _how should I write good code?_ Given nobody actively seeks to write _bad_ code, this leads to the question; _how do you know when you’ve written good Go code?_
+
+If there’s a continuum between good and bad, how to do we know what the good parts are? What are its properties, its attributes, its hallmarks, its patterns, and its idioms?
+
+### Idiomatic Go
+
+![][4]
+
+Which brings me to idiomatic Go. To say that something is idiomatic is to say that it follows the style of the time. If something is not idiomatic, it is not following the prevailing style. It is unfashionable.
+
+More importantly, to say to someone that their code is not idiomatic does not explain _why_ it’s not idiomatic. Why is this? Like all truths, the answer is found in the dictionary.
+
+> idiom (noun): a group of words established by usage as having a meaning not deducible from those of the individual words.
+
+Idioms are hallmarks of shared values. Idiomatic Go is not something you learn from a book, it’s something that you acquire by being part of a community.
+
+![][5]
+
+My concern with the mantra of idiomatic Go is, in many ways, it can be exclusionary. It’s saying “you can’t sit with us.” After all, isn’t that what we mean when critique of someone’s work as non-idiomatic? They didn’t do It right. It doesn’t look right. It doesn’t follow the style of time.
+
+I offer that idiomatic Go is not a suitable mechanism for teaching how to write good Go code because it is defined, fundamentally, by telling someone they did it wrong. Wouldn’t it be better if the advice we gave didn’t alienate the author right at the point they were most willing to accept it?
+
+### Proverbs
+
+Stepping away problematic idioms, what other cultural artefacts do Gophers have? Perhaps we can turn to Rob Pike’s wonderful [Go Proverbs][6]. Are these suitable teaching tools? Will these tell newcomers how to write good Go code?
+
+In general, I don’t think so. This is not to dismiss Pike’s work, it is just that the Go Proverbs, like Segoe Kensaku’s original, are observations, not statements of value. Again, the dictionary comes to the rescue:
+
+> proverb (noun): a short, well-known pithy saying, stating a general truth or piece of advice.
+
+The goal of the Go Proverbs are to reveal a deeper truth about the design of the language, but how useful is advice like the _empty interface says nothing_ to a novice from a language that doesn’t have structural typing?
+
+It’s important to recognise that, in a growing community, at any time the people learning Go far outnumber those who claim to have mastered the language. Thus proverbs are perhaps not the best teaching tool in this scenario.
+
+### Engineering Values
+
+Dan Luu found [an old presentation][7] by Mark Lucovsky about the engineering culture of the windows team around the windows NT-windows 2000 timeframe. The reason I mention it is Lukovsky’s description of a culture as a common way of evaluating designs and making tradeoffs.
+
+![][8]
+
+There are many ways of discussing culture, but with respect to an engineering culture Lucovsky’s description is apt. The central idea is _values guide decisions in an unknown design space_. The values of the NT team were; portability, reliability, security, and extensibility. Engineering values are, crudely translated, the way things are done around here.
+
+### Go’s values
+
+What are the explicit values of Go? What are the core beliefs or philosophy that define the way a Go programmer interprets the world? How are they promulgated? How are they taught? How are they enforced? How do they change over time?
+
+How will you, as a newly minted Go programmer, inculcate the engineering values of Go? Or, how will you, a seasoned Go professional promulgate your values to a future generations? And just so we’re clear, this process of knowledge transfer is not optional. Without new blood and new ideas, our community become myopic and wither.
+
+#### The values of other languages
+
+To set the scene for what I’m getting at we can look to other languages we see examples of their engineering values.
+
+For example, C++ (and by extension Rust) believe that a programmer _should not have to pay for a feature they do not use_. If a program does not use some computationally expensive feature of the language, then it shouldn’t be forced to shoulder the cost of that feature. This value extends from the language, to its standard library, and is used as a yardstick for judging the design of all code written in C++.
+
+In Java, and Ruby, and Smalltalk, the core value that _everything is an object_ drives the design of programs around message passing, information hiding, and polymorphism. Designs that shoehorn a procedural style, or even a functional style, into these languages are considered to be wrong–or as Gophers would say, non idiomatic.
+
+Turning to our own community, what are the engineering values that bind Go programmers? Discourse in our community is often fractious, so deriving a set of values from first principles would be a formidable challenge. Consensus is critical, but exponentially more difficult as the number of contributors to the discussion increases. But what if someone had done the hard work for us.
+
+### The Zen of ~~Python~~ Go
+
+Several decades ago Tim Peters sat down and penned _[PEP-20][9]_, the Zen of Python. Peters’ attempted to document the engineering values that he saw Guido van Rossum apply in his role as BDFL for Python.
+
+For the remainder of this article, I’m going to look towards the Zen of Python and ask, is there anything that can inform the engineering values of Go programmers?
+
+### A good package starts with a good name
+
+Let’s start with something spicy,
+
+> “Namespaces are one honking great idea–let’s do more of those!”
+
+The Zen of Python, Item 19
+
+This is pretty unequivocal, Python programmers should use namespaces. Lots of them.
+
+In Go parlance a namespace is a package. I doubt there is any question that grouping things into packages is good for design and potentially reuse. But there might be some confusion, especially if you’re coming with a decade of experience in another language, about the right way to do this.
+
+In Go each package should have a purpose, and the best way to know a package’s purpose is by its name—a noun. A package’s name describes what it provides. So too reinterpret Peters’ words, every Go package should have a single purpose.
+
+This is not a new idea, [I’ve been saying this a while][10], but why should you do this rather than approach where packages are used for fine grained taxonomy? Why, because change.
+
+> “Design is the art of arranging code to work today, and be changeable forever.”
+
+Sandi Metz
+
+Change is the name of the game we’re in. What we do as programmers is manage change. When we do that well we call it design, or architecture. When we do it badly we call it technical debt, or legacy code.
+
+If you are writing a program that works perfectly, one time, for one fixed set of inputs then nobody cares if the code is good or bad because ultimately the output of the program is all the business cares about.
+
+But this is _never_ true. Software has bugs, requirements change, inputs change, and very few programs are written solely to be executed once, thus your program _will_ change over time. Maybe it’s you who’ll be tasked with this, more likely it will be someone else, but someone has to change that code. Someone has to maintain that code.
+
+So, how can we make it easy to for programs to change? Interfaces everywhere? Make everything mockable? Pernicious dependency injection? Well, maybe, for some classes of programs, but not many, those techniques will be useful. However, for the majority of programs, designing something to be flexible up front is over engineering.
+
+What if, instead, we take a position that rather than enhancing components, we replace them. Then the best way to know when something needs to be replaced, is when it doesn’t do what it says on the tin.
+
+A good package starts with choosing a good name. Think of your package’s name as an elevator pitch, using just one word, to describe what it provides. When the name no longer matches the requirement, find a replacement.
+
+### Simplicity matters
+
+> “Simple is better than complex.”
+
+The Zen of Python, Item 3
+
+PEP-20 says simple is better than complex, I couldn’t agree more. A couple of years ago I made this tweet;
+
+> Most programming languages start out aiming to be simple, but end up just settling for being powerful.
+>
+> — Dave Cheney (@davecheney) [December 2, 2014][11]
+
+My observation, at least at the time, was that I couldn’t think of a language introduced in my life time that didn’t purport to be simple. Each new language offered as a justification, and an enticement, their inherent simplicity. But as I researched, I found that simplicity was not a core value of the many of the languages considered Go’s contemporaries. [1][12] Maybe this is just a cheap shot, but could it be that either these languages aren’t simple, or they don’t _think_ of themselves as being simple. They don’t consider simplicity to be a core value.
+
+Call me old fashioned, but when did being simple fall out of style? Why does the commercial software development industry continually, gleefully, forget this fundamental truth?
+
+> “There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”
+
+C. A. R. Hoare, The Emperor’s Old Clothes, 1980 Turing Award Lecture
+
+Simple does not mean easy, we know that. Often it is more work to make something simple to use, than easy to build.
+
+> “Simplicity is prerequisite for reliability.”
+
+Edsger W Dijkstra, EWD498, 18 June 1975
+
+Why should we strive for simplicity? Why is important that Go programs be simple? Simple doesn’t mean crude, it means readable and maintainable. Simple doesn’t mean unsophisticated, it means reliable, relatable, and understandable.
+
+> “Controlling complexity is the essence of computer programming.”
+
+Brian W. Kernighan, _Software Tools_ (1976)
+
+Whether Python abides by its mantra of simplicity is a matter for debate, but Go holds simplicity as a core value. I think that we can all agree that when it comes to Go, simple code is preferable to clever code.
+
+### Avoid package level state
+
+> “Explicit is better than implicit.”
+
+_The Zen of Python, Item_ 2
+
+This is a place where I think Peters’ was more aspirational than factual. Many things in Python are not explicit; decorators, dunder methods, and so on. Without doubt they are powerful, there’s a reason those features exists. Each feature is something someone cared enough about to do the work to implement it, especially the complicated ones. But heavy use of those features makes is harder for the reader to predict the cost of an operation.
+
+The good news is we have a choice, as Go programmers, to choose to make our code explicit. Explicit could mean many things, perhaps you may be thinking explicit is just a nice way of saying bureaucratic and long winded, but that’s a superficial interpretation. It’s a misnomer to focus only on the syntax on the page, to fret about line lengths and DRYing up expressions. The more valuable, in my opinon, place to be explicit are to do with coupling and with state.
+
+Coupling is a measure of the amount one thing depends on another. If two things are tightly coupled, they move together. An action that affects one is directly reflected in another. Imagine a train, each carriage joined–ironically the correct word is coupled–together; where the engine goes, the carriages follow.
+
+Another way to describe coupling is the word cohesion. Cohesion measures how well two things naturally belong together. We talk about a cohesive argument, or a cohesive team; all their parts fit together as if they were designed that way.
+
+Why does coupling matter? Because just like trains, when you need to change a piece of code, all the code that is tightly coupled to it must change. A prime example, someone release a new version of their API and now your code doesn’t compile.
+
+APIs are an unavoidable source of coupling but there are more insidious forms of coupling. Clearly everyone knows that if an API’s signature changes the data passing into and out of that call changes. It’s right there in the signature of the function; I take values of these types and return values of other types. But what if the API passed data another way? What if every time you called this API the result was based on the previous time you called that API even though you didn’t change your parameters.
+
+This is state, and management of state is _the_ problem in computer science.
+
+```
+package counter
+
+var count int
+
+func Increment(n int) int {
+ count += n
+ return count
+}
+```
+
+Suppose we have this simple `counter` package. You can call `Increment` to increment the counter, you can even get the value back if you `Increment` with a value of zero.
+
+Suppose you had to test this code, how would you reset the counter after each test? Suppose you wanted to run those tests in parallel, could you do it? Now suppose that you wanted to count more than one thing per program, could you do it?
+
+No, of course not. Clearly the answer is to encapsulate the `count` variable in a type.
+
+```
+package counter
+
+type Counter struct {
+ count int
+}
+
+func (c *Counter) Increment(n int) int {
+ c.count += n
+ return c.count
+}
+```
+
+Now imagine that this problem isn’t restricted to just counters, but your applications main business logic. Can you test it in isolation? Can you test it in parallel? Can you use more than one instance at a time? If the answer those question is _no_, the reason is package level state.
+
+Avoid package level state. Reduce coupling and spooky action at a distance by providing the dependencies a type needs as fields on that type rather than using package variables.
+
+### Plan for failure, not success
+
+> “Errors should never pass silently.”
+
+_The Zen of Python, Item 1_0
+
+It’s been said of languages that favour exception handling follow the Samurai principle; _return victorious or not at all_. In exception based languages functions only return valid results. If they don’t succeed then control flow takes an entirely different path.
+
+Unchecked exceptions are clearly an unsafe model to program in. How can you possibly write code that is robust in the presence of errors when you don’t know which statements could throw an exception? Java tried to make exceptions safer by introducing the notion of a checked exception which, to the best of my knowledge, has not been repeated in another mainstream language. There are plenty of languages which use exceptions but they all, with the singular exception of Java, do so in the unchecked variety.
+
+Obviously Go chose a different path. Go programmers believe that robust programs are composed from pieces that handle the failure cases _before_ they handle the happy path. In the space that Go was designed for; server programs, multi threaded programs, programs that handle input over the network, dealing with unexpected data, timeouts, connection failures and corrupted data must be front and centre of the programmer’s mind if they are to produce robust programs.
+
+> “I think that error handling should be explicit, this should be a core value of the language.”
+
+Peter Bourgon, [GoTime #91][13]
+
+I want to echo Peter’s assertion, as it was the impetus for this article. I think so much of the success of Go is due to the explicit way errors are handled. Go programmers thinks about the failure case first. We solve the “what if…” case first. This leads to programs where failures are handled at the point of writing, rather than the point they occur in production.
+
+The verbosity of
+
+```
+if err != nil {
+ return err
+}
+```
+
+is outweighed by the value of deliberately handling each failure condition at the point at which they occur. Key to this is the cultural value of handling each and every error explicitly.
+
+### Return early rather than nesting deeply
+
+> “Flat is better than nested.”
+
+The Zen of Python, Item 5
+
+This is sage advice coming from a language where indentation is the primary form of control flow. How can we interpret this advice in terms of Go? `gofmt` controls the overall whitespace of a Go program so there’s not thing doing there.
+
+I wrote earlier about package names, and there is probably some advice here about avoiding a complicated package hierarchy. In my experience the more a programmer tries to subdivide and taxonimise their Go codebase the more they risk hitting the dead end that is package import loops.
+
+I think the best application of item 5’s advice is the control flow _within_ a function. Simply put, avoid control flow that requires deep indentation.
+
+> “Line of sight is a straight line along which an observer has unobstructed vision.”
+
+May Ryer, [Code: Align the happy path to the left edge][14]
+
+Mat Ryer describes this idea as line of sight coding. Light of sight coding means things like:
+
+ * Using guard clauses to return early if a precondition is not met.
+ * Placing the successful return statement at the end of the function rather than inside a conditional block.
+ * Reducing the overall indentation level of the function by extracting functions and methods.
+
+
+
+Key to this advice is the thing that you care about, the thing that the function does, is never in danger of sliding out of sight to the right of your screen. This style has a bonus side effect that you’ll avoid pointless arguments about line lengths on your team.
+
+Every time you indent you add another precondition to the programmers stack, consuming one of their 7 ±2 short term memory slots. Rather than nesting deeply, keep the successful path of the function close to the left hand side of your screen.
+
+### If you think it’s slow, prove it with a benchmark
+
+> “In the face of ambiguity, refuse the temptation to guess.”
+
+The Zen of Python, Item 12
+
+Programming is based on mathematics and logic, two concepts which rarely involve the element of chance. But there are many things we, as programmers, guess about every day. What does this variable do? What does this parameter do? What happens if I pass `nil` here? What happens if I call `Register` twice? There’s actually a lot of guesswork in modern programming, especially when it comes to using libraries you didn’t write.
+
+> “APIs should be easy to use and hard to misuse.”
+
+Josh Bloch
+
+One of the best ways I know to help a programmer avoid having to guess is to, when building an API, [focus on the default use case][15]. Make it as easy as you can for the caller to do the most common thing. However, I’ve written and talked a lot about API design in the past, so instead my interpretation of item 12 is; _don’t guess about performance_.
+
+Despite how you may feel about Knuth’s advice, one of the drivers of Go’s success is its efficient execution. You can write efficient programs in Go and thus people _will_ choose Go because of this. There are a lot of misconceptions about performance, so my request is, when you’re looking to performance tune your code or you’re facing some dogmatic advice like defer is slow, CGO is expensive, or always use atomics not mutexes, don’t guess.
+
+Don’t complicate your code because of outdated dogma, and, if you think something is slow, first prove it with a benchmark. Go has excellent benchmarking and profiling tools that come in the distribution for free. Use them to find your bottlenecks.
+
+### Before you launch a goroutine, know when it will stop
+
+At this point I think I think I’ve mined the valuable points from PEP-20 and possibly stretched its reinterpretation beyond the point of good taste. I think that’s fine, because although this was a useful rhetorical device, ultimately we are talking about two different languages.
+
+> “You type g o, a space, and then a function call. Three keystrokes, you can’t make it much shorter than that. Three keystrokes and you’ve just started a sub process.”
+
+Rob Pike, [Simplicity is Complicated][16], dotGo 2015
+
+The next two suggestions I’ll dedicate to goroutines. Goroutines are the signature feature of the language, our answer for first class concurrency. They are so easy to use, just put the word `go` in front of the statement and you’ve launched that function asynchronously. It’s so simple, no threads, no stack sizes, no thread pool executors, no ID’s, no tracking completion status.
+
+Goroutines are cheap. Because of the runtime’s ability to multiplex goroutines onto a small pool of threads (which you don’t have to manage), hundreds of thousands, millions of goroutines are easily accommodated. This opens up designs that would be not be practical under competing concurrency models like threads or evented callbacks.
+
+But as cheap as goroutines are, they’re not free. At a minimum there’s a few kilobytes for their stack, which, when you’re getting up into the 10^6 goroutines, does start to add up. This is not to say you shouldn’t use millions of goroutines if that is what the design calls for, but when you do, it’s critical that you keep track of them because 10^6 of anything can consume a non trivial amount of resources in aggregate.
+
+Goroutines are the key to resource ownership in Go. To be useful a goroutine has to do something, and that means it almost always holds reference to, or ownership of, a resource; a lock, a network connection, a buffer with data, the sending end of a channel. While that goroutine is alive, the lock is held, the network connection remains open, the buffer retained and the receivers of the channel will continue to wait for more data.
+
+The simplest way to free those resources is to tie them to the lifetime of the goroutine–when the goroutine exits, the resource has been freed. So while it’s near trivial to start a goroutine, before you write those three letters, g o and a space, make sure you have an answer to these questions:
+
+ * **Under what condition will a goroutine stop?** Go doesn’t have a way to tell a goroutine to exit. There is no stop or kill function, for good reason. If we cannot command a goroutine to stop, we must instead ask it, politely. Almost always this comes down to a channel operation. Range loops over a channel exit when the channel is closed. A channel will become selectable if it is closed. The signal from one goroutine to another is best expressed as a closed channel.
+ * **What is required for that condition to arise?** If channels are both the vehicle to communicate between goroutines and the mechanism for them to signal completion, the next question to the programmer becomes, who will close the channel, when will that happen?
+ * **What signal will you use to know the goroutine has stopped?** When you signal a goroutine to stop, that stopping will happen at some time in the future relative to the goroutine’s frame of reference. It might happen quickly in terms of human perception, but computers execute billions of instructions every second, and from the point of view of each goroutine, their execution of instructions is unsynchronised. The solution is often to use a channel to signal back or a waitgroup where a fan in approach is needed.
+
+
+
+### Leave concurrency to the caller
+
+It is likely that in any serious Go program you write there will be concurrency involved. This raises the problem, many of the libraries and code that we write fall into this a one goroutine per connection, or worker pattern. How will you manage the lifetime of those goroutines?
+
+`net/http` is a prime example. Shutting down the server owning the listening socket is relatively straight forward, but what about a goroutines spawned from that accepting socket? `net/http` does provide a context object inside the request object which can be used to signal–to code that is listening–that the request should be canceled, thereby terminating the goroutine, however it is less clear how to know when all of these things have been done. It’s one thing to call `context.Cancel`, its another to know that the cancellation has completed.[2][17]
+
+The point I want to make about `net/http` is that its a counter example to good practice. Because each connection is handled by a goroutine spawned inside the `net/http.Server` type, the program, living outside the `net/http` package, does not have an ability to control the goroutines spawned for the accepting socket.
+
+This is an area of design that is still evolving, with efforts like go-kit’s `run.Group` and the Go team’s [`ErrGroup`][18] which provide a framework to execute, cancel and wait on functions run asynchronously.
+
+The bigger design maxim here is for library writers, or anyone writing code that could be run asynchronously, leave the responsibility of starting to goroutine to your caller. Let the caller choose how they want to start, track, and wait on your functions execution.
+
+### Write tests to lock in the behaviour of your package’s API
+
+Perhaps you were hoping to read an article from me where I didn’t rant about testing. Sadly, today is not that day.
+
+Your tests are the contract about what your software does and does not do. Unit tests at the package level should lock in the behaviour of the package’s API. They describe, in code, what the package promises to do. If there is a unit test for each input permutation, you have defined the contract for what the code will do _in code_, not documentation.
+
+This is a contract you can assert as simply as typing `go test`. At any stage, you can _know_ with a high degree of confidence, that the behaviour people relied on before your change continues to function after your change.
+
+Tests lock in api behaviour. Any change that adds, modifies or removes a public api must include changes to its tests.
+
+### Moderation is a virtue
+
+Go is a simple language, only 25 keywords. In some ways this makes the features that are built into the language stand out. Equally these are the features that the language sells itself on, lightweight concurrency, structural typing.
+
+I think all of us have experienced the confusion that comes from trying to use all of Go’s features at once. Who was so excited to use channels that they used them as much as they could, as often as they could? Personally for me I found the result was hard to test, fragile, and ultimately overcomplicated. Am I alone?
+
+I had the same experience with goroutines, attempting to break the work into tiny units I created a hard to manage hurd of Goroutines and ultimately missed the observation that most of my goroutines were always blocked waiting for their predecessor– the code was ultimately sequential and I had added a lot of complexity for little real world benefit. Who has experienced something like this?
+
+I had the same experience with embedding. Initially I mistook it for inheritance. Then later I recreated the fragile base class problem by composing complicated types, which already had several responsibilities, into more complicated mega types.
+
+This is potentially the least actionable piece of advice, but one I think is important enough to mention. The advice is always the same, all things in moderation, and Go’s features are no exception. If you can, don’t reach for a goroutine, or a channel, or embed a struct, anonymous functions, going overboard with packages, interfaces for everything, instead prefer simpler approach rather than the clever approach.
+
+### Maintainability counts
+
+I want to close with one final item from PEP-20,
+
+> “Readability Counts.”
+
+The Zen of Python, Item 7
+
+So much has been said, about the importance of readability, not just in Go, but all programming languages. People like me who stand on stages advocating for Go use words like simplicity, readability, clarity, productivity, but ultimately they are all synonyms for one word–_maintainability_.
+
+The real goal is to write maintainable code. Code that can live on after the original author. Code that can exist not just as a point in time investment, but as a foundation for future value. It’s not that readability doesn’t matter, maintainability matters _more_.
+
+Go is not a language that optimises for clever one liners. Go is not a language which optimises for the least number of lines in a program. We’re not optimising for the size of the source code on disk, nor how long it takes to type the program into an editor. Rather, we want to optimise our code to be clear to the reader. Because its the reader who’s going to have to maintain this code.
+
+If you’re writing a program for yourself, maybe it only has to run once, or you’re the only person who’ll ever see it, then do what ever works for you. But if this is a piece of software that more than one person will contribute to, or that will be used by people over a long enough time that requirements, features, or the environment it runs in may change, then your goal must be for your program to be maintainable. If software cannot be maintained, then it will be rewritten; and that could be the last time your company will invest in Go.
+
+Can the thing you worked hard to build be maintained after you’re gone? What can you do today to make it easier for someone to maintain your code tomorrow?
+
+##### [the-zen-of-go.netlify.com][2]
+
+ 1. This part of the talk had several screenshots of the landing pages for the websites for [Ruby][19], [Swift][20], [Elm][21], [Go][22], [NodeJS][23], [Python][24], [Rust][25], highlighting how the language described itself.[][26]
+ 2. I tend to pick on `net/http` a lot, and this is not because it is bad, in fact it is the opposite, it is the most successful, oldest, most used API in the Go codebase. And because of that its design, evolution, and shortcoming have been thoroughly picked over. Think of this as flattery, not criticism.[][27]
+
+
+
+#### Related posts:
+
+ 1. [Never start a goroutine without knowing how it will stop][28]
+ 2. [Simplicity Debt][29]
+ 3. [Curious Channels][30]
+ 4. [Let’s talk about logging][31]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://dave.cheney.net/2020/02/23/the-zen-of-go
+
+作者:[Dave Cheney][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://dave.cheney.net/author/davecheney
+[b]: https://github.com/lujun9972
+[1]: https://www.gophercon.org.il
+[2]: https://the-zen-of-go.netlify.com
+[3]: https://www.youtube.com/watch?v=yd_rtwYaXps
+[4]: https://dave.cheney.net/wp-content/uploads/2020/02/1011226.jpg
+[5]: https://dave.cheney.net/wp-content/uploads/2020/02/mean-girls-you-cant-sit-with-us-main.jpg
+[6]: http://go-proverbs.github.io
+[7]: https://danluu.com/microsoft-culture/
+[8]: https://dave.cheney.net/wp-content/uploads/2020/02/Lucovsky.001.jpeg
+[9]: https://www.python.org/dev/peps/pep-0020/
+[10]: https://dave.cheney.net/2019/01/08/avoid-package-names-like-base-util-or-common
+[11]: https://twitter.com/davecheney/status/539576755254611968?ref_src=twsrc%5Etfw
+[12]: tmp.iUoDiQyXMU#easy-footnote-bottom-1-3936 (This part of the talk had several screenshots of the landing pages for the websites for Ruby, Swift, Elm, Go, NodeJS, Python, Rust, highlighting how the language described itself.)
+[13]: https://changelog.com/gotime/91
+[14]: https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88
+[15]: http://sweng.the-davies.net/Home/rustys-api-design-manifesto
+[16]: https://www.youtube.com/watch?v=rFejpH_tAHM
+[17]: tmp.iUoDiQyXMU#easy-footnote-bottom-2-3936 (I tend to pick on net/http a lot, and this is not because it is bad, in fact it is the opposite, it is the most successful, oldest, most used API in the Go codebase. And because of that its design, evolution, and shortcoming have been thoroughly picked over. Think of this as flattery, not criticism.)
+[18]: https://godoc.org/golang.org/x/sync/errgroup
+[19]: https://www.ruby-lang.org/en/
+[20]: https://swift.org
+[21]: https://elm-lang.org
+[22]: https://golang.org
+[23]: https://nodejs.org/en/
+[24]: https://www.python.org
+[25]: https://www.rust-lang.org
+[26]: tmp.iUoDiQyXMU#easy-footnote-1-3936
+[27]: tmp.iUoDiQyXMU#easy-footnote-2-3936
+[28]: https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop (Never start a goroutine without knowing how it will stop)
+[29]: https://dave.cheney.net/2017/06/15/simplicity-debt (Simplicity Debt)
+[30]: https://dave.cheney.net/2013/04/30/curious-channels (Curious Channels)
+[31]: https://dave.cheney.net/2015/11/05/lets-talk-about-logging (Let’s talk about logging)
diff --git a/sources/tech/20200228 Getting started with Linux firewalls.md b/sources/tech/20200228 Getting started with Linux firewalls.md
deleted file mode 100644
index c77d60b618..0000000000
--- a/sources/tech/20200228 Getting started with Linux firewalls.md
+++ /dev/null
@@ -1,128 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Getting started with Linux firewalls)
-[#]: via: (https://opensource.com/article/20/2/firewall-cheat-sheet)
-[#]: author: (Seth Kenlon https://opensource.com/users/seth)
-
-Getting started with Linux firewalls
-======
-A firewall is your computer's first line of defense against network
-intrusion. Download our cheat sheet to make sure you're secure.
-![Cheat Sheet cover image][1]
-
-A sensible firewall is your computer's first line of defense against network intrusion. When you're at home, you're probably behind a firewall built into the router supplied by your internet service provider. When you're away from home, though, the only firewall you have is the one running on your computer, so it's important to configure and control the firewall on your Linux computer. If you run a Linux server, it's just as important to know how to manage your firewall so that you can protect it from unwanted traffic both locally and remotely.
-
-### Install a firewall
-
-Many Linux distributions ship with a firewall already installed, and traditionally that was **iptables**. It is extremely effective and customizable, but it can be complex to configure. Luckily, developers have produced several frontends to help users control their firewall without writing lengthy iptables rules.
-
-On Fedora, CentOS, Red Hat, and similar distributions, the firewall software installed by default is **firewalld**, which is configured and controlled with the **firewall-cmd** command. On Debian and most other distributions, firewalld is available to install from your software repository. Ubuntu ships with the Uncomplicated Firewall (ufw), so to use firewalld, you must enable the **universe** repository:
-
-
-```
-$ sudo add-apt-repository universe
-$ sudo apt install firewalld
-```
-
-You must also deactivate ufw:
-
-
-```
-`$ sudo systemctl disable ufw`
-```
-
-There's no reason _not_ to use ufw. It's an excellent firewall frontend. However, this article focuses on firewalld because of its wide availability and integration into systemd, which is shipped with nearly every distribution.
-
-Regardless of your distribution, for a firewall to be effective, it must be active, and it should be loaded at boot time:
-
-
-```
-`$ sudo systemctl enable --now firewalld`
-```
-
-### Understanding firewall zones
-
-Firewalld aims to make firewall configuration as simple as possible. It does this by establishing _zones_. A zone is a set of sensible, common rules that suit the everyday needs of most users. There are nine by default:
-
- * **trusted:** All network connections are accepted. This is the least paranoid firewall setting and should only be used in a trusted environment, such as a test lab or in a family home where everyone on the local network is known to be friendly.
- * **home, work, internal:** In these three zones, most incoming connections are accepted. They each exclude traffic on ports that usually expect no activity. Any of them is a reasonable setting for use in a home setting where there is no reason to expect network traffic to obscure ports, and you generally trust the other users on the network.
- * **public:** For use in public areas. This is a paranoid setting, intended for times when you do not trust other computers on the network. Only selected common and mostly safe incoming connections are accepted.
- * **dmz:** DMZ stands for demilitarized zone. This zone is intended for computers that are publically accessible, located on an organization's external network with limited access to the internal network. For personal computers, this is usually not a useful zone, but it is an important option for certain types of servers.
- * **external:** For use on external networks with masquerading enabled (meaning the addresses of your private network are mapped to and hidden behind a public IP address). Similar to the dmz zone, only selected incoming connections are accepted, including SSH.
- * **block:** Only network connections initiated within this system are possible, and all incoming network connections are rejected with an **icmp-host-prohibited** message. This is an extremely paranoid setting and is an important option for certain types of servers or personal computers in an untrusted or hostile environment.
- * **drop:** Any and all incoming network packets are dropped with no reply. Only outgoing network connections are possible. The only setting more paranoid than this one is turning off your WiFi and unplugging your Ethernet cable.
-
-
-
-You can read about each zone and any other zones defined by your distribution or sysadmin by looking at the configuration files in **/usr/lib/firewalld/zones**. For instance, here's the FedoraWorkstation zone that ships with Fedora 31:
-
-
-```
-$ cat /usr/lib/firewalld/zones/FedoraWorkstation.xml
-<?xml version="1.0" encoding="utf-8"?>
-<zone>
- <short>Fedora Workstation</short>
- <description>Unsolicited incoming network packets are rejected from port 1 to 1024, except for select network services. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
- <service name="dhcpv6-client"/>
- <service name="ssh"/>
- <service name="samba-client"/>
- <port protocol="udp" port="1025-65535"/>
- <port protocol="tcp" port="1025-65535"/>
-</zone>
-```
-
-### Getting your current zone
-
-You can see what zone you're in at any time with the **\--get-active-zones** option:
-
-
-```
-`$ sudo firewall-cmd --get-active-zones`
-```
-
-In response, you receive the name of the active zone along with the network interface assigned to it. On a laptop, that usually means you have a WiFi card in the default zone:
-
-
-```
-FedoraWorkstation
- interfaces: wlp61s0
-```
-
-### Change your current zone
-
-To change your zone, reassign your network interface to a different zone. For instance, to change the example **wlp61s0** card to the public zone:
-
-
-```
-$ sudo firewall-cmd --change-interface=wlp61s0 \
-\--zone=public
-```
-
-You can change the active zone for an interface any time you please and for any reason—whether you're going out to a café and feel the need to increase your laptop's security policy, or you're going to work and need to open up some ports to get on the intranet, or for any other reason. The options for **firewall-cmd** auto-complete when you press the **Tab** key, so as long as you remember the keywords "change" and "zone," you can stumble through the command until you learn it by memory.
-
-### Learn more
-
-There's a lot more you can do with your firewall, including customizing existing zones, setting a default zone, and more. The more comfortable with firewalls you get, the more secure your online activities are, so we've created a [cheat sheet][2] for quick and easy reference.
-
-### Download your [firewall cheat sheet][2]
-
-David Both shares how he replaced his dedicated network firewall computer with a Raspberry Pi 2.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/2/firewall-cheat-sheet
-
-作者:[Seth Kenlon][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/seth
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coverimage_cheat_sheet.png?itok=lYkNKieP (Cheat Sheet cover image)
-[2]: https://opensource.com/downloads/firewall-cmd-cheat-sheet
diff --git a/sources/tech/20200304 Getting started with the Gutenberg editor in Drupal.md b/sources/tech/20200304 Getting started with the Gutenberg editor in Drupal.md
deleted file mode 100644
index 6050adebfa..0000000000
--- a/sources/tech/20200304 Getting started with the Gutenberg editor in Drupal.md
+++ /dev/null
@@ -1,122 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Getting started with the Gutenberg editor in Drupal)
-[#]: via: (https://opensource.com/article/20/3/gutenberg-editor-drupal)
-[#]: author: (MaciejLukianski https://opensource.com/users/maciejlukianski)
-
-Getting started with the Gutenberg editor in Drupal
-======
-Learn how to use the WYSIWYG editor, made popular in WordPress, with
-Drupal.
-![Text editor on a browser, in blue][1]
-
-Since 2017, WordPress has had a really great WYSIWYG editor in the [Gutenberg][2] plugin. But the Drupal community hasn't yet reached consensus on the best approach to the content management system's (CMS) editorial experience. But a strong new option appeared when, with a lot of community effort, [Gutenberg was integrated with Drupal][3].
-
-Previously, there were two main approaches to content creation in Drupal 8:
-
- * In the [**Paragraph-based approach**][4], content is assembled out of entities called paragraphs. Currently, approximately 100,000 websites use the Paragraphs module (according to Drupal).
- * The [**Layout-Builder approach**][5] uses an editorial tool shipped with Drupal 8.5. It is still undergoing improvements, but it is the next strong contender because it is really well integrated with the Drupal core. Stats on usage are not available since Layout Builder is part of Drupal.
-
-
-
-At the end of 2018, the Drupal community, lead by Fronkom (a Norwegian digital agency strongly focused on open source solutions), ported the WordPress Gutenberg project as a contributed module into Drupal. Let's take a look at how Gutenberg works in Drupal (including some cool Drupal-specific integrations).
-
-### Installation
-
-Installing the [Gutenberg module][6] is as straightforward as installing any Drupal module, and it has good [installation documentation][7].
-
-### Configuration
-
-Gutenberg is integrated into Drupal's default content-entity creation workflow. You can use it on any of the content types you choose, provided that the content type has at least one text area field, which is where the Gutenberg editor's output will be saved.
-
-To enable the Gutenberg project on a content type in Drupal, you have to navigate to its settings: **Structure > Content types** and, from the dropdown next to the content type where you want to use Gutenberg, click **Edit**.
-
-![Drupal settings][8]
-
-In the form that appears, scroll down and select the **Gutenberg experience** tab on the left, where you can find the settings described below. Select the **Enable Gutenberg experience** box.
-
-![Drupal Gutenberg settings][9]
-
-#### Template
-
-This is one of the cool features that is not available in WordPress out of the box. It enables you to define a template for a new page in a JSON structure. This will pre-populate all newly created articles with dummy placeholder content, which will help editors structure content correctly. In the screenshot above, I added a heading and a paragraph. Note that any double-quotes have to be escaped.
-
-#### Template lock
-
-This setting allows you to define whether users are allowed to delete the placeholder content, add new blocks, or just edit the existing, pre-populated content.
-
-#### Allowed Gutenberg and Drupal blocks
-
-This is another super-cool feature on the Drupal side of Gutenberg. Drupal allows users to create various types of blocks to design a page. For example, you could create a block with a list of the five latest blog posts, the most recent comments, or a form to collect users' emails.
-
-Gutenberg's deep integration with Drupal allows users to select which Drupal blocks are available to users while they are editing (e.g., limit embeds to YouTube) and use blocks as inline content. This is a very handy feature that allows granular control of the user experience.
-
-There's not much to choose from in a blank Drupal installation, but a live site usually has many blocks that provide various functionalities. In the screenshot below, the **Search form** Drupal block is selected.
-
-![Drupal Gutenberg blocks][10]
-
-After you finish the configuration, hit **Save content type**.
-
-### Publishing content with Drupal Gutenberg
-
-When Gutenberg is enabled for a content type, it takes over most of the editorial experience.
-
-![Drupal Gutenberg content screen][11]
-
-In the main window, you can see the dummy placeholder content I added in the Template configuration above.
-
-#### Drupal-specific options
-
-On the right-hand side, there are a few fields and settings that Drupal provides. For example, the **Title** field is a required separate field in Drupal, and therefore it is not on the main Gutenberg screen.
-
-Underneath the **Title**, there are additional settings that can vary, depending on the modules installed and options set up in Drupal. You can see **Revision log messages**, **Menu settings**, **Comment settings**, and a place to add a **URL alias**.
-
-Typically, Drupal content types are composed of several text fields, such as tags, categories, checkboxes, image fields for teasers, etc. When you enable Gutenberg for a content type, these additional fields are available in the **More settings** tab.
-
-You can now add your content—it works the same as it does in WordPress Gutenberg, with the additional option to add Drupal blocks.
-
-In the screenshot below, you can see what happens when I add some text to replace the placeholder text, a search block from Drupal, a title, tags, and a custom URL alias.
-
-![Drupal Gutenberg entering text][12]
-
-After you hit **Save**, your content will be published.
-
-![Drupal Gutenberg output][13]
-
-And that is it. It works like a charm!
-
-### Working together for better software experiences
-
-Gutenberg in Drupal works well. It is an alternative option that allows editors to control the look and feel of their websites down to the tiniest details. Adoption is growing well, with over 1,000 installations as of this writing and 50 new ones every month. The Drupal integration adds other cool features like fine-grained permissions, placeholder content, and the ability to include Drupal blocks inline, which aren't available in the WordPress plugin.
-
-It is great to see the communities of two separate projects working together to achieve the common goal of giving people better software.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/gutenberg-editor-drupal
-
-作者:[MaciejLukianski][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/maciejlukianski
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_blue_text_editor_web.png?itok=lcf-m6N7 (Text editor on a browser, in blue)
-[2]: https://wordpress.org/plugins/gutenberg/
-[3]: https://drupalgutenberg.org/
-[4]: https://www.droptica.com/blog/flexible-and-easy-content-creation-drupal-paragraphs-module/
-[5]: https://www.droptica.com/blog/layout-builder-building-drupal-8-layouts/
-[6]: https://www.drupal.org/project/gutenberg
-[7]: https://www.drupal.org/docs/8/extending-drupal-8/installing-drupal-8-modules
-[8]: https://opensource.com/sites/default/files/uploads/gutenberg_edit.png (Drupal settings)
-[9]: https://opensource.com/sites/default/files/uploads/gutenberg_settings.png (Drupal Gutenberg settings)
-[10]: https://opensource.com/sites/default/files/uploads/gutenberg_blocks.png (Drupal Gutenberg blocks)
-[11]: https://opensource.com/sites/default/files/uploads/gutenberg_contentwindow.png (Drupal Gutenberg content screen)
-[12]: https://opensource.com/sites/default/files/uploads/gutenberg_entry.png (Drupal Gutenberg entering text)
-[13]: https://opensource.com/sites/default/files/uploads/gutenberg-demo.png (Drupal Gutenberg output)
diff --git a/sources/tech/20200309 Fish - A Friendly Interactive Shell.md b/sources/tech/20200309 Fish - A Friendly Interactive Shell.md
deleted file mode 100644
index b091fea171..0000000000
--- a/sources/tech/20200309 Fish - A Friendly Interactive Shell.md
+++ /dev/null
@@ -1,194 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (geekpi)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Fish – A Friendly Interactive Shell)
-[#]: via: (https://fedoramagazine.org/fish-a-friendly-interactive-shell/)
-[#]: author: (Michal Konečný https://fedoramagazine.org/author/zlopez/)
-
-Fish – A Friendly Interactive Shell
-======
-
-![Fish — A Friendly Interactive Shell][1]
-
-Are you looking for an alternative to bash? Are you looking for something more user-friendly? Then look no further because you just found the golden fish!
-
-Fish (friendly interactive shell) is a smart and user-friendly command line shell that works on Linux, MacOS, and other operating systems. Use it for everyday work in your terminal and for scripting. Scripts written in fish are less cryptic than their equivalent bash versions.
-
-### Fish’s user-friendly features
-
- * **Suggestions**
-Fish will suggest commands that you have written before. This boosts productivity when typing same commands often.
- * **Sane scripting**
-Fish avoids using cryptic characters. This provides a clearer and friendlier syntax.
- * **Completion based on man pages**
-Fish will autocomplete parameters based on the the command’s man page.
- * **Syntax highlighting**
-Fish will highlight command syntax to make it visually friendly.
-
-
-
-### Installation
-
-#### Fedora Workstation
-
-Use the _dnf_ command to install fish:
-
-```
-$ sudo dnf install fish
-```
-
-Make fish your default shell by installing the _util-linux-user_ package and then running the _chsh_ (change shell) command with the appropriate parameters:
-
-```
-$ sudo dnf install util-linux-user
-$ chsh -s /usr/bin/fish
-```
-
-You will need to log out and back in for this change to take effect.
-
-#### Fedora Silverblue
-
-Because this is not GUI application, you will need to layer it using _rpm-ostree_. Use the following command to install fish on Fedora Silverblue:
-
-```
-$ rpm-ostree install fish
-```
-
-On Fedora Silverblue you will need to reboot your PC to switch to the new ostree image.
-
-If you want to make fish your main shell on Fedora Silverblue, the easiest way is to update the _/etc/passwd_ file. Find your user and change _/bin/bash_ to _/usr/bin/fish_.
-
-You will need [root privileges][2] to edit the _/etc/passwd_ file. Also you will need to log out and back in for this change to take effect.
-
-### Configuration
-
-The per-user configuration file for fish is _~/.config/fish/config.fish_. To make configuration changes for all users, edit _/etc/fish/config.fish_ instead.
-
-The per-user configuration file must be created manually. The installation scripts will not create _~/.config/fish/config.fish_.
-
-Here are a couple configuration examples shown alongside their bash equivalents to get you started:
-
-#### Creating aliases
-
- * _~/.bashrc_: alias ll='ls -lh'
- * _~/.config/fish/config.fish_: alias ll='ls -lh'
-
-
-
-#### Setting environment variables
-
- * _~/.bashrc_: export PATH=$PATH:~/bin
- * _~/.config/fish/config.fish_: set -gx PATH $PATH ~/bin
-
-
-
-### Working with fish
-
-When fish is configured as your default shell, the command prompt will look similar to what is shown in the below image. If you haven’t configured fish to be your default shell, just run the _fish_ command to start it in your current terminal session.
-
-![][3]
-
-As you start typing commands, you will notice the syntax highlighting:
-
-![][4]
-
-Cool, isn’t it? 🙂
-
-You will also see commands being suggested as you type. For example, start typing the previous command a second time:
-
-![][5]
-
-Notice the gray text that appears as you type. The gray text is fish suggesting the command you wrote before. To autocomplete it, just press **CTRL+F**.
-
-Get argument suggestions based on the preceding command’s man page by typing a dash (**–**) and then the **TAB** key:
-
-![][6]
-
-If you press **TAB** once, it will show you the first few suggestions (or every suggestion, if there are only a few arguments available). If you press **TAB** a second time, it will show you all suggestions. If you press **TAB** three times consecutively, it will switch to interactive mode and you can select an argument using the arrow keys.
-
-Otherwise, fish works similar to most other shells. The remaining differences are well documented. So it shouldn’t be difficult to find other features that you may be interested in.
-
-### Make fish even more powerful
-
-Make the fish even more powerful with [powerline][7]. Powerline adds command execution time, colored git status, current git branch and much more to fish’s interface.
-
-Before installing powerline for fish, you must install [Oh My Fish][8]. Oh My Fish extends fish’s core infrastructure to enable the installation of additional plugins. The easiest way to install Oh My Fish is to use the _curl_ command:
-
-```
-> curl -L https://get.oh-my.fish | fish
-```
-
-If you don’t want to pipe the installation commands directly to _curl_, see the installation section of Oh My Fish’s [README][9] for alternative installation methods.
-
-Fish’s powerline plugin is [bobthefish][7]. Bobthefish requires the _powerline-fonts_ package.
-
-**On Fedora Workstation**:
-
-```
-> sudo dnf install powerline-fonts
-```
-
-**On Fedora Silverblue**:
-
-```
-> rpm-ostree install powerline-fonts
-```
-
-On Fedora Silverblue you will have to reboot to complete the installation of the fonts.
-
-After you have installed the _powerline-fonts_ package, install _bobthefish_:
-
-```
-> omf install bobthefish
-```
-
-Now you can experience the full awesomeness of fish with powerline:
-
-![][10]
-
-### Additional resources
-
-Check out these web pages to learn even more about fish:
-
- * [Official page][11]
- * [Documentation][12]
- * [Tutorial][13]
- * [FAQ][14]
- * [Web playground][15]
- * [Mailing lists][16]
- * [GitHub][17]
-
-
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/fish-a-friendly-interactive-shell/
-
-作者:[Michal Konečný][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://fedoramagazine.org/author/zlopez/
-[b]: https://github.com/lujun9972
-[1]: https://fedoramagazine.org/wp-content/uploads/2020/03/fish-816x345.jpg
-[2]: https://fedoramagazine.org/howto-use-sudo/
-[3]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-00-35.png
-[4]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-19-24.png
-[5]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-25-31.png
-[6]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-14-58-07.png
-[7]: https://github.com/oh-my-fish/theme-bobthefish
-[8]: https://github.com/oh-my-fish/oh-my-fish
-[9]: https://github.com/oh-my-fish/oh-my-fish/blob/master/README.md#installation
-[10]: https://fedoramagazine.org/wp-content/uploads/2020/03/Screenshot-from-2020-03-03-15-38-07.png
-[11]: https://fishshell.com/
-[12]: https://fishshell.com/docs/current/index.html
-[13]: https://fishshell.com/docs/current/tutorial.html
-[14]: https://fishshell.com/docs/current/faq.html
-[15]: https://rootnroll.com/d/fish-shell/
-[16]: https://sourceforge.net/projects/fish/lists/fish-users
-[17]: https://github.com/fish-shell/fish-shell/
diff --git a/sources/tech/20200311 Directing Kubernetes traffic with Traefik.md b/sources/tech/20200311 Directing Kubernetes traffic with Traefik.md
deleted file mode 100644
index 76a457be59..0000000000
--- a/sources/tech/20200311 Directing Kubernetes traffic with Traefik.md
+++ /dev/null
@@ -1,394 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Directing Kubernetes traffic with Traefik)
-[#]: via: (https://opensource.com/article/20/3/kubernetes-traefik)
-[#]: author: (Lee Carpenter https://opensource.com/users/carpie)
-
-Directing Kubernetes traffic with Traefik
-======
-A step-by-step walkthrough on ingressing traffic into a
-Kubernetes-Raspberry Pi cluster.
-![Digital creative of a browser on the internet][1]
-
-In this article, we will deploy a couple of simple websites and learn how to ingress traffic from the outside world into our cluster using Traefik. After that, we will learn how to remove Kubernetes resources as well. Let’s get started!
-
-### Materials needed
-
-To follow along with the article, you only need [the k3s Raspberry Pi cluster][2] we built in a previous article. Since your cluster will be pulling images from the web, the cluster will need to be able to access the internet.
-
-Some configuration files and sample HTML files will be shown in this article for explanation purposes. All sample files can be downloaded [here][3].
-
-### Deploying a simple website
-
-Previously, we did a direct deploy with **kubectl**. This is not the typical way to deploy things, however. Generally, YAML configuration files are used, and that is what we will use in this article. We will start at the top and create our configuration files in a top-down approach.
-
-### Deployment configuration
-
-First up is the deployment configuration. The configuration is shown below, and the explanation follows. I typically use the samples from the [Kubernetes documentation][4] as a starting point and then modify them to suit my needs. For example, the configuration below was modified after copying the sample from the [deployment docs][5].
-
-Create a file, **mysite.yaml**, with the following contents:
-
-
-```
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: mysite-nginx
- labels:
- app: mysite-nginx
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: mysite-nginx
- template:
- metadata:
- labels:
- app: mysite-nginx
- spec:
- containers:
- - name: nginx
- image: nginx
- ports:
- - containerPort: 80
-```
-
-Most of this is boilerplate. The important parts, we have named our deployment **mysite-nginx** with an **app** label of **mysite-nginx **as well. We have specified that we want one **replica** which means there will only be one pod created. We also specified **one container**, which we named **nginx**. We specified the **image** to be **nginx**. This means, on deployment, k3s will download the **nginx** image from DockerHub and create a pod from it. Finally, we specified a **containerPort** of **80**, which just means that inside the container the pod will listen on port **80**.
-
-I emphasized "inside the container" above because it is an important distinction. As we have the container configured, it is only accessible inside the container, and it is further restricted to an internal network. This is necessary to allow multiple containers to listen on the same container ports. In other words, with this configuration, some other pod could listen on its container port 80 as well and not conflict with this one. To provide formal access to this pod, we need a **service** configuration.
-
-### Service configuration
-
-In Kubernetes, a **service** is an abstraction. It provides a means to access a pod or set of pods. One connects to the service and the service routes to a single pod or load balances to multiple pods if multiple pod replicas are defined.
-
-The service can be specified in the same configuration file, and that is what we will do here. Separate configuration areas with **`---`**. Add the following to **mysite.yaml**:
-
-
-```
-\---
-apiVersion: v1
-kind: Service
-metadata:
- name: mysite-nginx-service
-spec:
- selector:
- app: mysite-nginx
- ports:
- - protocol: TCP
- port: 80
-```
-
-In this configuration, we have named our service **mysite-nginx-service**. We provided a `selector` of **app: mysite-nginx**. This is how the service chooses the application containers it routes to. Remember, we provided an **app** label for our container as **mysite-nginx**. This is what the service will use to find our container. Finally, we specified that the service protocol is **TCP** and the service listens on port **80**.
-
-### Ingress configuration
-
-The ingress configuration specifies how to get traffic from outside our cluster to services inside our cluster. Remember, k3s comes pre-configured with Traefik as an ingress controller. Therefore, we will write our ingress configuration specific to Traefik. Add the following to **mysite.yaml **( and don’t forget to separate with **`---`**):
-
-
-```
-\---
-apiVersion: networking.k8s.io/v1beta1
-kind: Ingress
-metadata:
- name: mysite-nginx-ingress
- annotations:
- kubernetes.io/ingress.class: "traefik"
-spec:
- rules:
- - http:
- paths:
- - path: /
- backend:
- serviceName: mysite-nginx-service
- servicePort: 80
-```
-
-In this configuration, we have named the ingress record **mysite-nginx-ingress**. And we told Kubernetes that we expect **traefik** to be our ingress controller with the **kubernetes.io/ingress.class** annotation.
-
-In the **rules** section, we are basically saying, when **http** traffic comes in, and the **path** matches **`/`** (or anything below that), route it to the **backend** service specified by the **serviceName mysite-nginx-service**, and route it to **servicePort 80**. This connects incoming HTTP traffic to the service we defined earlier.
-
-### Something to deploy
-
-That is really it as far as configuration goes. If we deployed now, we would get the default **nginx** page, but that is not what we want. Let’s create something simple but custom to deploy. Create the file **index.html** with the following contents:
-
-
-```
-<html>
-<head><title>K3S!</title>
- <style>
- html {
- font-size: 62.5%;
- }
- body {
- font-family: sans-serif;
- background-color: midnightblue;
- color: white;
- display: flex;
- flex-direction: column;
- justify-content: center;
- height: 100vh;
- }
- div {
- text-align: center;
- font-size: 8rem;
- text-shadow: 3px 3px 4px dimgrey;
- }
- </style>
-</head>
-<body>
- <div>Hello from K3S!</div>
-</body>
-</html>
-```
-
-We have not yet covered storage mechanisms in Kubernetes, so we are going to cheat a bit and just store this file in a Kubernetes config map. This is not the recommended way to deploy a website, but it will work for our purposes. Run the following:
-
-
-```
-`kubectl create configmap mysite-html --from-file index.html`
-```
-
-This command creates a `configmap` resource named **mysite-html** from the local file **index.html**. This essentially stores a file (or set of files) inside a Kubernetes resource that we can call out in configuration. It is typically used to store configuration files (hence the name), so we are abusing it a bit here. In a later article, we will discuss proper storage solutions in Kubernetes.
-
-With the config map created, let’s mount it inside our **nginx** container. We do this in two steps. First, we need to specify a **volume**, calling out the config map. Then we need to mount the volume into the **nginx** container. Complete the first step by adding the following under the **spec** label, just after **containers** in **mysite.yaml**:
-
-
-```
- volumes:
- - name: html-volume
- configMap:
- name: mysite-html
-```
-
-This tells Kubernetes that we want to define a **volume**, with the name **html-volume** and that volume should contain the contents of the **configMap** named **html-volume** (which we created in the previous step).
-
-Next, in the **nginx** container specification, just under **ports**, add the following:
-
-
-```
- volumeMounts:
- - name: html-volume
- mountPath: /usr/share/nginx/html
-```
-
-This tells Kubernetes, for the **nginx** container, we want to mount a **volume** named **html-volume** at the path (in the container) **/usr/share/nginx/html**. Why **/usr/share/nginx/html**? That is where the **nginx** image serves HTML from. By mounting our volume at that path, we have replaced the default contents with our volume contents.
-
-For reference, the **deployment** section of the configuration file should now look like this:
-
-
-```
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: mysite-nginx
- labels:
- app: mysite-nginx
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: mysite-nginx
- template:
- metadata:
- labels:
- app: mysite-nginx
- spec:
- containers:
- - name: nginx
- image: nginx
- ports:
- - containerPort: 80
- volumeMounts:
- - name: html-volume
- mountPath: /usr/share/nginx/html
- volumes:
- - name: html-volume
- configMap:
- name: mysite-html
-```
-
-### Deploy it!
-
-Now we are ready to deploy! We can do that with:
-
-
-```
-`kubectl apply -f mysite.yaml`
-```
-
-You should see something similar to the following:
-
-
-```
-deployment.apps/mysite-nginx created
-service/mysite-nginx-service created
-ingress.networking.k8s.io/mysite-nginx-ingress created
-```
-
-This means that Kubernetes created resources for each of the three configurations we specified. Check on the status of the pods with:
-
-
-```
-`kubectl get pods`
-```
-
-If you see a status of **ContainerCreating**, give it some time and run **kubectl get pods** again. Typically, the first time, it will take a while because k3s has to download the **nginx** image to create the pod. After a while, you should get a status of **Running**.
-
-### Try it!
-
-Once the pod is running, it is time to try it. Open up a browser and type **kmaster** into the address bar.
-
-![][6]
-
-Congratulations! You’ve deployed a website on your k3s cluster!
-
-### Another one
-
-So now we have a whole k3s cluster running a single website. But we can do more! What if we have another website we want to serve on the same cluster? Let’s see how to do that.
-
-Again, we need something to deploy. It just so happens that my dog has a message she has wanted the world to know for some time. So, I crafted some HTML just for her (available from the samples zip file). Again, we will use the config map trick to host our HTML. This time we are going to poke a whole directory (the **html** directory) into a config map, but the invocation is the same.
-
-
-```
-`kubectl create configmap mydog-html --from-file html`
-```
-
-Now we need to create a configuration file for this site. It is almost exactly the same as the one for **mysite.yaml**, so start by copying **mysite.yaml** to **mydog.yaml**. Now edit **mydog.yaml** to be:
-
-
-```
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: mydog-nginx
- labels:
- app: mydog-nginx
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: mydog-nginx
- template:
- metadata:
- labels:
- app: mydog-nginx
- spec:
- containers:
- - name: nginx
- image: nginx
- ports:
- - containerPort: 80
- volumeMounts:
- - name: html-volume
- mountPath: /usr/share/nginx/html
- volumes:
- - name: html-volume
- configMap:
- name: mydog-html
-\---
-apiVersion: v1
-kind: Service
-metadata:
- name: mydog-nginx-service
-spec:
- selector:
- app: mydog-nginx
- ports:
- - protocol: TCP
- port: 80
-\---
-apiVersion: networking.k8s.io/v1beta1
-kind: Ingress
-metadata:
- name: mydog-nginx-ingress
- annotations:
- kubernetes.io/ingress.class: "traefik"
- traefik.frontend.rule.type: PathPrefixStrip
-spec:
- rules:
- - http:
- paths:
- - path: /mydog
- backend:
- serviceName: mydog-nginx-service
- servicePort: 80
-```
-
-We can do most of the edits by simply doing a search and replace of **mysite** to **mydog**. The two other edits are in the ingress section. We changed **path** to **/mydog **and we added an annotation, **traefik.frontend.rule.type: PathPrefixStrip**.
-
-The specification of the path **/mydog** instructs Traefik to route any incoming request that requests a path starting with **/mydog** to the **mydog-nginx-service**. Any other path will continue to be routed to **mysite-nginx-service.**
-
-The new annotation, **PathPrefixStrip**, tells Traefik to strip off the prefix **/mydog** before sending the request to **mydog-nginx-service**. We did this because the **mydog-nginx** application doesn’t expect a prefix. This means we could change where the service was mounted simply by changing the prefix in the ingress record.
-
-Now we can deploy like we did before:
-
-
-```
-`kubectl apply -f mydog.yaml`
-```
-
-And now, my dog’s message should be available at .
-
-![][7]
-
-Phew! The message is out! Maybe we can all get some sleep tonight.
-
-So now, we have a k3s cluster hosting two websites with Traefik making decisions, based on path names, as to which service to pass the request to! We are not limited to path-based routing, however. We could use hostname based routing as well, which we will explore in a future article.
-
-Also, the websites we just hosted are standard unencrypted HTML sites. Everything these days is encrypted with SSL/TLS. In our next article, we will add support to our k3s cluster to host SSL/TLS HTTPS sites as well!
-
-### Cleaning up
-
-Before you go, since this article mostly dealt with sample sites, I would like to show you how to delete things in case you don’t want the samples hanging around on your cluster.
-
-For most configurations, you can undo the configuration simply by running the **delete** command with the same configuration file you deployed with. So let’s clean up both **mysite** and **mydog**.
-
-
-```
-kubectl delete -f mysite.yaml
-kubectl delete -f mydog.yaml
-```
-
-Since we manually created the config maps, we’ll need to delete those manually as well.
-
-
-```
-kubectl delete configmap mysite-html
-kubectl delete configmap mydog-html
-```
-
-Now if we do a **kubectl get pods**, we should see that our nginx pods are no longer around.
-
-
-```
-$ kubectl get pods
-No resources found in default namespace.
-```
-
-Everything is cleaned up.
-
-Tell me what thoughts you have on this project in the comments below.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/kubernetes-traefik
-
-作者:[Lee Carpenter][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/carpie
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
-[2]: https://opensource.com/article/20/3/kubernetes-raspberry-pi
-[3]: https://gitlab.com/carpie/ingressing_with_k3s/-/archive/master/ingressing_with_k3s-master.zip
-[4]: https://kubernetes.io/docs/
-[5]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment
-[6]: https://opensource.com/sites/default/files/uploads/mysite.jpg
-[7]: https://opensource.com/sites/default/files/uploads/mydog.jpg
diff --git a/sources/tech/20200311 What you need to know about variables in Emacs.md b/sources/tech/20200311 What you need to know about variables in Emacs.md
deleted file mode 100644
index d66ba374f4..0000000000
--- a/sources/tech/20200311 What you need to know about variables in Emacs.md
+++ /dev/null
@@ -1,243 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (What you need to know about variables in Emacs)
-[#]: via: (https://opensource.com/article/20/3/variables-emacs)
-[#]: author: (Clemens Radermacher https://opensource.com/users/clemera)
-
-What you need to know about variables in Emacs
-======
-Learn how Elisp deals with variables and to use them in your scripts and
-configurations.
-![Programming keyboard.][1]
-
-GNU Emacs is written in C and Emacs Lisp (Elisp), a dialect of the Lisp programming language. Because it's a text editor that happens to be an Elisp sandbox, it is helpful to understand how basic programming concepts work in Elisp.
-
-If you're new to [Emacs][2], visit Sacha Chua's excellent list of [resources for Emacs beginners][3]. This article assumes you're familiar with common Emacs terminology and that you know how to read and evaluate basic snippets of Elisp code. Ideally, you should also have heard of variable scope and how it works in another programming language. The examples also assume you use a fairly recent Emacs version ([v.25 or later][4]).
-
-The [Elisp manual][5] includes everything there is to know, but it is written for people who already know what they are looking for (and it is really great for that). But many people want resources that explain Elisp concepts at a higher level and reduce the amount of information to the most useful bits. This article is my attempt to respond to that—to give readers a good grasp of the basics so they can use them for their configuration and make it easier for people to look up some detail in the manual.
-
-### Global variables
-
-User options defined with **defcustom** and variables defined with **defvar** or **defconst** are global. One important aspect of variables declared by **defcustom** or **defvar** is that reevaluating them won't reset a variable if it is already bound. For example, if you establish a binding for **my-var** in your init file like this:
-
-
-```
-`(setq my-var nil)`
-```
-
-evaluating the following form won't reset the variable to **t**:
-
-
-```
-`(defvar my-var t)`
-```
-
-Note that there is _one exception_: If you evaluate the declaration above with **C-M-x** that calls **eval-defun**, the value will be reset to **t**. This way, you can enforce setting the value if you need to. This behavior is intentional: As you might know, many features in Emacs load only on demand (i.e., they are autoloaded). If the declarations in those files reset variables to their default value, this would override any settings in your init.
-
-### User options
-
-A user option is simply a global variable that is declared with **defcustom**. Unlike variables declared with **defvar**, such a variable is configurable with the **M-x customize** interface. As far as I know, most people don't use it much because it feels clunky. Once you know how to set variables in your init file, there's no compelling reason to use it. One detail many users aren't aware of is that setting user options with **customize** might execute code, and this is sometimes used to run additional setup instructions:
-
-
-```
-(defcustom my-option t
- "My user option."
- :set (lambda (sym val)
- (set-default sym val)
- (message "Set %s to %s" sym val)))
-```
-
-If you evaluate this code and change the value using the **customize** interface with **M-x customize-option RET my-option RET **the lambda will be called, and the message in the echo area will tell you the symbol and value of the option.
-
-If you use **setq** in your init file, to change the value of such an option, the setter function will _not_ run. To set such an option correctly with Elisp, you need to use the function **customize-set-variable**. Alternatively, people use various versions of **csetq** macros in their configs to automatically take care of this (you can use GitHub code search to discover more sophisticated variants if you like):
-
-
-```
-(defmacro csetq (sym val)
- `(funcall (or (get ',sym 'custom-set) 'set-default) ',sym ,val))
-```
-
-If you are using the [use-package][6] macro, the **:custom** keyword will handle this for you.
-
-After putting the code above into your init file, you can use **csetq** to set variables in a way that respects any existing setter functions. You can prove this by watching the message in the echo area when using this macro to change the option defined above:
-
-
-```
-`(csetq my-option nil)`
-```
-
-### Dynamic binding and lexical binding
-
-If you use other programming languages, you may not be aware of the differences between dynamic and lexical binding. Most programming languages today use lexical binding, and there is no need to know the difference when you learn about variable scope/lookup.
-
-Emacs Lisp is special in this regard because dynamic binding is the default, and lexical binding must be enabled explicitly. There are historical reasons for this, and in practice, you should _always_ enable lexical binding because it is faster and less error-prone. To enable it, simply put the following comment line as the first line in your Emacs Lisp file:
-
-
-```
-`;;; -*- lexical-binding: t; -*-`
-```
-
-Alternatively, you can call M-x **add-file-local-variable-prop-line**, which will insert the comment line above when you choose the variable **lexical-binding** with value **t**.
-
-When a file with such a specially formatted line is loaded, Emacs sets the variable accordingly, which means the code in that buffer is loaded with lexical binding enabled. Interactively, you can use **M-x eval-buffer**, which takes the lexical binding setting into account.
-
-Now that you know how to enable lexical binding, it's smart to learn what the terms mean. With dynamic binding, the last binding established during program execution is used for variable lookup. You can test this by putting the following code in an empty buffer and executing **M-x eval-buffer**:
-
-
-```
-(defun a-exists-only-in-my-body (a)
- (other-function))
-
-(defun other-function ()
- (message "I see `a', its value is %s" a))
-
-(a-exists-only-in-my-body t)
-```
-
-You may be surprised to see that the lookup of variable **a** in the **other-function** is successful.
-
-If you retry the preceding example with the special lexical-binding comment at the top, the code will throw a "variable is void" error because **other-function** does not know about the **a** variable. If you're coming from another programming language, this is the behavior you would expect.
-
-With lexical binding, the scope is defined by the surrounding source code. This is not only for performance reasons—experience and time have shown that this behavior is preferred.
-
-### Special variables and dynamic binding
-
-As you may know, **let** is used to temporary establish local bindings:
-
-
-```
-(let ((a "I'm a")
- (b "I'm b"))
- (message "Hello, %s. Hello %s" a b))
-```
-
-Here is the thing: Variables declared with **defcustom**, **defvar**, or **defconst** are called _special variables_, and they continue to use dynamic binding regardless of whether lexical binding is enabled:
-
-
-```
-;;; -*- lexical-binding: t; -*-
-
-(defun some-other-function ()
- (message "I see `c', its value is: %s" c))
-
-(defvar c t)
-
-(let ((a "I'm lexically bound")
- (c "I'm special and therefore dynamically bound"))
- (some-other-function)
- (message "I see `a', its values is: %s" a))
-```
-
-To see both messages in the example above, switch to the ***Messages*** buffer using **C-h e**.
-
-Local variables bound with **let** or function arguments follow the lookup rules defined by the **lexical-binding** variable, but global variables defined with **defvar**, **defconst**, or **defcustom** can be changed deep down in the call stack for the duration of the **let** body.
-
-This behavior allows for convenient ad-hoc customizations and is often used in Emacs, which isn't surprising given that Emacs Lisp started out with dynamic binding being the only option. Here is a common example showing how you can temporarily write to a read-only buffer:
-
-
-```
-(let ((inhibit-read-only t))
- (insert ...))
-```
-
-Here is another often-seen example for performing case-sensitive searches:
-
-
-```
-(let ((case-fold-search nil))
- (some-function-which-uses-search ...))
-```
-
-Dynamic binding allows you to change the behavior of functions in ways the authors of those functions may have never anticipated. It's a powerful tool and a great feature for a program that is designed and used like Emacs.
-
-There is one caveat to be aware of: You might accidentally use a local variable name that is declared as a special variable elsewhere. One trick to prevent such conflicts is to avoid dashes in local variables' names. In my current Emacs session, this leaves only a handful of potential conflicting candidates:
-
-
-```
-(let ((vars ()))
- (mapatoms
- (lambda (cand)
- (when (and (boundp cand)
- (not (keywordp cand))
- (special-variable-p cand)
- (not (string-match "-"
- (symbol-name cand))))
- (push cand vars))))
- vars) ;; => (t obarray noninteractive debugger nil)
-```
-
-### Buffer-local variables
-
-Each buffer can have a local binding for a variable. This means any variable lookup made while this buffer is current will reveal the buffer's local value of that variable instead of the default value. Local variables are an important feature in Emacs; for example, they are used by major modes to establish their buffer-local behavior and settings.
-
-You have already seen a buffer-local variable in this article: the special comment line for **lexical-binding** that binds the buffer locally to **t**. In Emacs, such buffer-local variables defined in special comment lines are also called _file-local variables_.
-
-Any global variable can be shadowed by a buffer-local variable. Take, for example, the **my-var** variable defined above, which you can set locally like this:
-
-
-```
-(setq-local my-var t)
-;; or (set (make-local-variable 'my-var) t)
-```
-
-**my-var** is local to the buffer, which is current when you evaluate the code above. If you call **describe-variable** on it, the documentation tells you both the local value and the global one. Programmatically, you can check the local value using **buffer-local-value** and the default value with **default-value**. To remove the local version, you could invoke **M-x kill-local-variable**.
-
-Another important property to be aware of is that once a variable is buffer-local, any further use of **setq** (while this buffer is current) will continue to set the local value. To set the default value, you would need to use **setq-default**.
-
-Because local variables are meant for buffer customization, they're used most often in mode hooks. A typical example would be something like this:
-
-
-```
-(add-hook 'go-mode-hook
- (defun go-setup+ ()
- (setq-local compile-command
- (if (string-suffix-p "_test.go" buffer-file-name)
- "go test -v"
- (format "go run %s"
- (shell-quote-argument
- (file-name-nondirectory buffer-file-name)))))))
-```
-
-This sets the compile command used by **M-x compile** for go-mode buffers.
-
-Another important aspect is that some variables are _automatically_ buffer-local. This means as soon as you **setq** such a variable, it sets a local binding for the current buffer. This feature shouldn't be used often (because this implicit behavior isn't nice), but if you want, you can create such automatically local variables like this:
-
-
-```
-(defvar-local my-automatical-local-var t)
-;; or (make-variable-buffer-local 'my-automatical-local-var)
-```
-
-The variable **indent-tabs-mode** is a built-in example of this. If you use **setq** in your init file to change the value of this variable, it won't affect the default value at all. Only the value for the buffer that is current while loading your init file will be changed. Therefore, you need to use **setq-default** to change the default value of **indent-tabs-mode**.
-
-### Closing words
-
-Emacs is a powerful editor, and it only gets more powerful the more you change it to suit your needs. Now you know how Elisp deals with variables and how you can use them in your own scripts and configurations.
-
-* * *
-
-_This previously appeared on [With-Emacs][7] under a CC BY-NC-SA 4.0 license and has been adapted (with a merge request) and republished with the author's permission._
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/variables-emacs
-
-作者:[Clemens Radermacher][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/clemera
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming_keyboard_coding.png?itok=E0Vvam7A (Programming keyboard.)
-[2]: https://www.gnu.org/software/emacs/
-[3]: http://sachachua.com/blog/p/27144
-[4]: https://www.gnu.org/software/emacs/download.html
-[5]: https://www.gnu.org/software/emacs/manual/html_node/elisp/
-[6]: https://github.com/jwiegley/use-package#customizing-variables
-[7]: https://with-emacs.com/posts/tutorials/almost-all-you-need-to-know-about-variables/
diff --git a/sources/tech/20200317 Create Stunning Pixel Art With Free and Open Source Editor Pixelorama.md b/sources/tech/20200317 Create Stunning Pixel Art With Free and Open Source Editor Pixelorama.md
deleted file mode 100644
index fc3c4b7bab..0000000000
--- a/sources/tech/20200317 Create Stunning Pixel Art With Free and Open Source Editor Pixelorama.md
+++ /dev/null
@@ -1,108 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Create Stunning Pixel Art With Free and Open Source Editor Pixelorama)
-[#]: via: (https://itsfoss.com/pixelorama/)
-[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
-
-Create Stunning Pixel Art With Free and Open Source Editor Pixelorama
-======
-
-_**Brief: Pixelorama is a cross-platform, free and open source 2D sprite editor. It provides all the necessary tools to create pixel art in a neat user interface.**_
-
-### Pixelorama: open source sprite editor
-
-[Pixelorama][1] is a tool created by young game developers at [Orama Interactive][2]. They have developed a few 2D games and a couple of them use pixel art.
-
-While Orama is primarily into game development, the developers are also creating utility tools that help them (and others) create those games.
-
-The free and open source sprite editor, Pixelorama is such a utility tool. It’s built on top of [Godot Engine][3] and is perfect for creating pixel art.
-
-![Pixelorama screenshot][4]
-
-You see the pixel art in the screenshot above? It’s been created using Pixelorama. This video shows a timelapse video of creating the above image.
-
-### Features of Pixelorama
-
-Here are the main features Pixelorama provides:
-
- * Multiple tools like penicl, erase, fill bucket color picker etc
- * Multiple layer system that allows you to add, remove, move up and down, clone and merge as many layers as you like
- * Support for spritesheets
- * Import images and edit them inside Pixelorama
- * Animation timeline with [Onion Skinning][5]
- * Custom brushes
- * Save and open your projects in Pixelorama’s custom file format, .pxo
- * Horizontal & vertical mirrored drawing
- * Tile Mode for pattern creation
- * Split screen mode and mini canvas preview
- * Zoom with mouse scroll wheel
- * Unlimited undo and redo
- * Scale, crop, flip, rotate, color invert and desaturate your images
- * Keyboard shortcuts
- * Available in several languages
- * Supports Linux, Windows and macOS
-
-
-
-### Installing Pixelorama on Linux
-
-Pixelorama is available as a Snap application and if you are using Ubuntu, you can find it in the software center itself.
-
-![Pixelorama is available in Ubuntu Software Center][6]
-
-Alternatively, if you have [Snap support enabled on your Linux distribution][7], you can install it using this command:
-
-```
-sudo snap install pixelorama
-```
-
-If you don’t want to use Snap, no worries. You can download the latest release of Pixelorama from [their GitHub repository][8], [extract the zip file][9] and you’ll see an executable file. Give this file execute permission and double click on it to run the application.
-
-[Download Pixelorama][10]
-
-**Conclusion**
-
-![Pixelorama Welcome Screen][11]
-
-In the Pixeloaram features, it says that you can import images and edit them. I guess that’s only true for certain kind of files because when I tried to import PNG or JPEG files, the application crashed.
-
-However, I could easily doodle like a 3 year old and make random pixel art. I am not that into arts but I think this is a [useful tool for digital artists on Linux][12].
-
-I liked the idea that despite being game developers, they are creating tools that could help other game developers and artists. That’s the spirit of open source.
-
-If you like the project and will be using it, consider supporting them by a donation. [It’s FOSS has made a humble donation][13] of $25 to thank their effort.
-
-[Donate to Pixelorama (personal Paypal account of the lead developer)][14]
-
-Do you like Pixelorama? Do you use some other open source sprite editor? Feel free to share your views in the comment section.
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/pixelorama/
-
-作者:[Abhishek Prakash][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/abhishek/
-[b]: https://github.com/lujun9972
-[1]: https://www.orama-interactive.com/pixelorama
-[2]: https://www.orama-interactive.com/
-[3]: https://godotengine.org/
-[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/pixelorama-v6.jpg?ssl=1
-[5]: https://en.wikipedia.org/wiki/Onion_skinning
-[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/pixelorama-ubuntu-software-center.jpg?ssl=1
-[7]: https://itsfoss.com/install-snap-linux/
-[8]: https://github.com/Orama-Interactive/Pixelorama
-[9]: https://itsfoss.com/unzip-linux/
-[10]: https://github.com/Orama-Interactive/Pixelorama/releases
-[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/pixelorama.jpg?ssl=1
-[12]: https://itsfoss.com/best-linux-graphic-design-software/
-[13]: https://itsfoss.com/donations-foss/
-[14]: https://www.paypal.me/erevos
diff --git a/sources/tech/20200318 Share data between C and Python with this messaging library.md b/sources/tech/20200318 Share data between C and Python with this messaging library.md
deleted file mode 100644
index cda6e54e33..0000000000
--- a/sources/tech/20200318 Share data between C and Python with this messaging library.md
+++ /dev/null
@@ -1,663 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Share data between C and Python with this messaging library)
-[#]: via: (https://opensource.com/article/20/3/zeromq-c-python)
-[#]: author: (Cristiano L. Fontana https://opensource.com/users/cristianofontana)
-
-Share data between C and Python with this messaging library
-======
-ZeroMQ makes for a fast and resilient messaging library to gather data
-and share between multiple languages.
-![Chat via email][1]
-
-I've had moments as a software engineer when I'm asked to do a task that sends shivers down my spine. One such moment was when I had to write an interface between some new hardware infrastructure that requires C and a cloud infrastructure, which is primarily Python.
-
-One strategy could be to [write an extension in C][2], which Python supports by design. A quick glance at the documentation shows this would mean writing a good amount of C. That can be good in some cases, but it's not what I prefer to do. Another strategy is to put the two tasks in separate processes and exchange messages between the two with the [ZeroMQ messaging library][3].
-
-When I experienced this type of scenario before discovering ZeroMQ, I went through the extension-writing path. It was not that bad, but it is very time-consuming and convoluted. Nowadays, to avoid that, I subdivide a system into independent processes that exchange information through messages sent over [communication sockets][4]. With this approach, several programming languages can coexist, and each process is simpler and thus easier to debug.
-
-ZeroMQ provides an even easier process:
-
- 1. Write a small shim in C that reads data from the hardware and sends whatever it finds as a message.
- 2. Write a Python interface between the new and existing infrastructure.
-
-
-
-One of ZeroMQ's project's founders is [Pieter Hintjens][5], a remarkable person with [interesting views and writings][6].
-
-### Prerequisites
-
-For this tutorial, you will need:
-
- * A C compiler (e.g., [GCC][7] or [Clang][8])
- * The [**libzmq** library][9]
- * [Python 3][10]
- * [ZeroMQ bindings][11] for python
-
-
-
-Install them on Fedora with:
-
-
-```
-`$ dnf install clang zeromq zeromq-devel python3 python3-zmq`
-```
-
-For Debian or Ubuntu:
-
-
-```
-`$ apt-get install clang libzmq5 libzmq3-dev python3 python3-zmq`
-```
-
-If you run into any issues, refer to each project's installation instructions (which are linked above).
-
-### Writing the hardware-interfacing library
-
-Since this is a hypothetical scenario, this tutorial will write a fictitious library with two functions:
-
- * **fancyhw_init()** to initiate the (hypothetical) hardware
- * **fancyhw_read_val()** to return a value read from the hardware
-
-
-
-Save the library's full source code to a file named **libfancyhw.h**:
-
-
-```
-#ifndef LIBFANCYHW_H
-#define LIBFANCYHW_H
-
-#include <stdlib.h>
-#include <stdint.h>
-
-// This is the fictitious hardware interfacing library
-
-void fancyhw_init(unsigned int init_param)
-{
- [srand][12](init_param);
-}
-
-int16_t fancyhw_read_val(void)
-{
- return (int16_t)[rand][13]();
-}
-
-#endif
-```
-
-This library can simulate the data you want to pass between languages, thanks to the random number generator.
-
-### Designing a C interface
-
-The following will go step-by-step through writing the C interface—from including the libraries to managing the data transfer.
-
-#### Libraries
-
-Begin by loading the necessary libraries (the purpose of each library is in a comment in the code):
-
-
-```
-// For printf()
-#include <stdio.h>
-// For EXIT_*
-#include <stdlib.h>
-// For memcpy()
-#include <string.h>
-// For sleep()
-#include <unistd.h>
-
-#include <zmq.h>
-
-#include "libfancyhw.h"
-```
-
-#### Significant parameters
-
-Define the **main** function and the significant parameters needed for the rest of the program:
-
-
-```
-int main(void)
-{
- const unsigned int INIT_PARAM = 12345;
- const unsigned int REPETITIONS = 10;
- const unsigned int PACKET_SIZE = 16;
- const char *TOPIC = "fancyhw_data";
-
- ...
-```
-
-#### Initialization
-
-Both libraries need some initialization. The fictitious one needs just one parameter:
-
-
-```
-`fancyhw_init(INIT_PARAM);`
-```
-
-The ZeroMQ library needs some real initialization. First, define a **context**—an object that manages all the sockets:
-
-
-```
-void *context = zmq_ctx_new();
-
-if (!context)
-{
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
-}
-```
-
-Then define the socket used to deliver data. ZeroMQ supports several types of sockets, each with its application. Use a **publish** socket (also known as **PUB** socket), which can deliver copies of a message to multiple receivers. This approach enables you to attach several receivers that will all get the same messages. If there are no receivers, the messages will be discarded (i.e., they will not be queued). Do this with:
-
-
-```
-`void *data_socket = zmq_socket(context, ZMQ_PUB);`
-```
-
-The socket must be bound to an address so that the clients know where to connect. In this case, use the [TCP transport layer][15] (there are [other options][16], but TCP is a good default choice):
-
-
-```
-const int rb = zmq_bind(data_socket, "tcp://*:5555");
-
-if (rb != 0)
-{
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
-}
-```
-
-Next, calculate some useful values that you will need later. Note **TOPIC** in the code below; **PUB** sockets need a topic to be associated with the messages they send. Topics can be used by the receivers to filter messages:
-
-
-```
-const size_t topic_size = [strlen][17](TOPIC);
-const size_t envelope_size = topic_size + 1 + PACKET_SIZE * sizeof(int16_t);
-
-[printf][14]("Topic: %s; topic size: %zu; Envelope size: %zu\n", TOPIC, topic_size, envelope_size);
-```
-
-#### Sending messages
-
-Start a loop that sends **REPETITIONS** messages:
-
-
-```
-for (unsigned int i = 0; i < REPETITIONS; i++)
-{
- ...
-```
-
-Before sending a message, fill a buffer of **PACKET_SIZE** values. The library provides signed integers of 16 bits. Since the dimension of an **int** in C is not defined, use an **int** with a specific width:
-
-
-```
-int16_t buffer[PACKET_SIZE];
-
-for (unsigned int j = 0; j < PACKET_SIZE; j++)
-{
- buffer[j] = fancyhw_read_val();
-}
-
-[printf][14]("Read %u data values\n", PACKET_SIZE);
-```
-
-The first step in message preparation and delivery is creating a ZeroMQ message and allocating the memory necessary for your message. This empty message is an envelope to store the data you will ship:
-
-
-```
-zmq_msg_t envelope;
-
-const int rmi = zmq_msg_init_size(&envelope, envelope_size);
-if (rmi != 0)
-{
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_msg_init_size(): %s\n", zmq_strerror(errno));
-
- zmq_msg_close(&envelope);
-
- break;
-}
-```
-
-Now that the memory is allocated, store the data in the ZeroMQ message "envelope." The **zmq_msg_data()** function returns a pointer to the beginning of the buffer in the envelope. The first part is the topic, followed by a space, then the binary data. Add whitespace as a separator between the topic and the data. To move along the buffer, you have to play with casts and [pointer arithmetic][18]. (Thank you, C, for making things straightforward.) Do this with:
-
-
-```
-[memcpy][19](zmq_msg_data(&envelope), TOPIC, topic_size);
-[memcpy][19]((void*)((char*)zmq_msg_data(&envelope) + topic_size), " ", 1);
-[memcpy][19]((void*)((char*)zmq_msg_data(&envelope) + 1 + topic_size), buffer, PACKET_SIZE * sizeof(int16_t));
-```
-
-Send the message through the **data_socket**:
-
-
-```
-const size_t rs = zmq_msg_send(&envelope, data_socket, 0);
-if (rs != envelope_size)
-{
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_msg_send(): %s\n", zmq_strerror(errno));
-
- zmq_msg_close(&envelope);
-
- break;
-}
-```
-
-Make sure to dispose of the envelope after you use it:
-
-
-```
-zmq_msg_close(&envelope);
-
-[printf][14]("Message sent; i: %u, topic: %s\n", i, TOPIC);
-```
-
-#### Clean it up
-
-Because C does not provide [garbage collection][20], you have to tidy up. After you are done sending your messages, close the program with the clean-up needed to release the used memory:
-
-
-```
-const int rc = zmq_close(data_socket);
-
-if (rc != 0)
-{
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_close(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
-}
-
-const int rd = zmq_ctx_destroy(context);
-
-if (rd != 0)
-{
- [printf][14]("Error occurred during zmq_ctx_destroy(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
-}
-
-return EXIT_SUCCESS;
-```
-
-#### The entire C program
-
-Save the full interface library below to a local file called **hw_interface.c**:
-
-
-```
-// For printf()
-#include <stdio.h>
-// For EXIT_*
-#include <stdlib.h>
-// For memcpy()
-#include <string.h>
-// For sleep()
-#include <unistd.h>
-
-#include <zmq.h>
-
-#include "libfancyhw.h"
-
-int main(void)
-{
- const unsigned int INIT_PARAM = 12345;
- const unsigned int REPETITIONS = 10;
- const unsigned int PACKET_SIZE = 16;
- const char *TOPIC = "fancyhw_data";
-
- fancyhw_init(INIT_PARAM);
-
- void *context = zmq_ctx_new();
-
- if (!context)
- {
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
- }
-
- void *data_socket = zmq_socket(context, ZMQ_PUB);
-
- const int rb = zmq_bind(data_socket, "tcp://*:5555");
-
- if (rb != 0)
- {
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_ctx_new(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
- }
-
- const size_t topic_size = [strlen][17](TOPIC);
- const size_t envelope_size = topic_size + 1 + PACKET_SIZE * sizeof(int16_t);
-
- [printf][14]("Topic: %s; topic size: %zu; Envelope size: %zu\n", TOPIC, topic_size, envelope_size);
-
- for (unsigned int i = 0; i < REPETITIONS; i++)
- {
- int16_t buffer[PACKET_SIZE];
-
- for (unsigned int j = 0; j < PACKET_SIZE; j++)
- {
- buffer[j] = fancyhw_read_val();
- }
-
- [printf][14]("Read %u data values\n", PACKET_SIZE);
-
- zmq_msg_t envelope;
-
- const int rmi = zmq_msg_init_size(&envelope, envelope_size);
- if (rmi != 0)
- {
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_msg_init_size(): %s\n", zmq_strerror(errno));
-
- zmq_msg_close(&envelope);
-
- break;
- }
-
- [memcpy][19](zmq_msg_data(&envelope), TOPIC, topic_size);
-
- [memcpy][19]((void*)((char*)zmq_msg_data(&envelope) + topic_size), " ", 1);
-
- [memcpy][19]((void*)((char*)zmq_msg_data(&envelope) + 1 + topic_size), buffer, PACKET_SIZE * sizeof(int16_t));
-
- const size_t rs = zmq_msg_send(&envelope, data_socket, 0);
- if (rs != envelope_size)
- {
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_msg_send(): %s\n", zmq_strerror(errno));
-
- zmq_msg_close(&envelope);
-
- break;
- }
-
- zmq_msg_close(&envelope);
-
- [printf][14]("Message sent; i: %u, topic: %s\n", i, TOPIC);
-
- sleep(1);
- }
-
- const int rc = zmq_close(data_socket);
-
- if (rc != 0)
- {
- [printf][14]("ERROR: ZeroMQ error occurred during zmq_close(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
- }
-
- const int rd = zmq_ctx_destroy(context);
-
- if (rd != 0)
- {
- [printf][14]("Error occurred during zmq_ctx_destroy(): %s\n", zmq_strerror(errno));
-
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-```
-
-Compile using the command:
-
-
-```
-`$ clang -std=c99 -I. hw_interface.c -lzmq -o hw_interface`
-```
-
-If there are no compilation errors, you can run the interface. What's great is that ZeroMQ **PUB** sockets can run without any applications sending or retrieving data. That reduces complexity because there is no obligation in terms of which process needs to start first.
-
-Run the interface:
-
-
-```
-$ ./hw_interface
-Topic: fancyhw_data; topic size: 12; Envelope size: 45
-Read 16 data values
-Message sent; i: 0, topic: fancyhw_data
-Read 16 data values
-Message sent; i: 1, topic: fancyhw_data
-Read 16 data values
-...
-...
-```
-
-The output shows the data being sent through ZeroMQ. Now you need an application to read the data.
-
-### Write a Python data processor
-
-You are now ready to pass the data from C to a Python application.
-
-#### Libraries
-
-You need two libraries to help transfer data. First, you need ZeroMQ bindings in Python:
-
-
-```
-`$ python3 -m pip install zmq`
-```
-
-The other is the [**struct** library][21], which decodes binary data. It's commonly available with the Python standard library, so there's no need to **pip install** it.
-
-The first part of the Python program imports both of these libraries:
-
-
-```
-import zmq
-import struct
-```
-
-#### Significant parameters
-
-To use ZeroMQ, you must subscribe to the same topic used in the constant **TOPIC** above:
-
-
-```
-topic = "fancyhw_data".encode('ascii')
-
-print("Reading messages with topic: {}".format(topic))
-```
-
-#### Initialization
-
-Next, initialize the context and the socket. Use a **subscribe** socket (also known as a **SUB** socket), which is the natural partner of the **PUB** socket. The socket also needs to subscribe to the right topic:
-
-
-```
-with zmq.Context() as context:
- socket = context.socket(zmq.SUB)
-
- socket.connect("tcp://127.0.0.1:5555")
- socket.setsockopt(zmq.SUBSCRIBE, topic)
-
- i = 0
-
- ...
-```
-
-#### Receiving messages
-
-Start an infinite loop that waits for new messages to be delivered to the SUB socket. The loop will be closed if you press **Ctrl+C** or if an error occurs:
-
-
-```
- try:
- while True:
-
- ... # we will fill this in next
-
- except KeyboardInterrupt:
- socket.close()
- except Exception as error:
- print("ERROR: {}".format(error))
- socket.close()
-```
-
-The loop waits for new messages to arrive with the **recv()** method. Then it splits whatever is received at the first space to separate the topic from the content:
-
-
-```
-`binary_topic, data_buffer = socket.recv().split(b' ', 1)`
-```
-
-#### Decoding messages
-
-Python does yet not know that the topic is a string, so decode it using the standard ASCII encoding:
-
-
-```
-topic = binary_topic.decode(encoding = 'ascii')
-
-print("Message {:d}:".format(i))
-print("\ttopic: '{}'".format(topic))
-```
-
-The next step is to read the binary data using the **struct** library, which can convert shapeless binary blobs to significant values. First, calculate the number of values stored in the packet. This example uses 16-bit signed integers that correspond to an "h" in the **struct** [format][22]:
-
-
-```
-packet_size = len(data_buffer) // struct.calcsize("h")
-
-print("\tpacket size: {:d}".format(packet_size))
-```
-
-By knowing how many values are in the packet, you can define the format by preparing a string with the number of values and their types (e.g., "**16h**"):
-
-
-```
-`struct_format = "{:d}h".format(packet_size)`
-```
-
-Convert that binary blob to a series of numbers that you can immediately print:
-
-
-```
-data = struct.unpack(struct_format, data_buffer)
-
-print("\tdata: {}".format(data))
-```
-
-#### The full Python program
-
-Here is the complete data receiver in Python:
-
-
-```
-#! /usr/bin/env python3
-
-import zmq
-import struct
-
-topic = "fancyhw_data".encode('ascii')
-
-print("Reading messages with topic: {}".format(topic))
-
-with zmq.Context() as context:
- socket = context.socket(zmq.SUB)
-
- socket.connect("tcp://127.0.0.1:5555")
- socket.setsockopt(zmq.SUBSCRIBE, topic)
-
- i = 0
-
- try:
- while True:
- binary_topic, data_buffer = socket.recv().split(b' ', 1)
-
- topic = binary_topic.decode(encoding = 'ascii')
-
- print("Message {:d}:".format(i))
- print("\ttopic: '{}'".format(topic))
-
- packet_size = len(data_buffer) // struct.calcsize("h")
-
- print("\tpacket size: {:d}".format(packet_size))
-
- struct_format = "{:d}h".format(packet_size)
-
- data = struct.unpack(struct_format, data_buffer)
-
- print("\tdata: {}".format(data))
-
- i += 1
-
- except KeyboardInterrupt:
- socket.close()
- except Exception as error:
- print("ERROR: {}".format(error))
- socket.close()
-```
-
-Save it to a file called **online_analysis.py**. Python does not need to be compiled, so you can run the program immediately.
-
-Here is the output:
-
-
-```
-$ ./online_analysis.py
-Reading messages with topic: b'fancyhw_data'
-Message 0:
- topic: 'fancyhw_data'
- packet size: 16
- data: (20946, -23616, 9865, 31416, -15911, -10845, -5332, 25662, 10955, -32501, -18717, -24490, -16511, -28861, 24205, 26568)
-Message 1:
- topic: 'fancyhw_data'
- packet size: 16
- data: (12505, 31355, 14083, -19654, -9141, 14532, -25591, 31203, 10428, -25564, -732, -7979, 9529, -27982, 29610, 30475)
-...
-...
-```
-
-### Conclusion
-
-This tutorial describes an alternative way of gathering data from C-based hardware interfaces and providing it to Python-based infrastructures. You can take this data and analyze it or pass it off in any number of directions. It employs a messaging library to deliver data between a "gatherer" and an "analyzer" instead of having a monolithic piece of software that does everything.
-
-This tutorial also increases what I call "software granularity." In other words, it subdivides the software into smaller units. One of the benefits of this strategy is the possibility of using different programming languages at the same time with minimal interfaces acting as shims between them.
-
-In practice, this design allows software engineers to work both more collaboratively and independently. Different teams may work on different steps of the analysis, choosing the tool they prefer. Another benefit is the parallelism that comes for free since all the processes can run in parallel. The [ZeroMQ messaging library][3] is a remarkable piece of software that makes all of this much easier.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/zeromq-c-python
-
-作者:[Cristiano L. Fontana][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/cristianofontana
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/email_chat_communication_message.png?itok=LKjiLnQu (Chat via email)
-[2]: https://docs.python.org/3/extending/extending.html
-[3]: https://zeromq.org/
-[4]: https://en.wikipedia.org/wiki/Network_socket
-[5]: https://en.wikipedia.org/wiki/Pieter_Hintjens
-[6]: http://hintjens.com/
-[7]: https://gcc.gnu.org/
-[8]: https://clang.llvm.org/
-[9]: https://github.com/zeromq/libzmq#installation-of-binary-packages-
-[10]: https://www.python.org/downloads/
-[11]: https://zeromq.org/languages/python/
-[12]: http://www.opengroup.org/onlinepubs/009695399/functions/srand.html
-[13]: http://www.opengroup.org/onlinepubs/009695399/functions/rand.html
-[14]: http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
-[15]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol
-[16]: http://zguide.zeromq.org/page:all#Plugging-Sockets-into-the-Topology
-[17]: http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html
-[18]: https://en.wikipedia.org/wiki/Pointer_%28computer_programming%29%23C_and_C++
-[19]: http://www.opengroup.org/onlinepubs/009695399/functions/memcpy.html
-[20]: https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)
-[21]: https://docs.python.org/3/library/struct.html
-[22]: https://docs.python.org/3/library/struct.html#format-characters
diff --git a/sources/tech/20200319 7 open hardware projects working to solve COVID-19.md b/sources/tech/20200319 7 open hardware projects working to solve COVID-19.md
deleted file mode 100644
index 3d89271d1c..0000000000
--- a/sources/tech/20200319 7 open hardware projects working to solve COVID-19.md
+++ /dev/null
@@ -1,207 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (wxy)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (7 open hardware projects working to solve COVID-19)
-[#]: via: (https://opensource.com/article/20/3/open-hardware-covid19)
-[#]: author: (Harris Kenny https://opensource.com/users/harriskenny)
-
-7 open hardware projects working to solve COVID-19
-======
-Open hardware solutions can prevent the spread and suffering of the
-novel coronavirus.
-![open on blue background with heartbeat symbol][1]
-
-The open source [hardware][2] movement has long championed the importance of the right to repair, fully own the technology you buy, and be able to remix and reproduce gadgets, just like you can with music. And so, during this challenging time, open hardware is providing some answers to some of the problems created by the coronavirus pandemic.
-
-### An overview of what's happening
-
-For one, hardware developers around the world are working to resolve supply chain weaknesses using open source, the same philosophy that has driven a proliferation of new software technologies over the last 30 years. The hardware movement's past successes include the [RepRap Project][3], [Open Source Ecology][4], and [Open Source Beehives][5], proving this can be done.
-
-There has been increasing interest in creators using 3D printing and other technologies to create replacement parts for and manufacturing of safety equipment on demand. For example, the Polytechnic University lab in Hong Kong [3D printed face shields][6] for hospital workers. And Italian startup Isinnova partnered with the FabLab in Milan to [3D-print replacement valves][7] for reanimation devices in hard-hit Northern Italy. Companies are also releasing designs to adapt our physical interactions, like this [3D printed hands-free door opener][8] from Materialise. These examples of replacing parts and solving problems are an excellent start and appear to be saving lives.
-
-Another traditional hardware technique is picking up steam: sewing. The AFP reports that there is an acute need for face masks around the world and guidance from the World Health Organization about their importance. With single-use, disposable masks being prioritized for healthcare workers, in the Czech Republic people are [taking to sewing to make their own masks][9]. (Repeat-use masks do introduce sterility concerns.) The Facebook group "Czechia sews face masks" started to address this problem in their country, with tens of thousands of members using their at-home sewing machines.
-
-Open source hardware equipment and machinery projects are also gaining traction. First, there is testing equipment that is sophisticated and highly capable. Next, there is medical equipment that can be categorized as field-grade (at best) for scenarios with no other option. These projects are outlined in detail below.
-
-To learn more, I spoke with Jason Huggins, founder and CEO of Chicago-based [Tapster Robotics][10]. Tapster Robotics designs and manufactures desktop robots using 3D printing, computer numerical control (CNC) machining, and open electronics like [Arduino][11]. He has both the technical know-how and the industrial capacity to make an impact. And he wants to commit his company's resources to help in this fight.
-
-"Basically, we're in a World War II mobilization moment right now. Even though I'm not a doctor, we should still all follow the Hippocratic Oath. Whatever I do, I don't want to make the problem worse," Huggins explains. "As a counterpoint, there is WHO executive director Dr. Michael Ryan's comment: 'Speed trumps perfection,'" Huggins argues.
-
-> Wow.
->
-> This man is the global authority on the spread of disease. If you are a leader (in any capacity) watch this. If you are not, watch it too. [pic.twitter.com/bFogaekehM][12]
->
-> — Jim Richards Sh🎙wgram (@JIMrichards1010) [March 15, 2020][13]
-
-Huggins has extensive experience with delivering during times of need. His efforts were instrumental in helping [Healthcare.gov][14] scale after its challenging initial launch. He also created the software industry-standard testing frameworks Selenium and Appium. With this experience, his advice is well worth considering.
-
-I also spoke with Seattle-based attorney Mark Tyson of [Tyson Law][15], who works with startups and small businesses. He has direct experience working with nimble companies in rapidly evolving industries. In framing the overall question, Tyson begins:
-
-> Good Samaritan laws protect volunteers—i.e., “Good Samaritans”—from being held liable as a result of their decision to give aid during an emergency. While the specifics of these laws vary by state, they share a common public policy rationale: namely, encouraging bystanders to help others facing an emergency. Conceivably, this rationale could justify application of these types of laws in less traditional settings than, say, pulling the victim of a car accident out of harm’s way.
-
-Applying this specific situation, Tyson notes:
-
-> "Before taking action, creators would be wise to speak with an attorney to conduct a state-specific risk assessment. It would also be prudent to ask larger institutions, like hospitals or insurers, to accept potential liability exposure via contract—for instance, through the use of indemnification agreements, whereby the hospital or its insurer agrees to indemnify the creator for liability."
-
-Tyson understands the urgency and gravity of the situation. This option to use contracts is not meant to be a roadblock; instead, it may be a way to help adoption happen at scale to make a bigger difference faster. It is up to you or your organization to make this determination.
-
-With all that said, let's explore the projects that are in use or in development (and may be available for deployment soon).
-
-### 7 open hardware projects fighting COVID-19
-
-#### Opentrons
-
-[Opentrons][16]' open source lab automation platform is comprised of a suite of open source hardware, verified labware, consumables, reagents, and workstations. Opentrons says its products can help dramatically [scale-up COVID-19 testing][17] with systems that can "automate up to 2,400 tests per day within days of an order being placed." It plans to ramp up to 1 million tested samples by July 1.
-
-![Opentrons roadmap graphic][18]
-
-From the Opentrons [website][17], Copyright
-
-The company is already working with federal and local government agencies to determine if its systems can be used for clinical diagnosis under an [emergency use authorization][19]. Opentrons is shared under an [Apache 2.0 license][20]. I first learned of it from biologist Kristin Ellis, who is affiliated with the project.
-
-#### Chai Open qPCR
-
-Chai's [Open qPCR][21] device uses [polymerase chain reaction][22] (PCR) to rapidly test swabs from surfaces (e.g., door handles and elevator buttons) to see if the novel coronavirus is present. This open source hardware shared under an [Apache 2.0 license][23] uses a [BeagleBone][24] low-power Linux computer. Data from the Chai Open qPCR can enable public health, civic, and business leaders to make more informed decisions about cleaning, mitigation, facility closures, contract tracing, and testing.
-
-#### OpenPCR
-
-[OpenPCR][25] is a PCR testing device kit from Josh Perfetto and Jessie Ho, the creators behind the Chai Open qPCR. This is more of a DIY open source device than their previous project, but it has the same use case: using environmental testing to identify the coronavirus in the field. As the project page states, "traditional real-time PCR machines capable of detecting these pathogens typically cost upwards of $30,000 US dollars and are not suitable for field usage." Because OpenPCR is a kit users build and is shared under a [GPLv3.0 license][26], the device aims to democratize access to molecular diagnostics.
-
-![OpenPCR][27]
-
-From the OpenPCR [website][25], Copyright
-
-And, like any good open source project, there is a derivative! [WildOpenPCR][28] by [GaudiLabs][29] in Switzerland is also shared under a [GPLv3.0 license][30].
-
-#### PocketPCR
-
-Gaudi Labs' [PocketPCR][31] thermocycler is used to activate biological reactions by raising and lowering the temperature of a liquid in small test tubes. It can be powered with a simple USB power adapter, either tethered to a device or on its own, with preset parameters that don't require a computer or smartphone.
-
-![PocketPCR][32]
-
-From the PocketPCR [website][31], Copyright
-
-Like the other PCR options described in this article, this device may facilitate environmental testing for coronavirus, although its project page does not explicitly state so. PocketPCR is shared under a [GPLv3.0 license][33].
-
-#### Open Lung Low Resource Ventilator
-
-The [Open Lung Low Resource Ventilator][34] is a quick-deployment ventilator that utilizes a [bag valve mask][35] (BVM), also known as an Ambu-bag, as a core component. Ambu-bags are mass-produced, certified, small, mechanically simple, and adaptable to both invasive tubing and masks. The OPEN LUNG ventilator will use micro-electronics to sense and control air pressure and flow, with the goal to enable semi-autonomous operation.
-
-![Open Lung ventilator][36]
-
-Open Lung [on GitLab][37]
-
-This early-stage project boasts a large team with hundreds of contributors, led by: Colin Keogh, David Pollard, Connall Laverty, and Gui Calavanti. It is shared under a [GPLv3.0 license][38].
-
-#### Pandemic Ventilator
-
-The [Pandemic Ventilator][39] is a DIY ventilator prototype. Like the RepRap project, it uses commonly available hardware components in its design. The project was uploaded by user Panvent to Instructables more than 10 years ago, and there are six major steps to producing it. The project is shared under a [CC BY-NC-SA license][39]. This video shows the system in action:
-
-#### Folding at Home
-
-[Folding at Home][40] is a distributed computing project for simulating protein dynamics, including the process of protein folding and the movements of proteins implicated in a variety of diseases. It is a call-to-action for citizen scientists, researchers, and volunteers to use their computers at home to help run simulations, similar to the decommissioned [SETI@Home project][41]. If you're a technologist with capable computer hardware, Folding at Home is for you.
-
-![Markov state model][42]
-
-Vincent Voelz, CC BY-SA 3.0
-
-Folding at Home uses Markov state models (shown above) to model the possible shapes and folding pathways a protein can take in order to look for new therapeutic opportunities. You can find out more about the project in Washington University biophysicist Greg Bowman's post on [how it works and how you can help][43].
-
-The project involves a consortium of academic laboratories, contributors, and corporate sponsors from many countries, including Hong Kong, Croatia, Sweden, and the United States. Folding at Home is shared under a [mix of GPL and proprietary licenses][44] on [GitHub][45] and is multi-platform for Windows, macOS, and GNU/Linux (e.g., Debian, Ubuntu, Mint, RHEL, CentOS, Fedora).
-
-### Many other interesting projects
-
-These projects are just a fraction of the activity happening in the open hardware space to solve or treat COVID-19. In researching this article, I discovered other projects worth exploring, such as:
-
- * [Open source ventilators, oxygen concentrators, etc.][46] by Coronavirus Tech Handbook
- * [Helpful engineering][47] by ProjectOpenAir
- * [Open source ventilator hackathon][48] on Hackaday
- * [Specifications for simple open source mechanical ventilator][49] by Johns Hopkins emergency medicine resident Julian Botta
- * [Coronavirus-related phishing, malware, and randomware on the rise][50] by Shannon Morse
- * [Converting a low-cost CPAP blower into a rudimentary ventilator][51] by jcl5m1
- * [Forum A.I.R.E. discussion on open respirators and fans][52] (Spanish/español)
- * [Special Issue on Open-Source COVID19 Medical Hardware][53] by Elsevier HardwareX
-
-
-
-These projects are based all over the world, and this type of global cooperation is exactly what we need, as the virus ignores borders. The novel coronavirus pandemic affects countries at different times and in different ways, so we need a distributed approach.
-
-As my colleague Steven Abadie and I write in the [OSHdata 2020 Report][54], the open source hardware movement is a global movement. Participating individuals and organizations with certified projects are located in over 35 countries around the world and in every hemisphere.
-
-![Open source hardware map][55]
-
-OSHdata, CC BY-SA 4.0 International
-
-If you are interested in joining this conversation with open source hardware developers around the world, join the [Open Hardware Summit Discord][56] server with a dedicated channel for conversations about COVID-19. You can find roboticists, designers, artists, firmware and mechanical engineers, students, researchers, and others who are fighting this war together. We hope to see you there.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/open-hardware-covid19
-
-作者:[Harris Kenny][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/harriskenny
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/health_heartbeat.png?itok=P-GXea-p (open on blue background with heartbeat symbol)
-[2]: https://opensource.com/resources/what-open-hardware
-[3]: https://reprap.org/wiki/RepRap
-[4]: https://www.opensourceecology.org/
-[5]: https://www.osbeehives.com/
-[6]: https://www.scmp.com/news/hong-kong/health-environment/article/3052135/polytechnic-university-lab-3d-printing-face
-[7]: https://www.3dprintingmedia.network/covid-19-3d-printed-valve-for-reanimation-device/
-[8]: https://www.3dprintingmedia.network/materialise-shows-3d-printed-door-opener-for-coronavirus-containment-efforts/
-[9]: https://news.yahoo.com/stitch-time-czechs-sew-combat-virus-mask-shortage-205213804.html
-[10]: http://tapster.io/
-[11]: https://opensource.com/life/15/5/arduino-or-raspberry-pi
-[12]: https://t.co/bFogaekehM
-[13]: https://twitter.com/JIMrichards1010/status/1239140710558969857?ref_src=twsrc%5Etfw
-[14]: http://Healthcare.gov
-[15]: https://www.marktysonlaw.com/
-[16]: https://opentrons.com/
-[17]: https://blog.opentrons.com/testing-for-covid-19-with-opentrons/
-[18]: https://opensource.com/sites/default/files/uploads/opentrons.png (Opentrons roadmap graphic)
-[19]: https://www.fda.gov/regulatory-information/search-fda-guidance-documents/policy-diagnostics-testing-laboratories-certified-perform-high-complexity-testing-under-clia-prior
-[20]: https://github.com/Opentrons/opentrons/blob/edge/LICENSE
-[21]: https://www.chaibio.com/openqpcr
-[22]: https://en.wikipedia.org/wiki/Polymerase_chain_reaction
-[23]: https://github.com/chaibio/chaipcr
-[24]: https://beagleboard.org/bone
-[25]: https://openpcr.org/
-[26]: https://github.com/jperfetto/OpenPCR/blob/master/license.txt
-[27]: https://opensource.com/sites/default/files/uploads/openpcr.png (OpenPCR)
-[28]: https://github.com/GenericLab/WildOpenPCR
-[29]: http://www.gaudi.ch/GaudiLabs/?page_id=328
-[30]: https://github.com/GenericLab/WildOpenPCR/blob/master/license.txt
-[31]: http://gaudi.ch/PocketPCR/
-[32]: https://opensource.com/sites/default/files/uploads/pocketpcr.png (PocketPCR)
-[33]: https://github.com/GaudiLabs/PocketPCR/blob/master/LICENSE
-[34]: https://gitlab.com/TrevorSmale/low-resource-ambu-bag-ventilor
-[35]: https://en.wikipedia.org/wiki/Bag_valve_mask
-[36]: https://opensource.com/sites/default/files/uploads/open-lung.png (Open Lung ventilator)
-[37]: https://gitlab.com/TrevorSmale/low-resource-ambu-bag-ventilor/-/blob/master/images/CONCEPT_1_MECH.png
-[38]: https://gitlab.com/TrevorSmale/low-resource-ambu-bag-ventilor/-/blob/master/LICENSE
-[39]: https://www.instructables.com/id/The-Pandemic-Ventilator/
-[40]: https://foldingathome.org/
-[41]: https://setiathome.ssl.berkeley.edu/
-[42]: https://opensource.com/sites/default/files/uploads/foldingathome.png (Markov state model)
-[43]: https://foldingathome.org/2020/03/15/coronavirus-what-were-doing-and-how-you-can-help-in-simple-terms/
-[44]: https://en.wikipedia.org/wiki/Folding@home
-[45]: https://github.com/FoldingAtHome
-[46]: https://coronavirustechhandbook.com/hardware
-[47]: https://app.jogl.io/project/121#about
-[48]: https://hackaday.com/2020/03/12/ultimate-medical-hackathon-how-fast-can-we-design-and-deploy-an-open-source-ventilator/
-[49]: https://docs.google.com/document/d/1FNPwrQjB1qW1330s5-S_-VB0vDHajMWKieJRjINCNeE/edit?fbclid=IwAR3ugu1SGMsacwKi6ycAKJFOMduInSO4WVM8rgmC4CgMJY6cKaGBNR14mpM
-[50]: https://www.youtube.com/watch?v=dmQ1twpPpXA
-[51]: https://github.com/jcl5m1/ventilator
-[52]: https://foro.coronavirusmakers.org/
-[53]: https://www.journals.elsevier.com/hardwarex/call-for-papers/special-issue-on-open-source-covid19-medical-hardware
-[54]: https://oshdata.com/2020-report
-[55]: https://opensource.com/sites/default/files/uploads/oshdata-country.png (Open source hardware map)
-[56]: https://discord.gg/duAtG5h
diff --git a/sources/tech/20200320 Build a private social network with a Raspberry Pi.md b/sources/tech/20200320 Build a private social network with a Raspberry Pi.md
deleted file mode 100644
index 7917add925..0000000000
--- a/sources/tech/20200320 Build a private social network with a Raspberry Pi.md
+++ /dev/null
@@ -1,373 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Build a private social network with a Raspberry Pi)
-[#]: via: (https://opensource.com/article/20/3/raspberry-pi-open-source-social)
-[#]: author: (Giuseppe Cassibba https://opensource.com/users/peppe8o)
-
-Build a private social network with a Raspberry Pi
-======
-Step-by-step instructions on how to create your own social network with
-low-cost hardware and simple setup.
-![Team of people around the world][1]
-
-Social networks have revolutionized people's lives in the last several years. People use social channels every day to stay connected with friends and family. But a common question remains regarding privacy and data security. Even if social networks have created complex privacy policies to protect users, maintaining your data in your own server is always the best option if you don't want to make them available to the public.
-
-Again, a Raspberry Pi—Raspbian Lite version can be very versatile to help you put a number of useful home services (see also my [Raspberry Pi projects][2] article) in place. Some addictive features can be achieved by searching for open source software and testing it with this fantastic device. An interesting example to try is installing OpenSource Social Network in your Raspberry Pi.
-
-### What Is OpenSource Social Network?
-
-[OpenSource Social Network][3] (OSSN) is a rapid-development social networking software written in PHP, that essentially allows you to make a social networking website. OSSN can be used to build different types of social apps, such as:
-
- * Private Intranets
- * Public/Open Networks
- * Community
-
-
-
-OSSN supports features like:
-
- * Photos
- * Profile
- * Friends
- * Smileys
- * Search
- * Chat
-
-
-
-OSSN runs on a LAMP server. It has very poor hardware requirements, but an amazing user interface, which is also mobile-friendly.
-
-### What we need
-
-This project is very simple and, because we're installing only remote web services, we only need a few cheap parts. I'm going to use a Raspberry Pi 3 model B+, but it should also work with Raspberry Pi 3 model A+ or newer boards.
-
-Hardware:
-
- * Raspberry Pi 3 model B+ with its power supply
- * a micro SD card (better if it is a performing card, at least 16GB)
- * a Desktop PC with an SFTP software (for example, the free [Filezilla][4]) to transfer installation packages into your RPI.
-
-
-
-### Step-by-step procedure
-
-We'll start by setting up a classic LAMP server. We'll then set up database users and install OpenSource Social Network.
-
-#### 1\. Install Raspbian Buster Lite OS
-
-For this step, you can simply follow my [Install Raspbian Buster Lite in your Raspberry Pi][5] article.
-
-Make sure that your system is up to date. Connect via ssh terminal and type following commands:
-
-
-```
-sudo apt-get update
-sudo apt-get upgrade
-```
-
-2\. Install LAMP server
-
-LAMP (Linux–Apache–Mysql–Php) servers usually come with the MySQL database. In our project, we'll use MariaDB instead, because it is lighter and works with Raspberry Pi.
-
-#### 3\. Install Apache server:
-
-
-```
-`sudo apt-get install apache2 -y`
-```
-
-You should now be able to check that Apache installation has gone correctly by browsing http://<<YouRpiIPAddress>>:
-
-![][6]
-
-#### 4\. Install PHP:
-
-
-```
-`sudo apt-get install php -y`
-```
-
-5\. Install MariaDB server and PHP connector:
-
-
-```
-`sudo apt-get install mariadb-server php-mysql -y`
-```
-
-6\. Install PhpMyAdmin:
-
-PhpMyAdmin is not mandatory in OpenSource Social Network, but I suggest that you install it because it simplifies database management.
-
-
-```
-`sudo apt-get install phpmyadmin`
-```
-
-In the phpMyAdmin setup screen, take the following steps:
-
- * Select apache (mandatory) with space and press OK.
- * Select Yes to configure the database for phpMyAdmin with dbconfig-common.
- * Enter your favorite phpMyAdmin password and press OK.
- * Enter your phpMyAdmin password again to confirm and press OK
-
-
-
-#### 7\. Grant phpMyAdmin user DB privileges to manage DBs:
-
-We'll connect to MariaDB with root user (default password is empty) to grant permissions. Remember to use semicolons at the end of each command row as shown below:
-
-
-```
-sudo mysql -uroot -p
-grant all privileges on *.* to 'phpmyadmin'@'localhost';
-flush privileges;
-quit
-```
-
-8\. Finally, restart Apache service:
-
-
-```
-`sudo systemctl restart apache2.service`
-```
-
-And check that phpMyAdmin is working by browsing http://<<YouRpiIPAddress>>/phpmyadmin/.
-
-![][7]
-
-Default phpMyAdmin login credentials are:
-
- * user: phpmyadmin
- * password: the one you set up in the phpMyAdmin installation step
-
-
-
-### Installing other open source social network-required packages and setting up PHP
-
-We need to prepare our system for OpenSource Social Network's first setup wizard. Required packages are:
-
- * PHP version any of 5.6, 7.0, 7.1
- * MYSQL 5 OR >
- * APACHE
- * MOD_REWRITE
- * PHP Extensions cURL & Mcrypt should be enabled
- * PHP GD Extension
- * PHP ZIP Extension
- * PHP settings allow_url_fopen enabled
- * PHP JSON Support
- * PHP XML Support
- * PHP OpenSSL
-
-
-
-So we'll install them with following terminal commands:
-
-
-```
-`sudo apt-get install php7.3-curl php7.3-gd php7.3-zip php7.3-json php7.3-xml`
-```
-
-#### 1\. Enable MOD_REWRITE:
-
-
-```
-`sudo a2enmod rewrite`
-```
-
-2\. Edit default Apache config to use mod_rewrite:
-
-
-```
-`sudo nano /etc/apache2/sites-available/000-default.conf`
-```
-
-3\. Add the section so that your **000-default.conf** file appears like the following (excluding comments):
-
-
-```
-<VirtualHost *:80>
- ServerAdmin webmaster@localhost
- DocumentRoot /var/www/html
- ErrorLog ${APACHE_LOG_DIR}/error.log
- CustomLog ${APACHE_LOG_DIR}/access.log combined
- # SECTION TO ADD --------------------------------
- <Directory /var/www/html>
- Options Indexes FollowSymLinks MultiViews
- AllowOverride All
- Require all granted
- </Directory>
- # END SECTION TO ADD --------------------------------
-</VirtualHost>
-```
-
-4\. Install Mcrypt:
-
-
-```
-sudo apt install php-dev libmcrypt-dev php-pear
-sudo pecl channel-update pecl.php.net
-sudo pecl install mcrypt-1.0.2
-```
-
-5\. Enable Mcrypt module by adding (or uncommenting) “extension=mcrypt.so" in "/etc/php/7.3/apache2/php.ini":
-
-
-```
-`sudo nano /etc/php/7.3/apache2/php.ini`
-```
-
-**allow_url_fopen** should be already enabled in "/etc/php/7.3/apache2/php.ini". OpenSSL should be already installed in php7.3.
-
-#### 6\. Another setting that I suggest is editing the PHP max upload file size up to 16 MB:
-
-
-```
-`sudo nano /etc/php/7.3/apache2/php.ini`
-```
-
-7\. Look for the row with the **upload_max_filesize** parameter and set it as the following:
-
-
-```
-`upload_max_filesize = 16M`
-```
-
-8\. Save and exit. Restart Apache:
-
-
-```
-`sudo systemctl restart apache2.service`
-```
-
-### Install OSSN
-
-#### 1\. Create DB and set up user:
-
-Go back to phpmyadmin web page (browse "http://<<YourRpiIPAddress>>/phpmyadmin/") and login:
-
-User: phpmyadmin
-
-Password: the one set up in phpmyadmin installation step
-
-Click on database tab:
-
-![][8]
-
-Create a database and take note of the database name, as you will be required to enter it later in the installation process.
-
-![][9]
-
-It's time to create a database user for OSSN. In this example, I'll use the following credentials:
-
-User: ossn_db_user
-
-Password: ossn_db_password
-
-So, terminal commands will be (root password is still empty, if not changed by you before):
-
-
-```
-sudo mysql -uroot -p
-CREATE USER 'ossn_db_user'@'localhost' IDENTIFIED BY 'ossn_db_password';
-GRANT ALL PRIVILEGES ON ossn_db.* TO 'ossn_db_user'@'localhost';
-flush privileges;
-quit
-```
-
-2\. Install OSSN software:
-
-Download the OSSN installation zip file from the [OSSN download page][10] on your local PC. At the time of this writing, this file is named "ossn-v5.2-1577836800.zip."
-
-Using your favorite SFTP software, transfer the entire zip file via SFTP to a new folder in the path "/home/pi/download" on your Raspberry Pi. Common (default) SFP connection parameters are:
-
- * Host: your Raspberry Pi IP address
- * User: pi
- * Password: raspberry (if you didn't change the pi default password)
- * Port: 22
-
-
-
-Back to terminal:
-
-
-```
-cd /home/pi/download/ #Enter directory where OSSN installation files have been transferred
-unzip ossn-v5.2-1577836800.zip #Extracts all files from zip
-cd /var/www/html/ #Enter Apache web directory
-sudo rm index.html #Removes Apache default page - we'll use OSSN one
-sudo cp -R /home/pi/download/ossn-v5.2-1577836800/* ./ #Copy installation files to web directory
-sudo chown -R www-data:www-data ./
-```
-
-Create a data folder:OSSN requires a folder to store data. OSSN suggests, for security reasons, to create this folder outside of the published document root. So, we'll create this opt-in folder and give grants:
-
-
-```
-sudo mkdir /opt/ossn_data
-sudo chown -R www-data:www-data /opt/ossn_data/
-```
-
-Browse http://<<YourRpiIPAddress>> to start the installation wizard:
-
-![][11]
-
-All checks should be fine. Click the Next button at the end of the page.
-
-![][12]
-
-Read the license validation and click the Next button at the end of the page to accept.
-
-![][13]
-
-Enter the database user, password, and the DB name you chose. Remember also to enter the OSSN data folder. Press Install.
-
-![][14]
-
-Enter your admin account information and press the Create button.
-
-![][15]
-
-Everything should be fine now. Press Finish to access the administration dashboard.
-
-![][16]
-
-So, administration panel can be reached with URL "http://<<YourRpiIPAddress>>/administrator" while user link will be "http://<<YourRpiIPAddress>>".
-
-![][17]
-
-_This article was originally published at [peppe8o.com][18]. Reposted with permission._
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/raspberry-pi-open-source-social
-
-作者:[Giuseppe Cassibba][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/peppe8o
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/team_global_people_gis_location.png?itok=Rl2IKo12 (Team of people around the world)
-[2]: https://peppe8o.com/2019/04/best-raspberry-pi-projects-with-open-source-software/
-[3]: https://www.opensource-socialnetwork.org/
-[4]: https://filezilla-project.org/
-[5]: https://peppe8o.com/2019/07/install-raspbian-buster-lite-in-your-raspberry-pi/
-[6]: https://opensource.com/sites/default/files/uploads/ossn_1_0.jpg
-[7]: https://opensource.com/sites/default/files/uploads/ossn_2.jpg
-[8]: https://opensource.com/sites/default/files/uploads/ossn_3.jpg
-[9]: https://opensource.com/sites/default/files/uploads/ossn_4.jpg
-[10]: https://www.opensource-socialnetwork.org/download
-[11]: https://opensource.com/sites/default/files/uploads/ossn_5.jpg
-[12]: https://opensource.com/sites/default/files/uploads/ossn_6.jpg
-[13]: https://opensource.com/sites/default/files/uploads/ossn_7.jpg
-[14]: https://opensource.com/sites/default/files/uploads/ossn_8.jpg
-[15]: https://opensource.com/sites/default/files/uploads/ossn_9.jpg
-[16]: https://opensource.com/sites/default/files/uploads/ossn_10.jpg
-[17]: https://opensource.com/sites/default/files/uploads/ossn_11.jpg
-[18]: https://peppe8o.com/private-social-network-with-raspberry-pi-and-opensource-social-network/
diff --git a/sources/tech/20200320 Control the firewall at the command line.md b/sources/tech/20200320 Control the firewall at the command line.md
deleted file mode 100644
index fb49292d28..0000000000
--- a/sources/tech/20200320 Control the firewall at the command line.md
+++ /dev/null
@@ -1,138 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (tinyeyeser )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Control the firewall at the command line)
-[#]: via: (https://fedoramagazine.org/control-the-firewall-at-the-command-line/)
-[#]: author: (Paul W. Frields https://fedoramagazine.org/author/pfrields/)
-
-Control the firewall at the command line
-======
-
-![][1]
-
-A network _firewall_ is more or less what it sounds like: a protective barrier that prevents unwanted network transmissions. They are most frequently used to prevent outsiders from contacting or using network services on a system. For instance, if you’re running a laptop at school or in a coffee shop, you probably don’t want strangers poking around on it.
-
-Every Fedora system has a firewall built in. It’s part of the network functions in the Linux kernel inside. This article shows you how to change its settings using _firewall-cmd_.
-
-### Network basics
-
-This article can’t teach you [everything][2] about computer networks. But a few basics suffice to get you started.
-
-Any computer on a network has an _IP address_. Think of this just like a mailing address that allows correct routing of data. Each computer also has a set of _ports_, numbered 0-65535. These are not physical ports; instead, you can think of them as a set of connection points at the address.
-
-In many cases, the port is a [standard number][3] or range depending on the application expected to answer. For instance, a web server typically reserves port 80 for non-secure HTTP communications, and/or 443 for secure HTTPS. The port numbers under 1024 are reserved for system and well-known purposes, ports 1024-49151 are registered, and ports 49152 and above are usually ephemeral (used only for a short time).
-
-Each of the two most common protocols for Internet data transfer, [TCP][4] and [UDP][5], have this set of ports. TCP is used when it’s important that all data be received and, if it arrives out of order, reassembled in the right order. UDP is used for more time-sensitive services that can withstand losing some data.
-
-An application running on the system, such as a web server, reserves one or more ports (as seen above, 80 and 443 for example). Then during network communication, a host establishes a connection between a source address and port, and the destination address and port.
-
-A network firewall can block or permit transmissions of network data based on rules like address, port, or other criteria. The _firewall-cmd_ utility lets you interact with the rule set to view or change how the firewall works.
-
-### Firewall zones
-
-To verify the firewall is running, use this command with [sudo][6]. (In fairness, you can run _firewall-cmd_ without the _sudo_ command in environments where [PolicyKit][7] is running.)
-
-```
-$ sudo firewall-cmd --state
-running
-```
-
-The firewalld service supports any number of _zones_. Each zone can have its own settings and rules for protection. In addition, each network interface can be placed in any zone individually The default zone for an external facing interface (like the wifi or wired network card) on a Fedora Workstation is the _FedoraWorkstation_ zone.
-
-To see what zones are active, use the _–get-active-zones_ flag. On this system, there are two network interfaces, a wired Ethernet card _wlp2s0_ and a virtualization (libvirt) bridge interface _virbr0_:
-
-```
-$ sudo firewall-cmd --get-active-zones
-FedoraWorkstation
- interfaces: wlp2s0
-libvirt
- interfaces: virbr0
-```
-
-To see the default zone, or all the defined zones:
-
-```
-$ sudo firewall-cmd --get-default-zone
-FedoraWorkstation
-$ sudo firewall-cmd --get-zones
-FedoraServer FedoraWorkstation block dmz drop external home internal libvirt public trusted work
-```
-
-To see the services the firewall is allowing other systems to access in the default zone, use the _–list-services_ flag. Here is an example from a customized system; you may see something different.
-
-```
-$ sudo firewall-cmd --list-services
-dhcpv6-client mdns samba-client ssh
-```
-
-This system has four services exposed. Each of these has a well-known port number. The firewall recognizes them by name. For instance, the _ssh_ service is associated with port 22.
-
-To see other port settings for the firewall in the current zone, use the _–list-ports_ flag. By the way, you can always declare the zone you want to check:
-
-```
-$ sudo firewall-cmd --list-ports --zone=FedoraWorkstation
-1025-65535/udp 1025-65535/tcp
-```
-
-This shows that ports 1025 and above (both UDP and TCP) are open by default.
-
-### Changing zones, ports, and services
-
-The above setting is a design decision.* It ensures novice users can use network facing applications they install. If you know what you’re doing and want a more protective default, you can move the interface to the _FedoraServer_ zone, which prohibits any ports not explicitly allowed. _(**Warning:** if you’re using the host via the network, you may break your connection — meaning you’ll have to go to that box physically to make further changes!)_
-
-```
-$ sudo firewall-cmd --change-interface= --zone=FedoraServer
-success
-```
-
-* _This article is not the place to discuss that decision, which went through many rounds of review and debate in the Fedora community. You are welcome to change settings as needed._
-
-If you want to open a well-known port that belongs to a service, you can add that service to the default zone (or use _–zone_ to adjust a different zone). You can add more than one at once. This example opens up the well-known ports for your web server for both HTTP and HTTPS traffic, on ports 80 and 443:
-
-```
-$ sudo firewall-cmd --add-service=http --add-service=https
-success
-```
-
-Not all services are defined, but many are. To see the whole list, use the _–get-services_ flag.
-
-If you want to add specific ports, you can do that by number and protocol as well. (You can also combine _–add-service_ and _–add-port_ flags, as many as necessary.) This example opens up the UDP service for a network boot service:
-
-```
-$ sudo firewall-cmd --add-port=67/udp
-success
-```
-
-**Important:** If you want your changes to be effective after you reboot your system or restart the firewalld service, you **must** add the _–permanent_ flag to your commands. The examples here only change the firewall until one of those events next happens.
-
-These are just some of the many functions of the _firewall-cmd_ utility and the firewalld service. There is much more information on firewalld at the project’s [home page][8] that’s worth reading and trying out.
-
-* * *
-
-_Photo by [Jakob Braun][9] on [Unsplash][10]._
-
---------------------------------------------------------------------------------
-
-via: https://fedoramagazine.org/control-the-firewall-at-the-command-line/
-
-作者:[Paul W. Frields][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://fedoramagazine.org/author/pfrields/
-[b]: https://github.com/lujun9972
-[1]: https://fedoramagazine.org/wp-content/uploads/2020/03/firewall-cmd-816x345.jpg
-[2]: https://en.wikipedia.org/wiki/Portal:Internet
-[3]: https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
-[4]: https://en.wikipedia.org/wiki/Transmission_Control_Protocol
-[5]: https://en.wikipedia.org/wiki/User_Datagram_Protocol
-[6]: https://fedoramagazine.org/howto-use-sudo/
-[7]: https://en.wikipedia.org/wiki/Polkit
-[8]: https://firewalld.org/
-[9]: https://unsplash.com/@jakobustrop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
-[10]: https://unsplash.com/s/photos/brick-wall?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
diff --git a/sources/tech/20200322 Meet DebianDog - Puppy sized Debian Linux.md b/sources/tech/20200322 Meet DebianDog - Puppy sized Debian Linux.md
deleted file mode 100644
index ea2b2d1f7c..0000000000
--- a/sources/tech/20200322 Meet DebianDog - Puppy sized Debian Linux.md
+++ /dev/null
@@ -1,120 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (robsean)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Meet DebianDog – Puppy sized Debian Linux)
-[#]: via: (https://itsfoss.com/debiandog/)
-[#]: author: (John Paul https://itsfoss.com/author/john/)
-
-Meet DebianDog – Puppy sized Debian Linux
-======
-
-Recently I stumbled upon an intriguing Linux project. This project aims to create small live CDs for Debian and Debian-based systems, similar to the [Puppy Linux project][1]. Let’s take a look at DebianDog.
-
-### What is DebianDog?
-
-As it says on the tin, [DebianDog][2] “is a small Debian Live CD shaped to look like Puppy and act like Puppy. Debian structure and Debian behaviour are untouched and Debian documentation is 100% valid for DebianDog. You have access to all Debian repositories using apt-get or synaptic.”
-
-![DebianDog Jessie][3]
-
-For those of you who are not familiar with [Puppy Linux][1], the project is “a collection of multiple Linux distributions, built on the same shared principles”. Those principles are to be fast, small (300 MB or less), and easy to use. There are versions of Puppy Linux built to support Ubuntu, Slackware, and Raspbian packages.
-
-The major difference between DebianDog and Puppy Linux is that Puppy Linux has its own package manager [the [Puppy Package Manager][4]]. As stated above, DebianDog using the Debian package manager and packages. Even the DebianDog website tries to make that clear: “It is not Puppy Linux and it has nothing to do with Puppy based on Debian.”
-
-### Why should anyone use DebianDog?
-
-The main reason to install DebianDog (or any of its derivatives) would be to restore an older system to operability. Every entry on DebianDog has a 32-bit option. They also have lighter desktop environments/window managers, such as [Openbox][5] or the [Trinity Desktop][6] environment. Most of those also have an alternative to systemd. They also come with lighter applications installed, such as [PCManFM][7].
-
-### What versions of DebianDog are available?
-
-Though DebianDog was the first in the series, the project is called ‘Dog Linux’ and provides various ‘Dog variants’ on popular distributions based on Debian and Ubuntu.
-
-#### DebianDog Jessie
-
-The first (and original) version of DebianDog is DebianDog Jessie. There are two [32-bit versions][8] of it. One uses [Joe’s Window Manager (JWM)][9] as default and the other uses XFCE. Both systemd and sysvinit are available. There is also a [64-bit version][10]. DebianDog Jessie is based on Debian 8.0 (codename Jessie). Support for Debian 8.0 ends on June 30th, 2020, so install with caution.
-
-![TrinityDog][11]
-
-#### StretchDog
-
-[Stret][12][c][12][hDog][12] is based on Debian 9.0 (codename Stretch). It is available in 32 and 64-bit. Openbox is the default window manager, but we can also switch to JWM. Support for Debian 9.0 ends on June 30th, 2022.
-
-#### BusterDog
-
-[BusterDog][13] is interesting. It is based on [Debian 10][14] (codename Buster). It does not use systemd, instead, it uses [elogind][15] just like [AntiX][16]. Support for Debian 10.0 ends on June 2024.
-
-#### MintPup
-
-[MintPup][17] is based on [Linux Mint][18] 17.1. This LiveCD is 32-bit only. You can also access all of the “Ubuntu/Mint repositories using apt-get or synaptic”. Considering that Mint 17 has reached end of life, this version must be avoided.
-
-#### XenialDog
-
-There are both [32-bit][19] and [64-bit versions][20] of this spin based on the Ubuntu 16.04 LTS. Both versions come with Openbox as default with JWM as an option. Support for Ubuntu 16.04 LTS ends in April of 2021, so install with caution.
-
-#### TrinityDog
-
-There are two versions of the [TrintyDog][21] spin. One is based on Debian 8 and the other is based on Debian 9. Both are 32-bit and both use the [Trinity Desktop Environment][6], thus the name.
-
-![BionicDog][22]
-
-#### BionicDog
-
-As you should be able to guess by the name. [BionicDog][23] is based on [Ubuntu 18.04 LTS][24]. The main version of this spin has both 32 and 64-bit with Openbox as the default window manager. There is also a version that uses the [Cinnamon desktop][25] and is only 64-bit.
-
-### Final Thoughts
-
-I like any [Linux project that wants to make older systems usable][26]. However, most of the operating systems available through DebianDog are no longer supported or nearing the end of their life span. This makes it less than useful for the long run.
-
-**I wouldn’t really advise to use it on your main computer.** Try it in live USB or on a spare system. Also, [you can create][27] your own LiveCD spin if you want to take advantage of a newer base system.
-
-Somehow I keep on stumbling across obscure Linux distributions like [FatDog64][28], [4M Linux][29] and [Vipper Linux][30]. Even though I may not always recommend them to use, it’s still good to know about the existence of such projects.
-
-What are your thoughts on the DebianDog? What is your favorite Puppy-syle OS? Please let us know in the comments below.
-
-If you found this article interesting, please take a minute to share it on social media, Hacker News or [Reddit][31].
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/debiandog/
-
-作者:[John Paul][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/john/
-[b]: https://github.com/lujun9972
-[1]: http://puppylinux.com/
-[2]: https://debiandog.github.io/doglinux/
-[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/DebianDog-Jessie.jpg?fit=800%2C600&ssl=1
-[4]: http://wikka.puppylinux.com/PPM?redirect=no
-[5]: http://openbox.org/wiki/Main_Page
-[6]: https://www.trinitydesktop.org/
-[7]: https://wiki.lxde.org/en/PCManFM
-[8]: https://debiandog.github.io/doglinux/zz01debiandogjessie.html
-[9]: https://en.wikipedia.org/wiki/JWM
-[10]: https://debiandog.github.io/doglinux/zz02debiandog64.html
-[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/TrinityDog.jpg?ssl=1
-[12]: https://debiandog.github.io/doglinux/zz02stretchdog.html
-[13]: https://debiandog.github.io/doglinux/zz03busterdog.html
-[14]: https://itsfoss.com/debian-10-buster/
-[15]: https://github.com/elogind/elogind
-[16]: https://antixlinux.com/
-[17]: https://debiandog.github.io/doglinux/zz04mintpup.html
-[18]: https://linuxmint.com/
-[19]: https://debiandog.github.io/doglinux/zz05xenialdog.html
-[20]: https://debiandog.github.io/doglinux/zz05zxenialdog.html
-[21]: https://debiandog.github.io/doglinux/zz06-trinitydog.html
-[22]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/BionicDog.jpg?ssl=1
-[23]: https://debiandog.github.io/doglinux/zz06-zbionicdog.html
-[24]: https://itsfoss.com/ubuntu-18-04-released/
-[25]: https://en.wikipedia.org/wiki/Cinnamon_(desktop_environment)
-[26]: https://itsfoss.com/lightweight-linux-beginners/
-[27]: https://github.com/DebianDog/MakeLive
-[28]: https://itsfoss.com/fatdog64-linux-review/
-[29]: https://itsfoss.com/4mlinux-review/
-[30]: https://itsfoss.com/viperr-linux-review/
-[31]: https://reddit.com/r/linuxusersgroup
diff --git a/sources/tech/20200323 Don-t love diff- Use Meld instead.md b/sources/tech/20200323 Don-t love diff- Use Meld instead.md
deleted file mode 100644
index e5049454e2..0000000000
--- a/sources/tech/20200323 Don-t love diff- Use Meld instead.md
+++ /dev/null
@@ -1,131 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: (geekpi)
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Don't love diff? Use Meld instead)
-[#]: via: (https://opensource.com/article/20/3/meld)
-[#]: author: (Ben Nuttall https://opensource.com/users/bennuttall)
-
-Don't love diff? Use Meld instead
-======
-Meld is a visual diff tool that makes it easier to compare and merge
-changes in files, directories, Git repos, and more.
-![Person drinking a hat drink at the computer][1]
-
-Meld is one of my essential tools for working with code and data files. It's a graphical diff tool, so if you've ever used the **diff** command and struggled to make sense of the output, [Meld][2] is here to help.
-
-Here is a brilliant description from the project's website:
-
-> "Meld is a visual diff and merge tool targeted at developers. Meld helps you compare files, directories, and version controlled projects. It provides two- and three-way comparison of both files and directories, and has support for many popular version control systems.
->
-> "Meld helps you review code changes and understand patches. It might even help you to figure out what is going on in that merge you keep avoiding."
-
-You can install Meld on Debian/Ubuntu systems (including Raspbian) with:
-
-
-```
-`$ sudo apt install meld`
-```
-
-On Fedora or similar, it's:
-
-
-```
-`$ sudo dnf install meld`
-```
-
-Meld is cross-platform—there's a [Windows install][3] using the [Chocolately][4] package manager. While it's not officially supported on macOS, there are [builds available for Mac][5], and you can install it on Homebrew with:
-
-
-```
-`$ brew cask install meld`
-```
-
-See Meld's homepage for [additional options][2].
-
-### Meld vs. the diff command
-
-If you have two similar files (perhaps one is a modified version of the other) and want to see the changes between them, you could run the **diff** command to see their differences in the terminal:
-
-![diff output][6]
-
-This example shows the differences between **conway1.py** and **conway2.py**. It's showing that I:
-
- * Removed the [shebang][7] and second line
- * Removed **(object)** from the class declaration
- * Added a docstring to the class
- * Swapped the order of **alive** and **neighbours == 2** in a method
-
-
-
-Here's the same example using the **meld** command. You can run the same comparison from the command line with:
-
-
-```
-`$ meld conway1.py conway2.py`
-```
-
-![Meld output][8]
-
-Much clearer!
-
-You can easily see changes and merge changes between files by clicking the arrows (they work both ways). You can even edit the files live (Meld doubles up as a simple text editor with live comparisons as you type)—just be sure to save before you close the window.
-
-You can even compare and edit three different files:
-
-![Comparing three files in Meld][9]
-
-### Meld's Git-awareness
-
-Hopefully, you're using a version control system like [Git][10]. If so, your comparison isn't between two different files but to find differences between the current working file and the one Git knows. Meld understands this, so if you run **meld conway.py**, where **conway.py** is known by Git, it'll show you any changes made since the last Git commit:
-
-![Comparing Git files in Meld][11]
-
-You can see changes made in the current version (on the right) and the repository version (on the left). You can see I deleted a method and added a parameter and a loop since the last commit.
-
-If you run **meld .**, you'll see all the changes in the current directory (or the whole repository, if you're in its root):
-
-![Meld . output][12]
-
-You can see a single file is modified, another file is unversioned (meaning it's new to Git, so I need to **git add** the file before comparing it), and lots of other unmodified files. Various display options are provided by icons along the top.
-
-You can also compare two directories, which is sometimes handy:
-
-![Comparing directories in Meld][13]
-
-### Conclusion
-
-Even regular users can find comparisons with diff difficult to decipher. I find the visualizations Meld provides make a big difference in troubleshooting what's changed between files. On top of that, Meld comes with some helpful awareness of version control and helps you compare across Git commits without thinking much about it. Give Meld a go, and make troubleshooting a little easier on the eyes.
-
-* * *
-
-_This was originally published on Ben Nuttall's [Tooling blog][14] and is reused with permission._
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/meld
-
-作者:[Ben Nuttall][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/bennuttall
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
-[2]: https://meldmerge.org/
-[3]: https://chocolatey.org/packages/meld
-[4]: https://opensource.com/article/20/3/chocolatey
-[5]: https://yousseb.github.io/meld/
-[6]: https://opensource.com/sites/default/files/uploads/diff-output.png (diff output)
-[7]: https://en.wikipedia.org/wiki/Shebang_(Unix)
-[8]: https://opensource.com/sites/default/files/uploads/meld-output.png (Meld output)
-[9]: https://opensource.com/sites/default/files/uploads/meld-3-files.png (Comparing three files in Meld)
-[10]: https://opensource.com/resources/what-is-git
-[11]: https://opensource.com/sites/default/files/uploads/meld-git.png (Comparing Git files in Meld)
-[12]: https://opensource.com/sites/default/files/uploads/meld-directory-changes.png (Meld . output)
-[13]: https://opensource.com/sites/default/files/uploads/meld-directory-compare.png (Comparing directories in Meld)
-[14]: https://tooling.bennuttall.com/meld/
diff --git a/sources/tech/20200323 How to create a personal file server with SSH on Linux.md b/sources/tech/20200323 How to create a personal file server with SSH on Linux.md
deleted file mode 100644
index f758123bb1..0000000000
--- a/sources/tech/20200323 How to create a personal file server with SSH on Linux.md
+++ /dev/null
@@ -1,137 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (How to create a personal file server with SSH on Linux)
-[#]: via: (https://opensource.com/article/20/3/personal-file-server-ssh)
-[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
-
-How to create a personal file server with SSH on Linux
-======
-Connecting to a remote Linux system over SSH is just plain easy. Here's
-how to do it.
-![Hand putting a Linux file folder into a drawer][1]
-
-The Raspberry Pi makes for a useful and inexpensive home server for lots of things. I most often use the [Raspberry Pi as a print server][2] to share a laser printer with other devices in our home or as a personal file server to store copies of projects and other data.
-
-I use this file server in various ways. Let's say I'm working on a project, such as a new book, and I want to make a snapshot copy of my work and all my associated files. In that case, I simply copy my **BookProject** folder to a **BookBackup** folder on the file server.
-
-Or if I'm cleaning up my local files, and I discover some files that I don't really need but I'm not yet ready to delete, I'll copy them to a **KeepForLater** folder on the file server. That's a convenient way to remove clutter from my everyday Linux system and offload infrequently used files to my personal file server.
-
-Setting up a Raspberry Pi—or any Linux system—as a personal file server doesn't require configuring Network File System (NFS) or Common Internet File System (CIFS) or tinkering with other file-sharing systems such as WebDAV. You can easily set up a remote file server using SSH. And here's how.
-
-### Set up SSHD on the remote system
-
-Your Linux system probably has the SSH daemon (sshd) installed. It may even be running by default. If not, you can easily set up SSH through whatever control panel you prefer on your Linux distribution. I run [Fedora ARM][3] on my Raspberry Pi, and I can access the control panel remotely by pointing my Pi's web browser to port 9090. (On my home network, the Raspberry Pi's IP address is **10.0.0.11**, so I connect to **10.0.0.11:9090**.) If the SSH daemon isn't running by default, you can set it to start automatically in Services in the control panel.
-
-![sshd in the list of system services][4]
-
-You can find sshd in the list of system services.
-
-![slider to activate sshd][5]
-
-Click the slider to activate **sshd** if it isn't already.
-
-### Do you have an account?
-
-Make sure you have an account on the remote system. It might be the same as the username you use on your local system, or it could be something different.
-
-On the popular Raspbian distribution, the default account username is **pi**. But other Linux distributions may require you to set up a unique new user when you install it. If you don't know your username, you can use your distribution's control panel to create one. On my Raspberry Pi, I set up a **jhall** account that matches the username on my everyday Linux desktop machine.
-
-![Set up a new account on Fedora Server][6]
-
-If you use Fedora Server, click the **Create New Account** button to set up a new account.
-
-![Set password or SSH key][7]
-
-Don't forget to set a password or add a public SSH key.
-
-### Optional: Share your SSH public key
-
-If you exchange your public SSH key with the remote Linux system, you can log in without having to enter a password. This step is optional; you can use a password if you prefer.
-
-You can learn more about SSH keys in these Opensource.com articles:
-
- * [Tools for SSH key management][8]
- * [Graphically manage SSH keys with Seahorse][9]
- * [How to manage multiple SSH keys][10]
- * [How to enable SSH access using a GPG key for authentication][11]
-
-
-
-### Make a file manager shortcut
-
-Since you've started the SSH daemon on the remote system and set up your account username and password, all that's left is to map a shortcut to the other Linux system from your file manager. I use GNOME as my desktop, but the steps are basically the same for any Linux desktop.
-
-#### Make the initial connection
-
-In the GNOME file manager, look for the **+Other Locations** button in the left-hand navigation. Click that to open a **Connect to Server** prompt. Enter the address of the remote Linux server here, starting with the SSH connection protocol.
-
-![Creating a shortcut in GNOME file manager][12]
-
-The GNOME file manager supports a variety of connection protocols. To make a connection over SSH, start your server address with **sftp://** or **ssh://**.
-
-If your username is the same on your local Linux system and your remote Linux system, you can just enter the server's address and the folder location. To make my connection to the **/home/jhall** directory on my Raspberry Pi, I use:
-
-
-```
-`sftp://10.0.0.11/home/jhall`
-```
-
-![GNOME file manager Connect to Server][13]
-
-If your username is different, you can specify your remote system's username with an **@** sign before the remote system's address. To connect to a Raspbian system on the other end, you might use:
-
-
-```
-`sftp://pi@10.0.0.11/home/pi`
-```
-
-![GNOME file manager Connect to Server][14]
-
-If you didn't share your public SSH key, you may need to enter a password. Otherwise, the GNOME file manager should automatically open the folder on the remote system and let you navigate.
-
-![GNOME file manager connection][15]
-
-#### Create a shortcut so you can easily connect to the server later
-
-This is easy in the GNOME file manager. Right-click on the remote system's name in the navigation list, and select **Add Bookmark**. This creates a shortcut to the remote location.
-
-![GNOME file manager - adding bookmark][16]
-
-If you want to give the bookmark a more memorable name, you can right-click on the shortcut and choose **Rename**.
-
-### That's it!
-
-Connecting to a remote Linux system over SSH is just plain easy. And you can use the same method to connect to systems other than home file servers. I also have a shortcut that allows me to instantly access files on my provider's web server and another that lets me open a folder on my project server. SSH makes it a secure connection; all of my traffic is encrypted. Once I've opened the remote system over SSH, I can use the GNOME file manager to manage my remote files as easily as I'd manage my local folders.
-
---------------------------------------------------------------------------------
-
-via: https://opensource.com/article/20/3/personal-file-server-ssh
-
-作者:[Jim Hall][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://opensource.com/users/jim-hall
-[b]: https://github.com/lujun9972
-[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/yearbook-haff-rx-linux-file-lead_0.png?itok=-i0NNfDC (Hand putting a Linux file folder into a drawer)
-[2]: https://opensource.com/article/18/3/print-server-raspberry-pi
-[3]: https://arm.fedoraproject.org/
-[4]: https://opensource.com/sites/default/files/uploads/fedora-server-control-panel-sshd.png (sshd in the list of system services)
-[5]: https://opensource.com/sites/default/files/uploads/fedora-server-control-panel-sshd-service.png (slider to activate sshd)
-[6]: https://opensource.com/sites/default/files/uploads/fedora-server-control-panel-accounts_create-user.png (Set up a new account on Fedora Server)
-[7]: https://opensource.com/sites/default/files/uploads/fedora-server-control-panel-accounts.png (Set password or SSH key)
-[8]: https://opensource.com/article/20/2/ssh-tools
-[9]: https://opensource.com/article/19/4/ssh-keys-seahorse
-[10]: https://opensource.com/article/19/4/gpg-subkeys-ssh-manage
-[11]: https://opensource.com/article/19/4/gpg-subkeys-ssh
-[12]: https://opensource.com/sites/default/files/uploads/gnome-file-manager-other-locations.png (Creating a shortcut in GNOME file manager)
-[13]: https://opensource.com/sites/default/files/uploads/gnome-file-manager-other-sftp.png (GNOME file manager Connect to Server)
-[14]: https://opensource.com/sites/default/files/uploads/gnome-file-manager-other-sftp-username.png (GNOME file manager Connect to Server)
-[15]: https://opensource.com/sites/default/files/uploads/gnome-file-manager-remote-jhall.png (GNOME file manager connection)
-[16]: https://opensource.com/sites/default/files/uploads/gnome-file-manager-remote-jhall-add-bookmark.png (GNOME file manager - adding bookmark)
diff --git a/sources/tech/20200324 Audacious 4.0 Released With Qt 5- Here-s How to Install it on Ubuntu.md b/sources/tech/20200324 Audacious 4.0 Released With Qt 5- Here-s How to Install it on Ubuntu.md
deleted file mode 100644
index 53e7ea3fa6..0000000000
--- a/sources/tech/20200324 Audacious 4.0 Released With Qt 5- Here-s How to Install it on Ubuntu.md
+++ /dev/null
@@ -1,106 +0,0 @@
-[#]: collector: (lujun9972)
-[#]: translator: ( )
-[#]: reviewer: ( )
-[#]: publisher: ( )
-[#]: url: ( )
-[#]: subject: (Audacious 4.0 Released With Qt 5: Here’s How to Install it on Ubuntu)
-[#]: via: (https://itsfoss.com/audacious-4-release/)
-[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
-
-Audacious 4.0 Released With Qt 5: Here’s How to Install it on Ubuntu
-======
-
-[Audacious][1] is an open-source audio player available for multiple platforms that include Linux. Almost after 2 years of its last major release, Audacious 4.0 has arrived with some big changes.
-
-The latest release Audacious 4.0 comes with [Qt 5][2] UI by default. You can still go for the old GTK2 UI from the source – however, the new features will be added to the Qt UI only.
-
-Let’s take a look at what has changed and how to install the latest Audacious on your Linux system.
-
-### Audacious 4.0 Key Changes & Features
-
-![Audacious 4 Release][3]
-
-Of course, the major change would be the use of Qt 5 UI as the default. In addition to that, there are a lot of improvements and feature additions mentioned in their [official announcement post][4], here they are:
-
- * Clicking on playlist column headers sorts the playlist
- * Dragging playlist column headers changes the column order
- * Application-wide settings for volume and time step sizes
- * New option to hide playlist tabs
- * Sorting playlist by path now sorts folders after files
- * Implemented additional MPRIS calls for compatibility with KDE 5.16+
- * New OpenMPT-based tracker module plugin
- * New VU Meter visualization plugin
- * Added option to use a SOCKS network proxy
- * The Song Change plugin now works on Windows
- * New “Next Album” and “Previous Album” commands
- * The tag editor in Qt UI can now edit multiple files at once
- * Implemented equalizer presets window for Qt UI
- * Lyrics plugin gained the ability to save and load lyrics locally
- * Blur Scope and Spectrum Analyzer visualizations ported to Qt
- * MIDI plugin SoundFont selection ported to Qt
- * JACK output plugin gained some new options
- * Added option to endlessly loop PSF files
-
-
-
-If you didn’t know about it previously, you can easily get it installed and use the equalizer coupled with [LADSP][5] effects to tweak your music experience.
-
-![Audacious Winamp Classic Interface][6]
-
-### How to Install Audacious 4.0 on Ubuntu
-
-It is worth noting that the [unofficial PPA][7] is made available by [UbuntuHandbook][8]. You can simply follow the instructions below to install it on Ubuntu 16.04, 18.04, 19.10, and 20.04.
-
-1\. First, you have to add the PPA to your system by typing in the following command in the terminal:
-
-```
-sudo add-apt-repository ppa:ubuntuhandbook1/apps
-```
-
-3\. Next, you need to update/refresh the package information from the repositories/sources you have and proceed to install the app. Here’s how to do that:
-
-```
-sudo apt update
-sudo apt install audacious audacious-plugins
-```
-
-That’s it. You don’t have to do anything else. In either case, if you want to [remove the PPA and the software][9], just type in the following commands in order:
-
-```
-sudo add-apt-repository --remove ppa:ubuntuhandbook1/apps
-sudo apt remove --autoremove audacious audacious-plugins
-```
-
-You can also check out their GitHub page for more information on the source and potentially install it on other Linux distros as well, if that’s what you’re looking for.
-
-[Audacious Source Code][10]
-
-### Wrapping Up
-
-The new features and the Qt 5 UI switch should be a good thing to improve the user experience and the functionality of the audio player. If you’re a fan of the classic Winamp interface, it works just fine as well – but missing a few features as mentioned in their announcement post.
-
-You can try it out and let me know your thoughts in the comments below!
-
---------------------------------------------------------------------------------
-
-via: https://itsfoss.com/audacious-4-release/
-
-作者:[Ankush Das][a]
-选题:[lujun9972][b]
-译者:[译者ID](https://github.com/译者ID)
-校对:[校对者ID](https://github.com/校对者ID)
-
-本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
-
-[a]: https://itsfoss.com/author/ankush/
-[b]: https://github.com/lujun9972
-[1]: https://audacious-media-player.org
-[2]: https://doc.qt.io/qt-5/qt5-intro.html
-[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/audacious-4-release.jpg?ssl=1
-[4]: https://audacious-media-player.org/news/45-audacious-4-0-released
-[5]: https://www.ladspa.org/
-[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/audacious-winamp.jpg?ssl=1
-[7]: https://itsfoss.com/ppa-guide/
-[8]: http://ubuntuhandbook.org/index.php/2020/03/audacious-4-0-released-qt5-ui/
-[9]: https://itsfoss.com/how-to-remove-or-delete-ppas-quick-tip/
-[10]: https://github.com/audacious-media-player/audacious
diff --git a/sources/tech/20200326 How to detect outdated Kubernetes APIs.md b/sources/tech/20200326 How to detect outdated Kubernetes APIs.md
new file mode 100644
index 0000000000..a45a9b2add
--- /dev/null
+++ b/sources/tech/20200326 How to detect outdated Kubernetes APIs.md
@@ -0,0 +1,234 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to detect outdated Kubernetes APIs)
+[#]: via: (https://opensource.com/article/20/3/deprek8)
+[#]: author: (Tyler Auerbeck https://opensource.com/users/tylerauerbeck)
+
+How to detect outdated Kubernetes APIs
+======
+Deprek8 and Conftest alert you about deprecated APIs that threaten to
+slip into your codebase.
+![Ship captain sailing the Kubernetes seas][1]
+
+Recently, deprecated APIs have been wreaking havoc on everyone's [Kubernetes][2] manifests. Why is this happening?!? It's because the objects that we've come to know and love are moving on to their new homes. And it's not like this happened overnight. Deprecation warnings have been in place for quite a few releases now. We've all just been lazy and thought the day would never come. Well, _it's here_!
+
+So, maybe it caught up to us this time. But we'll be prepared next time, right?!? Yeah, that's what we said last time. But what if we could put something in place that makes sure that this doesn't happen?
+
+### What is Deprek8?
+
+[Deprek8][3] is a set of [Open Policy Agent][4] (OPA) policies that allow you to check your repository for deprecated API versions. These policies offer a way to provide warnings and errors when something is in the process of being or has already been deprecated. But **Deprek8** is just a set of policies that define what to watch for. How do you actually actively use these policies in order to monitor for deprecations?
+
+There are a number of ways and tools that can do this; one way is to use the OPA Deprek8 policy.
+
+### What is the OPA Deprek8 policy?
+
+OPA is "an open source, general-purpose policy engine that enables unified, context-aware policy enforcement." In other words, OPA provides a means of establishing and enforcing a set of policies based upon a policy file. The policies are defined in a file (or set of files) using the [Rego query language][5]. This use case won't necessarily rely on the OPA application, but more specifically, it uses this query language to do the heavy lifting. By using Rego, you can check whether various manifests match certain criteria and then either warn or error them out based on your definition. For example, in Kubernetes 1.16, the Deployment object can no longer be served from the **extensions/v1beta1 apiVersion**. So in your .rego file, you could have something like:
+
+
+```
+_deny = msg {
+ resources := ["Deployment"]
+ input.apiVersion == "extensions/v1beta1"
+ input.kind == resources[_]
+ msg := sprintf("%s/%s: API extensions/v1beta1 for %s is no longer served by default, use apps/v1 instead.", [input.kind, input.metadata.name, input.kind])
+}
+```
+
+This would alert that you have a deprecated manifest and print a message like:
+
+> Deployment/myDeployment: API extensions/v1beta1 for Deployment is no longer served by default, use apps/v1 instead.
+
+That's great! This is exactly what you need in order to avoid having old manifests lying around. But these are just the policies; you need something that will check these policies and put them into action.
+
+### Conftest
+
+This is where [Conftest][6] comes in. Conftest is a utility that allows you to put Rego policies into action against any number of configuration files. According to the repo, Conftest currently supports:
+
+
+```
+ - YAML
+ - JSON
+ - INI
+ - TOML
+ - HOCON
+ - HCL
+ - CUE
+ - Dockerfile
+ - HCL2 (Experimental)
+ - EDN
+ - VCL
+ - XML
+```
+
+It has some fairly strict defaults (i.e., expecting policy files to be in certain locations), but they can be overridden with the appropriate flags if you have a layout that you prefer. If you want to know more about those specifics, please consult the [documentation][7] in the repository.
+
+For example, you can run any policy file on Conftest with a command like:
+
+
+```
+`helm template --set podSecurityPolicy.enabled=true --set server.ingress.enabled=true . | conftest -p mypolicy.rego -`
+```
+
+This would generate the appropriate output from a Helm template and pipe it directly to the Conftest utility. Conftest inspects that output against any policies defined in the **mypolicy.rego** file and then gives any appropriate warnings or errors for objects that match against those policies. You can, of course, swap out any templating tooling of your choice, or you can feed specific files directly to the Conftest tool.
+
+So now you have the tools to set your policies and enforce them against your configuration files. But how do you tie these two things together? Better yet: How do you automate this process to continuously monitor the codebase to make sure you never fall behind the deprecation line again?
+
+### Using Git to run checks
+
+There are many methods and tools to run checks against code. By adding similar steps to your continuous integration (CI) tooling (e.g., Jenkins, Tekton, etc.), you can accomplish the same goal. In this very basic use case, I used [GitHub Actions][8], a new feature of GitHub repositories.
+
+GitHub Actions allows you to automate your entire workflow, so you don't have to sit in front of your keyboard and hack all of this together. With Actions, you can string together any number of steps into a workflow (or multiple workflows) by either rolling your own Actions if you're doing something custom or, in most cases, using something that already exists in the [Marketplace][9]. Luckily, others have provided Actions to do the things you need to do for this example, so you can lean on the community's expertise to pull your workflow together.
+
+As described in the steps above, the workflow looks something like:
+
+ 1. Retrieve the Deprek8 policy you need and store it somewhere for later use.
+ 2. Run Conftest against the appropriate files/charts with the policy file you grabbed in step 1.
+
+
+
+What does this boil down to? Well, all you really need to do is to use curl to pull your policy file and then run it through Conftest after pointing to your code, using the [curl][10] and [Conftest][11] Actions. Since these Actions already exist, you don't need to write any custom code! And as I'm sure you can tell by the names, they allow you to run the associated commands without having to do any custom work to pre-process anything or pull down any binaries.
+
+Now that you have the Actions you need to use, how do you pull them together? This is where your workflow comes into play. While Actions are the pieces of code that get things done, they're useless without a way to string them together so that they can be triggered by some event. A GitHub Action workflow will look something like this:
+
+
+```
+name: Some Awesome Workflow Name
+on: An Event That Triggers Our Workflow
+jobs:
+ awesome-job-name:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: awesome-step-name
+ uses: someorg/someaction@version
+ with:
+ args: some args that I might pass to someaction
+```
+
+Now you have a workflow that has multiple steps, can be triggered by a specific GitHub event, and can be passed a set of parameters (if that is applicable to that specific Action). This example is _extremely basic_. But luckily, the workflow you're trying to put together is equally simple. This shouldn't be taken as a comprehensive example of a GitHub Action, as there are many more complicated (and elegant) things you can do. If you're interested in learning more, take a look at the [GitHub Actions documentation][12].
+
+Now that you have an idea of what a workflow looks like and know what Actions you're interested in using, take a run at plugging the two together. For this example, you want to make sure that whenever your code is updated, it's checked to make sure it's not using any deprecated APIs.
+
+First, rig up your workflow with some names and the events that you want to trigger off of. Give your workflow and job a useful name that will help you identify it (and what it does).
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+jobs:
+ deprecation-check:
+```
+
+Next, you need to tell your workflow that you want to trigger these Actions based on any **pull_request** or **push** that happens to this repository because these are the two main events that get new code into a repository. You can do this by utilizing the **on** keyword.
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+jobs:
+ deprecation-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+```
+
+Then, add where you want these Actions to run and how the Action can get the code. You can tell the Action where to run by using the **runs-on** keyword. You have a few options here: Windows, Mac, or Ubuntu. In most cases, using Ubuntu is fine, as you'll frequently rely on Actions that run inside their own container (versus running on the base OS that you define here). It's also very important to understand that an Action does not check out code by default. When you need to do something that interacts with your code, make sure to use the Action **actions/checkout**. When this is included, your code will be available within your Action, and you can pass that through to the next step in your workflow.
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+name: API Deprecation Check
+jobs:
+ deprecation-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: curl
+ uses: wei/curl@master
+ with:
+ args: > /github/home/deprek8.rego
+```
+
+Now that your code is checked out, you can start preparing to do something with it. As mentioned, before you can check code for deprecations, you first need the file that contains the policies that you want to check for, so just retrieve the file using the **curl** Action. This is a fairly straightforward Action, in that it accepts whatever parameters you would normally pass into the curl command. If you were doing something more complicated, this is where you could pass in things like specific HTTP Actions, headers, etc. However, in this case, you're just trying to retrieve a file, so the only thing you need to pass to your Action is the URL you want to retrieve (in this case, the one that contains your raw policy file) and then tell it where you want to write that file. In this case, you're going to have it write to **/github/home**. Why? It's because this filesystem persists between steps and will allow you to use the policy file within this next step.
+
+
+```
+name: API Deprecation Check
+on: pull_request, push
+jobs:
+ deprecation-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - name: curl
+ uses: wei/curl@master
+ with:
+ args: > /github/home/deprek8.rego
+ - name: Check helm chart for deprecation
+ uses: instrumenta/conftest-action/helm@master
+ with:
+ chart: nginx-test
+ policy: /github/home/deprek8.rego
+```
+
+Now that you have your policy file, it's just a matter of running it against the code via **conftest**. Similar to the **curl** Action, the **conftest** Action just expects a series of parameters to understand how it should run against the code. In the example above, it runs against a Helm chart, but it can run against a specific file (or set of files) by changing the **uses** value to **instrumenta/[conftest-action@master][13]**. Just point to the path where your chart sits in the repository and then provide the path to your policy file (specified in the previous step). Once you have all of this together, you have a complete workflow. But what does this look like (assuming there's some bad code in your Helm chart)? To find out, take a look at the [example repository][14].
+
+In the Nginx Helm chart, you'll notice that one of the templates is a [statefulset][15]. You may also notice that the apiVersion the StatefulSet is using is **apps/v1beta1**. This API was deprecated in Kubernetes 1.16 and is now hosted in **apps/v1**. So when your GitHub Actions workflow runs, it should detect this issue and serve an error like:
+
+
+```
+FAIL - StatefulSetf/web: API apps/v1beta1 is no longer served by default, use apps/v1 instead.
+Error: plugin "conftest" exited with error
+##[error]Docker run failed with exit code 1
+```
+
+The Action indicates there is something wrong and then fails the rest of the Action. You can see the [full workflow][16] if you are interested.
+
+### Wrapping up
+
+This workflow will save some future heartache by alerting you to any deprecated APIs that slip into your codebase. To be clear, this is an _alerting_ mechanism. This won't prevent you from merging bad code into your codebase. But, as long as you pay attention, you should be completely aware prior to (or just after) merging problematic code.
+
+Where do you go from here? Well, there are a few things to keep in mind. Currently, Deprek8 is up to date as of Kubernetes 1.16. If you're interested in more recent versions, I'm sure Deprek8 would be happy to accept your [pull request][3].
+
+The other shortcoming of this method is that the **conftest** and GitHub Actions are a bit limited in that they only allow you to point at specific files or a single chart at a time. What if you want to point at multiple directories of manifests or have multiple charts inside your repository? Currently, the only way to get around that is to either list out every single file you're interested in (in the case of having multiple charts) or have multiple steps inside your workflow. Other scenarios could become problematic, like other templating engines that require some custom logic to pair the parameters and template files together. But a simple workaround for that could be to have a step in your workflow that pulls down Conftest along with a tiny inline script to loop through some of this. I'm sure there are more elegant solutions (and if you come up with one, I'm sure these projects would be more than happy to take a look at your PR).
+
+Regardless, you now have a mechanism that should allow you to sleep a bit easier when checking in your code! And hopefully, this method will help you build even more robust workflows to protect your code.
+
+* * *
+
+_This was originally published in [Tyler Auerbeck's GitHub repository][17] and is reposted, with edits, with permission._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/deprek8
+
+作者:[Tyler Auerbeck][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/tylerauerbeck
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
+[2]: https://opensource.com/resources/what-is-kubernetes
+[3]: https://github.com/naquada/deprek8
+[4]: https://github.com/open-policy-agent/opa
+[5]: https://blog.openpolicyagent.org/opas-full-stack-policy-language-caeaadb1e077
+[6]: https://github.com/instrumenta/conftest
+[7]: https://github.com/instrumenta/conftest/tree/master/docs
+[8]: https://github.com/features/actions
+[9]: https://github.com/marketplace?type=actions
+[10]: https://github.com/marketplace/actions/github-action-for-curl
+[11]: https://github.com/instrumenta/conftest-action
+[12]: https://help.github.com/en/actions
+[13]: mailto:conftest-action@master
+[14]: https://github.com/tylerauerbeck/deprek8-example
+[15]: https://raw.githubusercontent.com/tylerauerbeck/deprek8-example/master/nginx-test/templates/statefulset.yaml
+[16]: https://github.com/tylerauerbeck/deprek8-example/runs/426774566?check_suite_focus=true
+[17]: https://github.com/tylerauerbeck/writing/blob/master/opa/deprek8.md
diff --git a/sources/tech/20200328 Open source fights against COVID-19, Google-s new security tool written in Python, and more open source news.md b/sources/tech/20200328 Open source fights against COVID-19, Google-s new security tool written in Python, and more open source news.md
new file mode 100644
index 0000000000..dce9c83a0e
--- /dev/null
+++ b/sources/tech/20200328 Open source fights against COVID-19, Google-s new security tool written in Python, and more open source news.md
@@ -0,0 +1,82 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Open source fights against COVID-19, Google's new security tool written in Python, and more open source news)
+[#]: via: (https://opensource.com/article/20/3/news-march-28)
+[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
+
+Open source fights against COVID-19, Google's new security tool written in Python, and more open source news
+======
+Catch up on the biggest open source headlines from the past two weeks.
+![][1]
+
+In this edition of our open source news roundup, we take a look open source solutions for COVID-19, Google's new security tool, code cleanup software from Uber, and more!
+
+### Using open source in the fight against COVID-19
+
+When COVID-19 started its march around the world, open source [stepped up][2] to try to help stop it. That includes using open data to [create tracking dashboards and apps][3], designing ventilators, and developing protective gear.
+
+Scientists at the University of Waterloo in Canada have teamed with artificial intelligence firm DarwinAI to create an open source tool "[to identify signs of Covid-19 in chest x-rays][4]." Called COVID-Net, it's neural network "that is particularly good at recognizing images." The dataset the researchers are using is [available on GitHub][5], which includes a link the software.
+
+Additionally, many [open source hardware projects][6] are underway to expedite the search for a cure.
+
+### Google releases tool to fight USB keystroke injection attacks
+
+One of the sneakiest and potentially most malicious ways to hack a computer is a USB keystroke injection attack. Using a compromised USB device connected to a computer, a hacker can run commands without you even noticing. Google's making it easier for Linux users to fight back against these kinds of attacks by releasing [an open source detection tool][7].
+
+Called USB Keystroke Injection Protection, the tool detects "if the keystrokes have been made without human involvement". It does that by measuring "the timing of keystrokes coming from connected USB devices." Sebastian Neuner of Google's Information Security Engineering Team said that while the USB Keystroke Injection Protection tool isn't the last word in defense against these kinds of attacks, but offers "another layer of protection and to defend a user sitting in front of their unlocked machine by them seeing the attack happening."
+
+You can find the Python source code for the tool [on GitHub][8].
+
+### Uber makes code deletion tool open source
+
+As applications get bigger, they often contain code that's either no longer used or which is obsolete. That added code make software more difficult to maintain. To help solve the problem of quickly finding that redundant code, Uber recently [open sourced a tool called Pirhana][9].
+
+Pirhana scans code for [feature flags][10], looking for ones that are no longer used. The software then deletes the unused flags from the code. At the moment, Pirhana works with software written in the Objective-C, Swift, and Java languages. Uber's developers hope the number of supported languages will increase "now that outside developers have an opportunity to contribute to the project."
+
+You can grab [Pirhana's source code][11] from its repository on GitHub
+
+#### In other news
+
+ * [Singapore government to open source contact-tracing protocol][12]
+ * [European Commission to use open source messaging service Signal][13]
+ * [Spanish software to computerize healthcare in Cameroon and India][14]
+ * [ING Open-Sources Lion, Its White-Label Web Component Library][15]
+ * [Open Source Goes Mainstream – How Sharing Is Shaping The Future Of Music][16]
+
+
+
+Thanks, as always, to Opensource.com staff members and [Correspondents][17] for their help this week.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/news-march-28
+
+作者:[Scott Nesbitt][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/scottnesbitt
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/weekly_news_roundup_tv.png?itok=tibLvjBd
+[2]: https://jaxenter.com/covid-19-open-source-170237.html
+[3]: https://opensource.com/article/20/3/open-source-software-covid19
+[4]: https://www.technologyreview.com/s/615399/coronavirus-neural-network-can-help-spot-covid-19-in-chest-x-ray-pneumonia/
+[5]: https://github.com/lindawangg/COVID-Net
+[6]: https://opensource.com/article/20/3/open-hardware-covid19
+[7]: https://www.zdnet.com/article/google-linux-systems-can-use-this-new-tool-against-usb-keystroke-injection-attacks/
+[8]: https://github.com/google/ukip
+[9]: https://siliconangle.com/2020/03/17/ubers-open-source-piranha-tool-hunts-redundant-application-code/
+[10]: https://en.wikipedia.org/wiki/Feature_toggle
+[11]: https://github.com/uber/piranha
+[12]: https://www.computerweekly.com/news/252480501/Singapore-government-to-open-source-contact-tracing-protocol
+[13]: https://joinup.ec.europa.eu/collection/open-source-observatory-osor/news/signal-messaging-service
+[14]: https://intallaght.ie/spanish-software-to-computerize-healthcare-in-cameroon-and-india/
+[15]: https://www.infoq.com/articles/ing-open-sources-lion-web-component/
+[16]: https://www.forbes.com/sites/andreazarczynski/2020/03/19/open-source-goes-mainstream--how-sharing-is-shaping-the-future-of-music/#9e1ca1290013
+[17]: https://opensource.com/correspondent-program
diff --git a/sources/tech/20200329 Nextcloud- The Swiss Army Knife of Remote Working Tools.md b/sources/tech/20200329 Nextcloud- The Swiss Army Knife of Remote Working Tools.md
new file mode 100644
index 0000000000..82d84f984b
--- /dev/null
+++ b/sources/tech/20200329 Nextcloud- The Swiss Army Knife of Remote Working Tools.md
@@ -0,0 +1,154 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Nextcloud: The Swiss Army Knife of Remote Working Tools)
+[#]: via: (https://itsfoss.com/nextcloud/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+Nextcloud: The Swiss Army Knife of Remote Working Tools
+======
+
+Remote working culture has been booming for past few years in coding, graphics and other IT related fields. But the recent [Coronavirus pandemic][1] has made it mandatory for the companies to work from home if it’s possible for them.
+
+While there are tons of tools to help you and your organization in working from home, let me share one open source software that has the features of several such tools combined into one.
+
+### Nextcloud Hub: A Suite of Essential Tools for Remote Collaboration
+
+[Nextcloud][2] is an open source software that can be used to store files, photos and videos for personal usage like Dropbox. But it’s more than just a private [cloud service][3].
+
+You can add more than one users in Nextcloud and turn it into a collaboration platform for editing files in real time, chat with users, manage calendars, assign and manage tasks and more.
+
+This video gives a good overview of its main features:
+
+[Subscribe to our YouTube channel for more Linux videos][4]
+
+### Main Features of Nextcloud
+
+Let me highlight the main features of Nextcloud:
+
+#### Sync files and share
+
+![Nextcloud Files][5]
+
+You can create workspaces based on user groups and share files in those folders. Users can create private files and folders and share them with selected users internally or externally (if they are allowed to). You can lock files in read only mode as well.
+
+It also has a very powerful search feature that lets you search files from their name or tags. You can comment on files to provide feedback.
+
+Text files can be edited in real time thanks to its builtin markdown editor. You can use OnlyOffice or Collabora to allow editing of docs, spreadsheet and presentations in real time.
+
+It also has version control for the files so that you can revert changes easily.
+
+#### Text Chat, Audio Chat, Video Chat and Web Meetings
+
+![Nextcloud Video Call][6]
+
+With NextCloud Talk, you can interact with other users by text messaging, audio calls, video calls and group calls for web meetings. You can also take meeting minutes during the video calls and share your screen for presentations. There is also a mobile app to stay connected all the time.
+
+You can also create Slack like channels (known as circles) to communicate between members concerned with a specific topic.
+
+#### Calendar, Contacts & Mail
+
+![Calendar Nextcloud][7]
+
+You can manage all of your organization’s contact, divide them into groups based on departments.
+
+With the calendar, you can see when someone is free or what meetings are taking place, like you do on Outlook.
+
+You can also use the Mail feature and import the emails from other providers to use them inside Nextcloud interface.
+
+#### Kanban project management with Deck
+
+![][8]
+
+Like Trello and Jira, you can create boards for various projects. You can create cards for each tasks, assign them to users and they can move it between the list based on the status of the task. It’s really up to you how you create boards to manage your projects in Kanban style.
+
+#### Plenty of add-ons to get more out of Nextcloud
+
+![Password Manager][9]
+
+Nextcloud also has several add-ons (called apps). Some are developed by Nextcloud teams while some are from third-party developers. You may use them to extend the capability of Nextcloud.
+
+For example, you can add a [Feedly style feed reader][10] and read news from various sources. Similarly, the [Paswords addon][11] lets you use Netxcloud as a password manager. You can even share common passwords with other Nextcloud users.
+
+You can explore [all the apps on its website][12]. You’ll also notice the ratings of apps that will help you decide if you should use an app or not.
+
+#### Many more features
+
+Let me summarize all the features here:
+
+ * Open source software that lets you own your data on your own servers
+ * Seamlessly edit office documents together with others
+ * Communicate with other members of your organization and do audio and video calls and held web meetings
+ * Calendar lets you book meetings, brings busy view for meetings and resource booking and more
+ * Manage users locally or authenticate through LDAP / Active Directory, Kerberos and Shibboleth / SAML 2.0 and more
+ * Secure data with powerful file access control, multi-layer encryption, machine-learning based authentication protection and advanced ransomware recovery capabilities
+ * Access existing storage silos like FTP, Windows Network Drives, SharePoint, Object Storage and Samba shares seamlessly through Nextcloud.
+ * Automation: Automatically turn documents in PDFs, send messages to chat rooms and more!
+ * Built in ONLYOFFICE makes collaborative editing of Microsoft Office documents accessible to everyone
+ * Users can install desktop and mobile apps or simply use it in web browser
+
+
+
+### How to get Nextcloud
+
+![][13]
+
+NextCloud is free and open source software. You can download it and install it on your own server.
+
+You can use cloud server providers like [Linode][14] or [DigitalOcean][15] that allow you to deploy a brand new Linux server within minutes. And then you can use Docker to install NextCloud. At It’s FOSS, we use [Linode][14] for our NextCloud instance.
+
+If you don’t want to do that, you can [signup with one of the Nextcloud partners][16] that provide you with configured Nextcloud instance. Some providers also provide a few GB of free data to try it.
+
+Nextcloud also has an [enterprise plan][17] where Nextcloud team itself handles everything for the users and provide premium support. You can check their pricing [here][18].
+
+If you decide to use Nextcloud, you should refer to its documentation or community forum to explore all its features.
+
+### Conclusion
+
+At It’s FOSS, our entire team works remote. We have no centralized office anywhere and all of us work from our home. Initially we relied on non-open source tools like Slack, Google Drive etc but lately we are migrating to their open source alternatives.
+
+Nextcloud is one of the first software we tried internally. It has features of Dropbox, Google Docs, [Slack][19], [Trello][20], Google Hangout all combined in one software.
+
+NextCloud works for most part but we found it struggling with the video calls. I think that has to do with the fact that we have it installed on a server with 1 GB of RAM that also runs some other web services like [Ghost CMS][21]. We plan to move it to a server with better specs. We’ll see if that should address these issues.
+
+Since the entire world is struggling with the Coronavirus pandemic, using a solution like Nextcloud could be helpful for you and your organization in working from home.
+
+How are you coping during the Coronavirus lockdown? Like [Linus Torvalds’ advice on remote working][22], do you also have some suggestion to share with the rest of us? Please feel free to use the comment section.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/nextcloud/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://en.wikipedia.org/wiki/2019%E2%80%9320_coronavirus_pandemic
+[2]: https://nextcloud.com/
+[3]: https://itsfoss.com/cloud-services-linux/
+[4]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
+[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud_files.png?ssl=1
+[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud_video_call.jpg?ssl=1
+[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/calendar_nextcloud.jpeg?ssl=1
+[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud_kanban_project_management_app.jpeg?ssl=1
+[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/03/passman.png?fit=800%2C389&ssl=1
+[10]: https://apps.nextcloud.com/apps/news
+[11]: https://apps.nextcloud.com/apps/passwords
+[12]: https://apps.nextcloud.com/
+[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/03/nextcloud-feature.jpg?ssl=1
+[14]: https://www.linode.com/?r=19db9d1ce8c1c91023c7afef87a28ce8c8c067bd
+[15]: https://m.do.co/c/d58840562553
+[16]: https://nextcloud.com/signup/
+[17]: https://nextcloud.com/enterprise/
+[18]: https://nextcloud.com/pricing/
+[19]: https://slack.com/
+[20]: https://trello.com/
+[21]: https://itsfoss.com/ghost-3-release/
+[22]: https://itsfoss.com/torvalds-remote-work-advice/
diff --git a/sources/tech/20200330 Access control lists and external drives on Linux- What you need to know.md b/sources/tech/20200330 Access control lists and external drives on Linux- What you need to know.md
new file mode 100644
index 0000000000..079e775ce1
--- /dev/null
+++ b/sources/tech/20200330 Access control lists and external drives on Linux- What you need to know.md
@@ -0,0 +1,233 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Access control lists and external drives on Linux: What you need to know)
+[#]: via: (https://opensource.com/article/20/3/external-drives-linux)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Access control lists and external drives on Linux: What you need to know
+======
+Learn how to use external drives correctly on Linux.
+![Penguin driving a car with a yellow background][1]
+
+While cloud storage offers many advantages, there's nothing quite like having your data on a physical hard drive. When you save data to a drive, you know exactly where your data is, and it's always available when you need it. When you save data to an external portable drive like a USB thumb drive, it's even better—not only do you know where your data is, but you can take your data with you everywhere you go. If you're new to [Linux][2], or you're trying to use a Linux file system on an external drive, you might find external drives confusing, being prone to permission errors or conflicts, or even losing metadata.
+
+There are two "right" answers to this:
+
+### ExFAT
+
+Formerly, ExFAT was a file system fraught with legal threats from Microsoft because they own the code. They've sued companies and organizations before to defend their ownership of FAT, so it was commonly feared that they could do the same over ExFAT. However, recently. Microsoft made the specifications for ExFAT open source. They didn't provide a driver, unfortunately, but there's an existing drive to make it function on Linux, and, now that developers have access to the full specs, improvements are inevitable.
+
+The advantage of ExFAT is that it's cross-platform (Windows, Mac, and many portable devices use it), and it's designed without the overhead of file permissions. You can attach a drive formatted as ExFAT to any computer, and all files are available to anyone. Whether that's good or bad depends on your use case, but for portable media, that's often exactly the intent.
+
+### Access control lists (ACL)
+
+If you prefer to use a Linux file system on your portable drive, then you can do that, but to make sharing files seamless, you should use access control lists (ACL).
+
+When you create a file or directory on a drive, there are defaults on your system determining what file permissions it gets. For most cases, those defaults make sense—when you create a file in your home directory, you probably don't want other users to have access to that file. However, when you're creating a file on an external drive, there's a high likelihood that it's because you need to share that file with someone else (even if that someone is you on another computer).
+
+You can override default permissions for file viewing with an ACL, and you can control default file creation mode by setting a sticky bit. An ACL is a layer of security policies in the extended attributes of directories and files. It allows you to specify exceptions to what the file system permissions indicate. Most notably, this allows you to transcend the single-owner and single-group model of traditional UNIX permissions.
+
+For instance, while the **seth** (ID 1000) account might own a directory created on my desktop, **seth** (ID 500) on my laptop does not, because the user IDs are different.
+
+The same could be true for a group. If a directory with group ID 1000 is assigned to a directory on one computer, then a group with an ID 500 or 10922 doesn't have access to it on another computer. But an ACL can add secondary owners and groups to directories and files.
+
+#### View the current ACL
+
+Any directory and file on any common Linux filesystem has ACL rules by default. They're stored in extended attributes, a kind of metadata that you don't normally see.
+
+You can view them in the terminal:
+
+
+```
+$ getfacl ./example
+# file: /run/media/drive/example
+# owner: seth
+# group: users
+user::rwx
+group::rwx
+other::r--
+```
+
+The commented lines are just for your reference; they tell you the path, and the owner and group, of the file or directory you're viewing information about. The next lines display the rules applied to the file or directory. In this example, the user permissions are set to **rwx**, the group to **r-x**, and other to **r-x**. These permissions are reflected by a normal filesystem list:
+
+
+```
+$ ls -lA /run/media/drive
+drwxrwxr-- 26 seth users 4096 Jan 16 21:04 example
+$ id
+uid=1000(seth) gid=100(users) groups=100(users)...
+```
+
+As long as user **seth** (UID 1000) or a member of **group** (GID 100) interacts with the **example** directory, full access is granted. Any other account, however, has only read (**r**) permission.
+
+#### Setting an ACL
+
+To modify an ACL, you use the **setfacl** command or use a file manager with ACL support. You can be very specific or very generic when setting your ACL.
+
+To just modify the filesystem permission settings, you can use either **chmod** or **setfacl**. This is a very generic ACL setting because you're not adding anything to the permissions already available to UNIX from the filesystem specification.
+
+
+```
+$ setfacl --modify g::r example
+$ getfacl ./example | grep "group::"
+group::r--
+$ ls -l . | grep example
+drwxr--r-- 26 seth users 4096 Jan 16 21:04 example
+```
+
+The same effect is available through **chmod**:
+
+
+```
+$ chmod g+x example
+$ getfacl ./example | grep "group::"
+group::r-x
+$ ls -l . | grep example
+drwxr-xr-- 26 seth users 4096 Jan 16 21:04 example
+```
+
+#### Adding users and groups
+
+To really benefit from an ACL is to use it for permissions outside the scope of native UNIX permissions. If I'm logged into my desktop as **seth** with user ID 1000, and I know that a directory on my portable drive needs to be usable by **seth** with ID 500 on my laptop, then just declaring **seth** as owner isn't enough because the user IDs aren't the same.
+
+You can add a user or user ID to an access control list:
+
+
+```
+$ setfacl --modify u:500:rwx example
+$ getfacl example
+# file: /run/media/drive/example
+# owner: seth
+# group: users
+user::rwx
+user:500:rwx
+[...]
+```
+
+A new entry, specific to user ID 500, has been added to the list. Attaching the drive to another Linux or UNIX computer now allows the user with ID 500 to access the **example** folder.
+
+You can also add users by account name, or groups by either group name or group ID. The IDs are what really count with permissions, though, so if you're in a mixed environment (RHEL servers and Elementary clients, for example), you should verify the user IDs and group IDs lurking behind accounts that seem, on the surface, identical.
+
+#### Setting default ACL rules
+
+If you treat access control as a one-time setting, you'll quickly run into problems once your different user accounts start creating files and directories. Any new file or directory created by each user inherits the system's default permissions (and ACL). This means that once laptop user **seth** with ID 500 creates a file in a directory, it could be off-limits to desktop user **seth** with ID 1000 because the owner of the file is set to UID 500.
+
+A default ACL can be applied to directories so that files and subdirectories created within them inherit the parent ACL. You can set the default ACL of a directory with the **–default** option:
+
+
+```
+$ setfacl --default --modify u:500:rwx example
+$ setfacl --default --modify u:1000:rwx example
+$ getfacl --omit-header example
+user::rwx
+user:500:rwx
+group::rw-
+mask::rwx
+other::r-x
+default:user::rwx
+default:group::rw-
+default:group:500:rwx
+default:group:1000:rwx
+default😷:rwx
+default:other::r-x
+```
+
+When a user creates a new directory within the **example** directory, the inherited ACL is the same as its parent:
+
+
+```
+$ cd example
+$ mkdir penguins
+$ getfacl --omit-header penguins
+user::rwx
+group::rw-
+group:500:rwx
+group:1000:rwx
+mask::rwx
+other::r-x
+default:user::rwx
+default:group::rw-
+default:group:500:rwx
+default:group:1000:rwx
+default😷:rwx
+default:other::r-x
+```
+
+This means that any directory or file created inherits the same ACL, so neither user 500 or 1000 are ever excluded from access.
+
+#### Pragmatic ACL for external drives
+
+When using a Linux filesystem for external drives, the easy method of ensuring it works with all the users who expect to use the portable drive is to set an ACL on a single top-level directory.
+
+For instance, assume you have formatted a USB drive called **mydrive** as an ext4 filesystem. You want your account on your laptop and your desktop, as well as your colleague Alice, to be able to access the files.
+
+First, create a directory at the top level of the drive:
+
+
+```
+$ mkdir /mnt/mydrive/umbrella
+```
+
+Then apply an ACL to the top-level directory to grant all-important users access:
+
+
+```
+$ setfacl --modify \
+ u:500:rwx,u:1000:rwx,u:alice:rwx \
+ /mnt/mydrive/umbrella
+```
+
+Finally, apply a default ACL so that all directories and files created within the top-level directory **umbrella** inherit the same default ACL (note that this command uses the short version of **–modify**):
+
+
+```
+$ setfacl --default -m u:500:rwx,u:1000:rwx,u:alice:rwx \
+ /mnt/mydrive/umbrella
+```
+
+#### Applying defaults to an existing system
+
+If you need to apply ACL settings to many files that already exist, you can accomplish that with the **find** command.
+
+First, find all directories and apply ACL rules:
+
+
+```
+$ find /mnt/mydrive/umbrella -type d | \
+ parallel --max-args=6 setfacl \
+ --default -m u:500:rwx,u:1000:rwx,u:alice:rwx
+```
+
+It's not wise to indiscriminately set all file permissions to executable, so next, find all files and set permissions to **re**. Files that require an executable bit can be set manually or by file extension:
+
+
+```
+$ find /mnt/mydrive/umbrella -type f | \
+ parallel --max-args=6 setfacl \
+ --default -m u:500:rw,u:1000:rw,u:alice:rw
+```
+
+Adjust the logic of these commands to suit your individual need (don't run a command that removes the executable bit on **/usr**, for instance, or on a directory containing nothing but executable programs).
+
+### External drives
+
+Don't let confusion around external drives on Linux get the best of you, and don't limit yourself to traditional UNIX permissions. Put access control lists to work for you, and feel free to use native journaled Linux filesystems on your portable drives.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/3/external-drives-linux
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/car-penguin-drive-linux-yellow.png?itok=twWGlYAc (Penguin driving a car with a yellow background)
+[2]: https://opensource.com/resources/linux
diff --git a/sources/tech/20200330 Why I switched from Mac to Linux.md b/sources/tech/20200330 Why I switched from Mac to Linux.md
new file mode 100644
index 0000000000..95561b6b45
--- /dev/null
+++ b/sources/tech/20200330 Why I switched from Mac to Linux.md
@@ -0,0 +1,68 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Why I switched from Mac to Linux)
+[#]: via: (https://opensource.com/article/20/3/mac-linux)
+[#]: author: (Lee Tusman https://opensource.com/users/leeto)
+
+Why I switched from Mac to Linux
+======
+After 25 years, Lee made the switch to Linux and couldn't be happier.
+Here's what he uses.
+![Code going into a computer.][1]
+
+In 1994, my family bought a Macintosh Performa 475 as a home computer. I had used Macintosh SE computers in school and learned to type with [Mavis Beacon Teaches Typing][2], so I've been a Mac user for well over 25 years. Back in the mid-1990s, I was attracted to its ease of use. It didn't start with a DOS command prompt; it opened to a friendly desktop. It was playful. And even though there was a lot less software for Macintosh than PCs, I thought the Mac ecosystem was better, just on the strength of KidPix and Hypercard, which I still think of as the unsurpassed, most intuitive _creative stack_.
+
+Even so, I still had the feeling that Mac was an underdog compared to Windows. I remember thinking the company could disappear one day. Flash-forward decades later, and Apple is a behemoth, a trillion-dollar company. But as it evolved, it changed significantly. Some changes have been for the better, such as better stabilization, simpler hardware choices, increased security, and more accessibility options. Other changes annoyed me—not all at once, but slowly. Most significantly, I am annoyed by Apple's closed ecosystem—the difficulty of accessing photos without iPhoto; the necessity of using iTunes; and the enforced bundling of the Apple store ecosystem even when I don't want to use it.
+
+Over time, I found myself working largely in the terminal. I used iTerm2 and the [Homebrew][3] package manager. I couldn't get all my Linux software to work, but much of it did. I thought I had the best of both worlds: the macOS graphical operating system and user interface alongside the ability to jump into a quick terminal session.
+
+Later, I began using Raspberry Pi computers booting Raspbian. I also collected a number of very old laptops rescued from the trash at universities, so, by necessity, I decided to try out various Linux distros. While none of them became my main machine, I started to really enjoy using Linux. I began to consider what it would be like to try running a Linux distro as my daily driver, but I thought the Macbook's comfort and ease, especially the hardware's size and weight, would be hard to find in a non-Mac laptop.
+
+## Time to make the switch?
+
+About two years ago, I began using a Dell for work. It was a larger laptop with an integrated GPU, and dual-booted Linux and Windows. I used it for game development, 3D modeling, some machine learning, and basic programming in C# and Java. I considered making it my primary machine, but I loved the portability of my Macbook Air, and continued to use that as well.
+
+Last fall, I started to notice my Air was running hot, and the fan was coming on more often. My primary machine was starting to show its age. For years, I used the Mac's terminal to access Darwin's Unix-like operating system, and I was spending more and more time bouncing between the terminal and my web browser. Was it time to make the switch?
+
+I began exploring the possibilities for a Macbook-like Linux laptop. After doing some research, reading reviews and message boards, I went with the long-celebrated Dell XPS 13 Developer Edition 7390, opting for the 10th Generation i7. I chose it because I love the feel of the Macbook (and especially the slim Macbook Air), and reviews of the XPS 13 suggested it seemed it was similar, with really positive reviews of the trackpad and keyboard.
+
+Most importantly, it came loaded with Ubuntu. While it's easy enough to get a PC, wipe it, and install a new Linux distro, I was attracted to the cohesive operating system and hardware, but one that allowed a lot of the customization we know and love in Linux. So when there was a sale, I took the plunge and purchased it.
+
+## What it's like to run Linux daily
+
+I've been using the XPS 13 for three months and my dual-booted Linux work laptop for two years. At first, I thought I'd want to spend more time finding an alternate desktop environment or window manager that was more Mac-like, such as [Enlightenment][4]. I tried several, but I have to say, I like the simplicity of running [GNOME][5] out of the box. For one thing, it's minimal; there's not much GUI to get caught up in. In fact, it's intuitive and the [overview][6] takes only a couple minutes to read.
+
+I can access my applications through the application dash bar or a grid button to get to the application view. To access my file system, I click on the **Files** icon in the dash. To open the GNOME terminal, I type **Ctrl+Alt+T** or just **Alt+Tab** to switch between an open application and an open terminal. It's also easy to define your own [custom hotkey shortcuts][7].
+
+Beyond this, there's not much else to say. Unlike the Mac's desktop, there's not a lot to get lost in, which means there's less to distract me from my work or the applications I want to run. I didn't realize all the options or how much time I spent navigating windows on my Mac. In Linux, there are just files, applications, and the terminal.
+
+I installed the [i3 tiling window manager][8] to do a test run. I had a few issues configuring it because I type in [Dvorak][9], and i3 doesn't adapt to the alternate keyboard configuration. I think with more effort, I could figure out a new keyboard mapping in i3, but the main thing I was looking for was simple tiling.
+
+I looked up GNOME's tiling capabilities and was pleasantly surprised. You press the **Super** key (for me, it's the key with the Windows logo—which I should cover with a sticker!) and then a modifier key. For example, pressing **Super+Left** moves your current window to a tile on the left side of the screen. **Super+Right** moves to the right half. **Super+Up** maximizes the current window. **Super+Down** reverts to the previous size. You can move between app windows with **Alt+Tab**. This is all default behavior and can be customized in the Keyboard settings.
+
+Plugging in headphones or connecting to HDMI works the way you expect. Sometimes, I open the Sound settings to switch between the HDMI sound output or my external audio cable, just as I would on a Mac or PC. The trackpad is responsive, and I haven't noticed any difference from the Macbook's. When I plug in a three-button mouse, it works instantly, even with my Bluetooth mouse and keyboard.
+
+### Software
+
+I installed Atom, VLC, Keybase, Brave Browser, Krita, Blender, and Thunderbird in a matter of minutes. I installed other software with the Apt package manager in the terminal (as normal), which offers many more packages than the Homebrew package manager for macOS.
+
+### Music
+
+I have a variety of options for listening to music. I use Spotify and [PyRadio][10] to stream music. [Rhythmbox][11] is installed by default on Ubuntu; the simple music player launches instantly and without any bloat. Simply click on the menu, choose **Add Music**, and navigate to a directory of audio tracks (it searches recursively). You can also stream podcasts or online radio easily.
+
+### Text and PDFs
+
+I tend to write in Markdown in [Neovim][12] with some plugins, then convert my document using Pandoc to whatever final format is needed. For a nice Markdown editor with preview, I downloaded [Ghostwriter][13], a minimal-focus writing application.
+
+If someone sends me a Microsoft Word document, I can open it using the default LibreOffice Writer application.
+
+Occasionally, I have to sign a document. This is easy with macOS's Preview application and my signature in PNG format, and I needed a Linux equivalent. I found that the default PDF viewer app didn't have the annotation tools I needed. The LibreOffice Draw program was acceptable but not particularly easy to use, and it occasionally crashed. Based on some research, I installed [Xournal][14], which has the simple annotation tools I need to add dates, text, and my signature and is fairly comparable to Mac's Preview app. It works exactly as needed.
+
+### Importing images from my phone
+
+I have an iPhone. To get my images off the phone, there are a number of methods to sync and access your files. If you have a different phone, your process may be different. Here's my method:
+
+ 1. Install gvfs-backends with **sudo apt install gvfs-backends**, which is part of the GNO
\ No newline at end of file
diff --git a/sources/tech/20200401 How does kanban relate-to DevOps.md b/sources/tech/20200401 How does kanban relate-to DevOps.md
new file mode 100644
index 0000000000..3f37c35a4c
--- /dev/null
+++ b/sources/tech/20200401 How does kanban relate-to DevOps.md
@@ -0,0 +1,117 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How does kanban relate to DevOps?)
+[#]: via: (https://opensource.com/article/20/4/kanban-devops)
+[#]: author: (Willy-Peter Schaub https://opensource.com/users/wpschaub)
+
+How does kanban relate to DevOps?
+======
+Reduce waste, optimize the flow of value, and continuously deliver value
+to delighted users.
+![two women kanban brainstorming and brainmapping with post-it notes on a whiteboard ][1]
+
+Kanban is nothing new; in fact, it predates most readers of this article. Its age becomes apparent when we add the year Toyota introduced kanban in its main plant machine shop (1953) to the timeline image from our [analyzing the DNA of DevOps][2] article.
+
+![DevOps timeline][3]
+
+I have intuitively been using kanban, in one form or the other, for more than two decades to track personal plans, engineering projects, and digital transformations. Only in the past few weeks have I pondered the origins, power, and synergy of kanban with other frameworks and systems, while introducing teams to kanban and helping them embrace it as a powerful system in our common engineering system.
+
+### What is kanban?
+
+Kanban means "visual signal" and has its roots in the Toyota manufacturing industry. It was developed by [Taiichi Ohno][4] to improve manufacturing efficiency. When we jump a few decades into the future, kanban complements agile and lean, often used with frameworks such as scrum, Scaled Agile Framework, and Disciplined Agile to visualize and manage work.
+
+![Kanban complements agile and lean][5]
+
+You can explore the many interpretations of kanban on the internet, in books, and in vibrant discussions with other engineers who have embraced the system. In the context of our common collaboration and engineering system, kanban delivers four pivotal practices:
+
+ * **Visualize work:** We visualize all work and look for triggers such as cards turning **red** when the work they represent is blocked or has been dormant for more than two days.
+ * **Limit work in progress:** We agree on and enforce (soft) work-in-progress limits to encourage reduced batch sizes and manage queue lengths.
+ * **Focus on flow:** We _pull_ not push work, which helps us to defer commitment until we meet our definition of done (_DoD_) and we have the capacity to commit to the next _activity_.
+ * **Continuous improvement:** It is important to measure work from when it enters our backlog, how long it takes to get through the process (lead time), and how efficient we are working (cycle/lead time). This enables us to continuously inspect and improve how we work and track progress.
+
+
+
+![Kanban practices and terminology][6]
+
+We use colorful, visual cards to represent activities that flow through one or more _activities_ in one of many _swim lanes_. Each kanban column represents an activity, and each swim lane represents a person, group, or another bucket to segment the cards. There are no rules for the color of the cards, but **red** typically signals a problem. But remember to combine color with a meaningful icon to visualize special states for users who are color-blind.
+
+> "_We should defer commitment until our Definition of Ready (DOR) is met so that we can ensure that our Definition of Done (DOD) is achieved sooner and with high quality. I like the two distinct terms (DOR and DOD) because the [project owner] should be accountable for the DOR while the team can take ownership of the DOD_." —[Mathew Mathai][7]
+
+I often use this analogy to explain the difference between _lead_ and _cycle_ time to new teams: Imagine you walk into a restaurant. You sit down, study the menu, and decide what you would like to drink and eat. When the waiter takes your order, the _lead_ cycle time starts ticking. When the bar starts pouring your favorite potion and the kitchen starts preparing your meal, the _cycle_ time starts ticking. As the order arrives at your table, both the lead and cycle time are stopped if (and only if) you are satisfied.
+
+Therefore, the _lead_ time measures how long you, the customer, had to wait until you received your order. The _cycle_ time measures the process time of an activity to prepare your order. From a customer perspective, the _lead_ time is important.
+
+It is important to _make your policies explicit_, such as when you start measuring lead and cycle times. Some customers start their "impatience" clock when they enter the restaurant, while others start the clock when they place their order. In both cases, they need to understand how you measure your flow to avoid misunderstandings, unfeasible expectations, and disappointment.
+
+This image is extracted from one of our information transfer posters, and it summarizes key learnings when we started adopting the kanban system.
+
+![Key kanban learnings][8]
+
+### What about DevOps?
+
+In _[Using PowerShell to automate Linux, macOS, and Windows processes][9]_, we briefly introduced value-stream mapping. It enables us to measure individual and total lead times, cycle times, efficiency, and quality and unearth different activities, groups, and silos that cancel out each other.
+
+![value-stream mapping][10]
+
+You will notice a similarity between the kanban board and the value-stream mapping images. Both _visualize_ and _focus_ on the flow of activities represented by individual cards pulled across a visual board.
+
+![Continuous delivery pipeline][11]
+
+Continuous flow and efficiency are core to a healthy DevOps mindset. It transforms into a continuous delivery pipeline, as shown above, which unites different teams, such as business, development, security, and quality assurance, to implement ideas from ideation to production. Continuously measuring and streamlining the delivery pipeline not only helps improve the flow of value, but also the quality of value.
+
+It should be evident that (similar to kanban) the focus here is on flow. Flipping back and forth between activities is frowned upon in kanban and impractical with continuous delivery pipelines. It reminds me of a recent whiteboard discussion where we discussed the challenge of visualizing and managing the flow of work that requires two teams.
+
+![Dividing a job between two teams][12]
+
+As shown here, we slice a job that requires team X to perform activities, then team Y, and again team X, into three stories. The three stories are visualized by three cards on two kanban boards, flowing from A to B to C, with clear ownership by team X and Y, which we can measure independently as lead and cycle time.
+
+We are drifting into another exciting topic of flow optimization … let's get back to the original question.
+
+### What is the relationship between kanban and DevOps?
+
+[Donovan Brown][13] defines DevOps as "_the union of people, process, and products to enable continuous delivery of value to our end users._"
+
+When we unpack this definition, we realize that the core of the DevOps [mindset][14] is to continuously deliver value and delight our customers.
+
+ * _"Feedback from stakeholders is essential."_
+ * _"Improve beyond the limits of today's processes."_
+ * _"No new silos to break down silos."_
+ * _"Knowing your customers means cross-organization collaboration."_
+ * _"Inspire adoption through enthusiasm."_
+
+
+
+The kanban system helps us visualize and improve the efficiency of value delivery, resulting in delighted customers. I argue that if you are comfortable with kanban, you will enjoy the full benefits of DevOps through _visualization_, _flow improvement_, _feedback_, and _continuous innovation_.
+
+We have collaboration at its finest—_synergy_**,** or is that _symbiosis_?
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/kanban-devops
+
+作者:[Willy-Peter Schaub][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/wpschaub
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/whiteboard-brainstorming-brainmapping-design-thinking-postits-kanban.png?itok=Is2Tg1Jk (Brainstorming with post-it notes on a whiteboard)
+[2]: https://opensource.com/article/18/11/analyzing-devops
+[3]: https://opensource.com/sites/default/files/uploads/devops-timeline.png (DevOps timeline)
+[4]: https://en.wikipedia.org/wiki/Taiichi_Ohno
+[5]: https://opensource.com/sites/default/files/uploads/kanban-agile-lean-devops.png (Kanban complements agile and lean)
+[6]: https://opensource.com/sites/default/files/uploads/kanban-practices-terms.png (Kanban practices and terminology)
+[7]: https://opensource.com/users/anicheinc
+[8]: https://opensource.com/sites/default/files/uploads/kanban-key-learnings.png (Key kanban learnings)
+[9]: https://opensource.com/article/20/2/devops-automation
+[10]: https://opensource.com/sites/default/files/uploads/value-stream-mapping.png (value-stream mapping)
+[11]: https://opensource.com/sites/default/files/uploads/cd-pipeline.png (Continuous delivery pipeline)
+[12]: https://opensource.com/sites/default/files/uploads/splitting-jobs.png (Dividing a job between two teams)
+[13]: https://www.donovanbrown.com/post/what-is-devops
+[14]: https://opensource.com/article/19/5/values-devops-mindset
diff --git a/sources/tech/20200403 Building a sensing prosthetic with the Raspberry Pi.md b/sources/tech/20200403 Building a sensing prosthetic with the Raspberry Pi.md
new file mode 100644
index 0000000000..0eef549525
--- /dev/null
+++ b/sources/tech/20200403 Building a sensing prosthetic with the Raspberry Pi.md
@@ -0,0 +1,85 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Building a sensing prosthetic with the Raspberry Pi)
+[#]: via: (https://opensource.com/article/20/4/raspberry-pi-sensebreast)
+[#]: author: (Kathy Reid https://opensource.com/users/kathyreid)
+
+Building a sensing prosthetic with the Raspberry Pi
+======
+SenseBreast is an early prototype of a sensing mastectomy prosthetic
+based on open hardware.
+![Open source doctor.][1]
+
+_Content advisory: this article contains frank discussions of breast cancer._
+
+What's the first question you ask your surgeon when you're discussing reconstruction options after breast cancer?
+
+"How many USB ports can you give me?" is probably not the one that comes to mind for many people!
+
+Although the remark was said jokingly, it sparked a thread that would ultimately become [SenseBreast][2]—an early prototype of a sensing mastectomy prosthetic, based on open hardware.
+
+### How did SenseBreast come about?
+
+All technology has a history—an origin story of experimentation, missteps, successes, setbacks, and breakthroughs. SenseBreast is no different. SenseBreast was developed as a term project for the Masters of Applied Cybernetics—a highly selective course at the Australian National University's [3A Institute][3]. The mission of the 3Ai is to bring artificial intelligence and cyber-physical systems safely, responsibly, and sustainably to scale. The purpose of the assignment was to explore the nexus between the electronic, virtual world, and the physical, tactile world.
+
+### What is SenseBreast?
+
+SenseBreast combines two distinct elements: a cyber component—electronics, sensors, and storage for gathering data, and a physical component—a breast form designed to be worn inside a mastectomy bra. SenseBreast is a rudimentary cyber-physical system. In cyber-physical systems, physical and software components are deeply intertwined and interact in different ways depending on context.
+
+The SenseBreast draws on a rich heritage of open source hardware and software. Based on the Raspberry Pi 3B+, it uses the Debian-flavored Raspbian operating system, Python to interact with the onboard sensors, and d3.js to visualize the data that the sensors generate.
+
+Early versions of the SenseBreast used the SenseHAT, but in the true spirit of open source collaboration, I partnered with Australian open source luminary Jon Oxer to develop a custom SenseBreast board. This contains an inertial motion unit (IMU) and temperature, humidity, and pressure sensors, just like the SenseHAT, but in addition, it contains the BME680 volatile gas sensor and a breakout for a heart rate monitor.
+
+![SenseBreast open hardware board developed by Jon Oxer and Kathy Reid][4]
+
+SenseBreast is wearable tech, so the physical form of the cyber-physical system is also important. Factors like comfort, texture, and fit in clothing are important in the design of wearables because technology isn't better unless it's better for people! The early attempts at building a housing for SenseBreast were spectacular failures; in fact, the very first iteration was put together using acrylic render and linen cloth, and held together with paper clips—in true hacker style! It wasn't comfortable to wear at all, but it served as a proof point for further exploration.
+
+![First attempt at creating a breast form using acrylic render covered in linen cloth][5]
+
+Later iterations used a different approach. This involved taking a cast of a breast, using quick-dry silicone supported by a plaster cast. The resulting mold was then used with slow-setting silicone to create a true-to-life shape. A recess was carved into the form to house the electronic components, and an additional silicone layer was added to protect the wearer's skin from contact with electronics.
+
+### What did we learn from SenseBreast?
+
+The key learning from SenseBreast is that data is partial. It only tells part of a story. It can be misleading and untrustworthy, which makes the decisions based on that data unreliable too. For example, the sensor data gathered by SenseBreast was affected by how hard the CPU was working. The graph below plots a sequence of 5 minutes of data from SenseBreast, just after the device has booted. You can see that the temperature decreases over time; this is because the CPU has to work harder as the Raspberry Pi boots, and then cools down after the boot operations are completed.
+
+![Data visualisation of the readings in SenseBreast using the d3.js library][6]
+
+These sorts of learnings have implications on a broader scale.
+
+What if the SenseBreast were not an open source device, but a commercial wearable that stored data about me? What if part of the business model of that company was to sell the data that was harvested? What if my health insurer had access to that data? Or prospective employers? Now, more than ever, it's important that we have private, open solutions for sensing data about ourselves.
+
+### What's next for the SenseBreast project?
+
+The SenseBreast is a very early prototype, but it has the potential to develop through many different arcs. It could be used to assess range of movement post-surgery, to research how different garments and fabrics adjust to temperature and humidity, and to identify correlations between ambient air pressure and conditions such as lymphoedema. The path SenseBreast takes will be dependent on the passion, needs, and dedication of the incredible global open source community.
+
+You can learn more about SenseBreast at [https://sensebreast.org][2] and see my presentation at [linux.conf.au][7] 2020 [here][8].
+
+The code for SenseBreast is available on [GitHub][9].
+
+Health IT has been surprisingly unwilling to deeply support open source software. Despite the huge...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/raspberry-pi-sensebreast
+
+作者:[Kathy Reid][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/kathyreid
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/osdc_520x292_opensourcedoctor.png?itok=fk79NwpC (Open source doctor.)
+[2]: https://sensebreast.org/
+[3]: https://3ainstitute.cecs.anu.edu.au/
+[4]: https://opensource.com/sites/default/files/uploads/49427571178_bb5df37c3a_c.jpg (SenseBreast open hardware board developed by Jon Oxer and Kathy Reid)
+[5]: https://opensource.com/sites/default/files/uploads/49641040471_6d0cc91619_c.jpg (First attempt at creating a breast form using acrylic render covered in linen cloth)
+[6]: https://opensource.com/sites/default/files/uploads/49640513813_5a7d63803a_c.jpg (Data visualisation of the readings in SenseBreast using the d3.js library)
+[7]: http://linux.conf.au
+[8]: https://www.youtube.com/watch?v=G3QfZ11DCpc.
+[9]: https://github.com/KathyReid/sensebreast
diff --git a/sources/tech/20200407 Love or hate chat- 4 best practices for remote teams.md b/sources/tech/20200407 Love or hate chat- 4 best practices for remote teams.md
new file mode 100644
index 0000000000..855c622e49
--- /dev/null
+++ b/sources/tech/20200407 Love or hate chat- 4 best practices for remote teams.md
@@ -0,0 +1,92 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Love or hate chat? 4 best practices for remote teams)
+[#]: via: (https://opensource.com/article/20/4/chat-tools-best-practices)
+[#]: author: (Jen Wike Huger https://opensource.com/users/jen-wike)
+
+Love or hate chat? 4 best practices for remote teams
+======
+Plus, learn about a few open source alternatives for chat.
+![Chat via email][1]
+
+Chat is a part of most people's daily lives, especially if you work in tech, and especially if you work with teammates located in different parts of the world. It can be a great way to achieve these goals:
+
+ * **to connect**; to share with teammates on a personal level
+ * **to get work done**; to communicate with teammates about work in progress
+ * **to share**; to give notes and feedback from experiences, meetings, and interactions outside of the group that may be relevant to your work or interests
+
+
+
+I encourage you to explore [open source alternatives to chat][2] like [Mattermost][3], [Rocket.Chat][4], and [Riot][5].
+
+### To chat or not to chat, that is the question
+
+First, it's important to make time to have a discussion with each member of your team focused on answering whether they are comfortable with using a chat platform to keep in touch throughout the workday. Some people enjoy chat and see it as a vital part of their workday, getting things done and communicating with teammates who they rely on to get that work done and move forward with projects. Others struggle with chat as a way of getting work done and prefer to use it when they feel like having more casual conversations with teammates on topics less focused on work and more on social interaction and personal sharing. Some people wish chat would burn in a fire.
+
+Gather these opinions and talk through these feelings with each person. You can do this as a group or one-on-one if that feels more appropriate.
+
+Why? Because communication is important and always will be, and your team will find a way to chat no matter what you do. We're human, and need various levels and types of interaction with each other throughout our days and lives. And when it comes to our work colleagues, it's helpful to put some structure in place to guide your team.
+
+### Best practices for team chat
+
+If you have decided to use chat in some form, the next step is to place structure around when and how to use it and **not** use it. These best practices work well for teams who are working remotely and at home, as well as in the office.
+
+**1\. Create rooms and threads to focus your conversations.**
+
+My team has a room for each of our sub-teams who work on a particular project together. We also have an at-large room for all of us to banter and share.
+
+Additionally, we use threads to focus on one topic at a time which is helpful when you have several to dozens of teammates in one room together. It helps conversations to continue and not stop prematurely because they were lost in the mix of other conversations.
+
+**2\. Decide when your team will be signed in and available to talk.**
+
+Is it throughout the workday (whatever hours those are for you), during a set timeframe, or as desired?
+
+My team has set the expectation that they will be signed in and available to chat at some point during the workday **about work-related topics**, and that at that time they will check for and respond to messages that were sent to them while they were away. So, we are using it as an asynchronous way to communicate about work.
+
+For us, asynchronous chat helps us plan and schedule each day how we see fit with the goal of being productive and serving our project in the best we can _that day_.
+
+If a teammate does **not** plan on signing in and responding to messages one day, that is OK, and we set the expectation that they will send a message to let the team know. For my team, almost no communication is wrong (see guideline #4), but it should be communicated. We also review our schedules for the following week in a team meeting the week before so we know when someone will be away from their desk, not working, or blocking out a chunk of time for a project.
+
+**3\. Decide when your teammates are responsible for responding (and when they are not).**
+
+Use @ mentions if you want someone to see and respond to your question or comment in chat. Don't expect them to be watching every thread and conversation.
+
+And I would recommend that you take it a step further and define when teammates should be responsible for responding and when they should not. This type of decision is meant to free you and your teammates, not hold you down. The more you understand the expectations, the freer you are to operate within the same understood universe. When you are unsure of the rules, you may act and make decisions in fear or trepidation instead, like staying signed in to chat all day when you really just need to block it out to get something done.
+
+Our team has decided that it's nice if you can respond in chat when you are mentioned, but if you don't that is OK. Perhaps you were AFK during that time and lost track of the notification. For us, if you definitely want a response to something from someone, send them an email.
+
+**4\. Communicate clearly and with kindness.**
+
+The way we interpret messages when we are chatting via text is different than when we are chatting verbally, in-person or over video.
+
+My team uses a lot of humor, emojis, and clear, concise messages to chat with each other.
+
+We also hold weekly in-person or video conference meetings so that we can get to know each other better. The more you trust someone, the easier it is to give them the benefit of the doubt when you're confused by a message and the better you are at understanding what they are saying and what their intention is behind the text coming through to you.
+
+### Signing off
+
+What best practices does your team use? Do you love or hate chat, and why?
+
+For all kinds of teams today, chat is a special part of how we stay connected, working, and sharing with each other. Finding ways to do that in a healthy and committed way is part of everyone's responsibility.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/chat-tools-best-practices
+
+作者:[Jen Wike Huger][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jen-wike
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/email_chat_communication_message.png?itok=LKjiLnQu (Chat via email)
+[2]: https://opensource.com/alternatives/slack
+[3]: https://mattermost.com/
+[4]: https://rocket.chat/
+[5]: https://riot.im/app/
diff --git a/sources/tech/20200409 GNOME Announces Community Engagement Challenge Offering up to -65,000 in Rewards.md b/sources/tech/20200409 GNOME Announces Community Engagement Challenge Offering up to -65,000 in Rewards.md
new file mode 100644
index 0000000000..63de71fec7
--- /dev/null
+++ b/sources/tech/20200409 GNOME Announces Community Engagement Challenge Offering up to -65,000 in Rewards.md
@@ -0,0 +1,84 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (GNOME Announces Community Engagement Challenge Offering up to $65,000 in Rewards)
+[#]: via: (https://itsfoss.com/gnome-community-engagement-challenge/)
+[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
+
+GNOME Announces Community Engagement Challenge Offering up to $65,000 in Rewards
+======
+
+It’s always good to see several competitions or challenges trying to promote Free and Open-Source Software (FOSS) more than ever.
+
+In a recent effort by GNOME with the help of [Endless][1], they announced the inaugural GNOME Community Engagement Challenge.
+
+This Community Challenge is a part of their original announcement of [coding education challenge for which GNOME was granted $500,000 funding by Endless][2] last year.
+
+The three-phase challenge aims to attract new developers to engage with FOSS and potentially create new/unique solutions that would gain more traction from the next-gen coders.
+
+The challenge will involve up to $65,000 in cash prizes. Sounds exciting, right? Let’s take a look at some of the details involved in the challenge.
+
+![][3]
+
+### Why The GNOME Community Engagement Challenge?
+
+In their official [press release][4], they mentioned their primary motive for the challenge:
+
+> “Through the Challenge we hope to reach a diverse audience, to encourage beginning coders to get involved with the FOSS community to help ensure that free software is available long into the future,” said Neil McGovern, GNOME Foundation Executive Director. “What better way to do that than to reach out to the community itself to come up with creative ways to inspire the next generation?”
+
+As Neil mentioned above, it’s definitely a good idea to reach out to more people (community) to look for creative ways to promote and work on FOSS projects that will leave a significant impact on the open-source community.
+
+And, rewarding for the ideas in the form of a challenge will easily get the attention needed.
+
+### Here’s How The Community Challenge Works
+
+To quote the official announcement:
+
+> The Challenge will ask entrants to devise creative ways to promote open-source software to coders typically in high school and college. How a submission will achieve this goal has deliberately been left open-ended to encourage unique, novel approaches.
+
+So, there’s no particular constraint for the type of ideas or projects you can propose and submit. But, it would be wise to read the usual [terms and conditions][5] to know about the submission rules, eligibility, requirements, prize details, and more.
+
+Here are the key information about the three phases of the challenge as per the announcement:
+
+ * The **first phase** of the Challenge asks entrants to submit a written proposal for their concept no later than **July 1, 2020**. Twenty entries will be chosen to move to the next round and receive **$1000 each**.
+ * The **second phase** of the Challenge will require proof of concept, with four entries receiving **$5000** and moving onto the final round.
+ * The final round will call for a deliverable end product, with the winner receiving **$15,000** and the second place finisher receiving **$10,000**.
+
+
+
+They plan to announce the winner of the challenge in the spring of 2021.
+
+You can take a look at their [challenge FAQ][6] and the [official webpage][7] for more details before starting to submit your entry on **April 9th**. The last date of submission is **July 1, 2020**.
+
+Head to their website to get started and explore more about the challenge.
+
+[GNOME Community Engagement Challenge][7]
+
+### Wrapping Up
+
+I think this is a perfect opportunity for developers to get started with FOSS projects that will end up rewarding them with a good amount of money and help the community at the same time.
+
+What do you think about the community engagement challenge by GNOME? Feel free to let me know your thoughts in the comments below.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/gnome-community-engagement-challenge/
+
+作者:[Ankush Das][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/ankush/
+[b]: https://github.com/lujun9972
+[1]: https://www.endlessnetwork.com/
+[2]: https://itsfoss.com/endless-gnome-coding-education-challenge/
+[3]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/gnome-community-challenge.png?ssl=1
+[4]: https://www.gnome.org/news/2020/04/gnome-foundation-and-endless-launch-inaugural-community-engagement-challenge/
+[5]: https://www.gnome.org/challenge/terms/
+[6]: https://www.gnome.org/challenge/faq/
+[7]: https://www.gnome.org/challenge/
diff --git a/sources/tech/20200409 How to set up a remote school environment for kids with Linux.md b/sources/tech/20200409 How to set up a remote school environment for kids with Linux.md
new file mode 100644
index 0000000000..327af54c79
--- /dev/null
+++ b/sources/tech/20200409 How to set up a remote school environment for kids with Linux.md
@@ -0,0 +1,75 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to set up a remote school environment for kids with Linux)
+[#]: via: (https://opensource.com/article/20/4/school-home-linux)
+[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdoss)
+
+How to set up a remote school environment for kids with Linux
+======
+Repurpose an old computer to support the new home-schooler in your life.
+![Image by Alan Formy-Duvall][1]
+
+COVID-19 has suddenly thrown all of us into a new and challenging situation. Many of us are now working full-time from home, and for a lot of us (especially people who aren't used to working remotely), this is taking some getting used to.
+
+Another group that is similarly challenged is our kids. They can't go to school or participate in their regular after-school activities. My daughter's elementary school closed its classrooms and is teaching through an online, web-based learning portal instead. And one of her favorite extracurricular activities—a coding school where she has been learning Scratch and just recently "graduated" to WoofJS–has also gone to an online-only format.
+
+We are fortunate that so many of our children's activities can be done online now, as this is the only way they will be able to learn, share, and socialize for at least the next several months.
+
+### Setting up a temporary homeschool environment
+
+When our daughter's school went to an online-only format, we realized she needed a place and some tools to do her work. So we cleaned off her desk and cleared the toys from the floor around it to make an "office" for her. We also realized she would need a computer. While I could have shopped online and ordered a new computer (and spent at least several hundred dollars—if not more than $1,000—in the process), I chose an alternative and put an old, unused laptop back to work.
+
+If you have an unused computer sitting around and are willing to do a bit of tech work, you, too, can set something up to get your kids online. Here's how I did it.
+
+### The hardware
+
+While my daughter already has her own small IT department (as I like to say), it consists of some gaming systems, a tablet, and a Chromebook. Even her Chromebook has just an 11.6" screen and a small keyboard, so none of her devices are really quite adequate for full-time school duty.
+
+So we found ourselves in a pinch. She really needed a desktop-capable computer system with a decent-sized screen, a full keyboard, a good-quality microphone, a set of speakers, and a headphone jack. And having an external video connector helps if you decide one screen isn't enough.
+
+I didn't have a spare desktop, but I did have a laptop: a Lenovo G550 with a Pentium Dual-Core T4500 2.3GHz processor and 4GB RAM. I replaced its aging 5400RPM spindle hard drive with a 240GB solid-state drive. The laptop has a 15.6" screen, which is much easier to view than the small screens on her other devices, and a comfortable, full-size keyboard. Its CPU scores a bit better in PassMark's benchmarks (913 vs. 674) than the 1.6GHz Intel Celeron N3060 Dual-Core in the Chromebook.
+
+However, it is 10 years old, certainly on the edge of usability by today's standards. But, thanks to the efficiency of the Linux operating system, it gets the job done. I installed the latest version (v31) of [Fedora Workstation][2], but many other distributions will work just fine. If you really want to eke out every drop of performance, you could use one of the [lightweight Linux distributions][3]. The only area that required a little extra effort with Fedora was the wireless; I had to install the driver for the Broadcom WiFi hardware. But really, this was only a few extra steps and a restart, and it was good to go.
+
+Linux supports all of the other hardware in the laptop. My daughter prefers a full-sized mouse over the touchpad, so I attached one. She likes the keyboard on this laptop, but if she wants an external keyboard, there are enough USB ports to hook one up.
+
+It has a traditional 3.5mm audio jack, so she can use headphones. I recommend giving children decibel-limited headphones to protect their hearing.
+
+Even though this laptop has a 15.6" widescreen display, I think having a second monitor gives the best experience. I have a spare that I might hook up to the external VGA connector.
+
+### The software
+
+My daughter's school set up an online learning portal. The benefit is that students just need a supported web browser to log on and get to work, and I thank the school for its efforts and choice of a vendor-agnostic solution. Most Linux distributions include the Mozilla Firefox web browser installed by default, and Linux provides a full operating system, so I can install any applications she might need. Fedora is also updated regularly (unlike the old Windows Vista that came with the laptop and is no longer supported).
+
+![][4]
+
+Scratch running on Fedora
+
+Her extracurricular coding school is using the Zoom client. I'm happy to report that it was an easy [install with RPM][5] and works great on Fedora 31.
+
+### Success!
+
+My daughter has no trouble using her new laptop. She likes the [GNOME desktop][6], particularly the fact that it "Looks like Dad's!" This is turning out to be a great experiment in practical (and under-pressure) use of a Linux desktop.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/school-home-linux
+
+作者:[Alan Formy-Duval][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/alanfdoss
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/homeschool.jpg?itok=vYEd9NON (Image by Alan Formy-Duvall)
+[2]: https://getfedora.org/en/workstation/
+[3]: https://opensource.com/article/19/6/linux-distros-to-try
+[4]: https://opensource.com/sites/default/files/scratch.jpg
+[5]: https://zoom.us/download?os=linux
+[6]: https://www.gnome.org/
diff --git a/sources/tech/20200409 Print double-sided documents at home with this simple Bash script.md b/sources/tech/20200409 Print double-sided documents at home with this simple Bash script.md
new file mode 100644
index 0000000000..daacfa8365
--- /dev/null
+++ b/sources/tech/20200409 Print double-sided documents at home with this simple Bash script.md
@@ -0,0 +1,152 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Print double-sided documents at home with this simple Bash script)
+[#]: via: (https://opensource.com/article/20/4/print-duplex-bash-script)
+[#]: author: (Jim Hall https://opensource.com/users/jim-hall)
+
+Print double-sided documents at home with this simple Bash script
+======
+Use this script and save yourself the hassle and wasted paper of trying
+to manually load and print double-sided documents.
+![bash logo on green background][1]
+
+We have a laser printer at home. This Hewlett Packard LaserJet Pro CP1525nw Color Printer is an older model, but it has been a great workhorse that prints reliably and in color. I [put it on our home network][2] a few years ago using our [Raspberry Pi][3] as a print server.
+
+The LaserJet has been a great addition to my home office. Since [I launched my company][4] last year, I have relied on this little laser printer to print handouts and other materials for client meetings, workshops, and training sessions.
+
+My only gripe with this printer is that it prints single-sided only. If you want to print double-sided, you need to set up a custom print job to do it yourself. That's inconvenient and requires manual steps. In LibreOffice, I need to specifically set up the print job to print the odd-numbered pages first, then reload the paper before printing the even-numbered pages on the other side—but in reverse order.
+
+![LibreOffice print dialog][5]
+
+If I need to print a PDF that someone has sent me, the process is the same. For a four-page document, I first need to print pages 1 and 3, then reload the paper and print pages 2 and 4 in reverse order. In the GNOME print dialog, you need to select "Page Setup" to print odd pages or even pages.
+
+![Gnome print dialog][6]
+
+![Gnome page setup][7]
+
+Regardless of how I print, the overall process is to print the odd-numbered pages, reload the stack of printed pages into the paper tray, then print the even-numbered pages in reverse order. If I'm printing a four-page document, printing the even-numbered pages in reverse order means page 4 prints on the back of page 3 and page 2 prints on the back of page 1. Imagine my frustration in those few instances when I forgot to select the option to print in reverse order when printing the even-numbered pages and ruined a long print job.
+
+Similarly, it's easy to forget how to deal with documents that have an odd number of pages. In a five-page document, you first print pages 1, 3, and 5. But when you reload the printed pages into the printer, you don't want page 5. Instead, you only want to load pages 1 and 3. Otherwise, page 4 will print on the back of page 5, page 2 will print on the back of page 3, and nothing gets printed on the back of page 1.
+
+To make things easier and more reliable, I wrote a simple Bash script that automates printing duplex. This is basically a wrapper to print odd-numbered pages, remind me to reload the pages (and remove the last page if needed), then print the even-numbered pages.
+
+Whenever I need to print a document as duplex, I first convert the document to PDF. This is very easy to do. In LibreOffice, there's a toolbar icon to export directly as PDF. You can also navigate under **File— Export As—Export as PDF** to do the same. Or in any other application, there's usually a **Save to PDF** feature. When in doubt, GNOME supports printing to a PDF file instead of a printer.
+
+![Libre Office toolbar][8]
+
+![Export as PDF][9]
+
+### How it works
+
+Once I've saved to PDF, I let my Bash script do the rest. This really just automates the **lpr** commands to make printing easier. It prints odd pages first, prompts me to reload the paper, then prints the even pages. If the document has an odd number of pages, it also reminds me to remove the last page when I reload the printed pages. It's pretty simple.
+
+The only "programming" part of the script is determining the page count, and figuring out if that's an even or odd number. Both of those are easy to do.
+
+To determine the page count, I use the **pdfinfo** command. This generates useful info about a PDF document. Here's some sample output:
+
+
+```
+$ pdfinfo All\ training\ -\ catalog.pdf
+Creator: Writer
+Producer: LibreOffice 6.3
+CreationDate: Fri Oct 18 16:06:07 2019 CDT
+Tagged: no
+UserProperties: no
+Suspects: no
+Form: none
+JavaScript: no
+Pages: 11
+Encrypted: no
+Page size: 612 x 792 pts (letter)
+Page rot: 0
+File size: 65623 bytes
+Optimized: no
+PDF version: 1.5
+```
+
+That output is very easy to parse. To get the page count, I use an AWK one-line script to look for **Pages:** and print the second field.
+
+
+```
+`pages=$( pdfinfo "$1" | awk '/^Pages:/ {print $2}' )`
+```
+
+To figure out if this is an odd or even number, I use the modulo (**%**) arithmetic operator to divide by two and tell me the remainder. The modulo of two will always be zero for an even number, and one for an odd number. I use this simple test to determine if the document has an odd number of pages, so I'll need to remove the last page before printing the rest of the document:
+
+
+```
+`if [ $(( $pages % 2 )) -ne 0 ] ; then`
+```
+
+With that, writing the **print-duplex.sh** Bash script is a simple matter of calling **lpr** with the correct options to send output to my printer (**lpr -P "HP_LaserJet_CP1525nw"**), to print odd-numbered pages (**-o page-set=odd**) or even-numbered pages (**-o page-set=even**), and to print in reverse order (**-o outputorder=reverse**).
+
+### Bash script
+
+
+```
+#!/bin/sh
+# print-duplex.sh
+# simple wrapper to print duplex
+
+cat<<EOF
+$1 ($pages pages)
+\-------------------------------------------------------------------------------
+Printing odd pages first
+Please wait for job to finish printing...
+\-------------------------------------------------------------------------------
+EOF
+
+lpr -P "HP_LaserJet_CP1525nw" -o page-set=odd "$1"
+sleep $pages
+
+cat<<EOF
+===============================================================================
+Put paper back into the printer in EXACT OUTPUT ORDER (face down in tray)
+then press ENTER
+===============================================================================
+EOF
+
+pages=$( pdfinfo "$1" | awk '/^Pages:/ {print $2}' )
+
+if [ $(( $pages % 2 )) -ne 0 ] ; then
+ echo '!! Remove the last page - this document has an odd number of pages'
+fi
+
+echo -n '>'
+read x
+
+cat<<EOF
+\-------------------------------------------------------------------------------
+Printing even pages
+Please wait for job to finish printing...
+\-------------------------------------------------------------------------------
+EOF
+
+lpr -P "HP_LaserJet_CP1525nw" -o page-set=even -o outputorder=reverse "$1"
+```
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/print-duplex-bash-script
+
+作者:[Jim Hall][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jim-hall
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bash_command_line.png?itok=k4z94W2U (bash logo on green background)
+[2]: https://opensource.com/article/18/3/print-server-raspberry-pi
+[3]: https://opensource.com/resources/raspberry-pi
+[4]: https://opensource.com/article/19/9/business-creators-open-source-tools
+[5]: https://opensource.com/sites/default/files/uploads/print_dialog_-_libreoffice_0.png (LibreOffice print dialog)
+[6]: https://opensource.com/sites/default/files/uploads/print_dialog_-_gnome_0.png (Gnome print dialog)
+[7]: https://opensource.com/sites/default/files/uploads/print_dialog_-_gnome_-_page_setup.png (Gnome page setup)
+[8]: https://opensource.com/sites/default/files/uploads/toolbar_-_export_as_pdf_-_libreoffice.png (Libre Office toolbar)
+[9]: https://opensource.com/sites/default/files/uploads/file_-_export_as_pdf_-_libreoffice.png (Export as PDF)
diff --git a/sources/tech/20200409 Use Emacs Org mode to easily create LaTeX documents.md b/sources/tech/20200409 Use Emacs Org mode to easily create LaTeX documents.md
new file mode 100644
index 0000000000..461c52a8a5
--- /dev/null
+++ b/sources/tech/20200409 Use Emacs Org mode to easily create LaTeX documents.md
@@ -0,0 +1,142 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Use Emacs Org mode to easily create LaTeX documents)
+[#]: via: (https://opensource.com/article/20/4/emacs-org-mode)
+[#]: author: (Peter Prevos https://opensource.com/users/danderzei)
+
+Use Emacs Org mode to easily create LaTeX documents
+======
+You can use LaTeX for scientific and technical documents without all of
+the confusing commands and syntax you would normally need.
+![Filing cabinet for organization][1]
+
+LaTeX is a powerful system, especially for writing scientific and technical documents. But writing documents in LaTeX can be confusing because you need to know a lot of commands, and your text is littered with backslashes, curly braces, and other syntax distractions. But being productive as a writer requires that you focus on the text's content instead of how it looks. Fortunately, the [GNU Emacs][2] Org mode extension makes it easy to write plain-text documents and seamlessly export them to LaTeX and PDF.
+
+[Org mode][3] is a built-in Emacs extension that helps you keep notes, maintain to-do lists, manage projects, and author documents with a fast and effective plain-text system. Emacs also comes with [AUCTeX][4], an extensible package for writing TeX files in Emacs. AUCTeX has a preview module that shows the results of what you type, but I find it distracting because it draws my attention away from the document's content to its design. Writing text in Org mode is my preferred option because the source remains a plain-text file with minimal typesetting elements. The text is independent of its result because Org mode can export it to multiple formats, including LaTeX and PDF.
+
+Emacs is known for being difficult to use with a steep learning curve. But Emacs is only difficult when you want to fine-tune the default settings. By following a minimalist approach to using the vanilla GNU Emacs, this article will get you quickly and easily on your way to writing beautiful documents without any complex configuration.
+
+### First steps
+
+Before you begin, [install Emacs][5] and a fully functioning version of [LaTeX][6] on your computer.
+
+Next, you need to learn some conventions. In Emacs lingo, the abbreviation **C-c** means to enter **Ctrl+C** on your keyboard. The abbreviation **M-x** means **Alt+X**. The M stands for the mod key, which no longer exists in modern systems. The **S** prefix indicates the **Shift** key.
+
+The **find-file** function, which you start with the **C-x C-f** keystroke combination, creates a new document or opens an existing document. Entering this function opens a dialog in the mini-buffer at the bottom of the screen, which is where Emacs communicates with the user. Type the name of the file you want to create or open into the mini-buffer. Emacs is sensitive to file extensions, so make sure that the name of your document ends in **.org**.
+
+In Emacs speak, opening or creating a file is called ["visiting" a file][7]. Visiting a file means reading its contents into an Emacs buffer so that it is available for editing. Emacs generates a new buffer for each file you visit.
+
+### Writing prose with Org mode
+
+Once you're visiting a file, you can start typing your text the same way you would in any text editor or word processor. Some conventions: Begin the file with **#+TITLE:** to denote the title of the document and **#+AUTHOR** for your name. These options are used when exporting the file. Org mode recognizes a range of [export settings][8] to configure the output. For example, to suppress the table of contents, enter **#+OPTIONS: toc:nil**.
+
+Org mode has its own Markdown-like conventions to format your document. [Headlines][9] start with one or more asterisks. Org mode can [collapse a headline][10] to render parts of it invisible with the **TAB** or **S-TAB** keys. You can make words ***bold***, **/italic/**, **_underlined_**, or **=verbatim=**. The Org manual describes the many options for [rich text][11].
+
+One minor issue with plain-vanilla Emacs that you will quickly notice is it does not wrap lines at the end of the visible screen. Emacs has several line-wrapping functions, and [Visual Line mode][12] is the most useful for writing long-form text. To activate this mode, use **M-x** and enter **visual-line-mode** in the mini-buffer at the bottom of the screen. The **M-x** keyboard shortcut enables executing functions for which there is no direct keyboard shortcut.
+
+Adding [images][13] is as easy as adding a link to the image file within double square brackets:
+
+
+```
+`[[file:path_to_image.png]]`
+```
+
+Org has a great system for [formatting tables][14] in plain ASCII. Any line with **|** is considered part of a table. The vertical line is also the column separator. A line starting with **|-** is rendered as a horizontal rule, and rows before the first horizontal rule are header lines. A table might look like this in the source file:
+
+
+```
+| Name | id | Age |
+|-------+------+-----|
+| Peter | 1234 | 50 |
+| Sue | 4321 | 54 |
+```
+
+Both images and tables are preceded with **#+CAPTION:** to add a [caption][15]. Advanced options are also available to control float placement and size of figures.
+
+Emacs has extensive [editing functions][16] to make you more efficient when typing text. Spell checking, thesaurus, auto-completion, and an undo tree are just some of the tools that help you write efficiently.
+
+### Adding LaTeX snippets to Org
+
+In addition to the text itself, Org mode-text can include simple LaTeX commands, such as **\newpage**, within the text. Equations in standard LaTeX syntax are placed between dollar signs **$e^{i\pi} + 1 = 0$**. The **org-latex-preview** function (**C-c C-x C-l**) shows a [preview][17] of any LaTeX equations within the text buffer. Last, you can also add complete LaTeX snippets to insert complex content. The code has to be placed in an export block:
+
+
+```
+#+BEGIN_EXPORT latex
+\setlength{\unitlength}{1cm}
+\thicklines
+\begin{picture}(10,6)
+\put(2,2.2){\line(1,0){6}}
+\put(2,2.2){\circle{2}}
+\put(6,2.2){\oval(4,2)[r]}
+\end{picture}
+#+END_EXPORT
+```
+
+### Exporting to LaTeX
+
+Org mode includes a powerful export module to convert your files to many formats using the powerful [Pandoc][18] software. Start the export module with the **org-export-dispatch** function, which you can run with the **C-c C-e** keyboard shortcut. The dispatch will split your screen and provide a range of options.
+
+First, Pandoc converts the Org mode file to a LaTeX file. Then you can choose to open the LaTeX file in a new buffer or save it as a file. Org mode can also directly render a PDF file, which you can view within Emacs or save to disk.
+
+![Emacs with Org mode source and PDF preview][19]
+
+### Advanced use
+
+This article provides a first taste of writing prose in Org mode and LaTeX. Org mode has numerous configuration options to fine-tune your document or to change default settings.
+
+By default, Org mode uses the article style to export documents, but you can change this with export settings. These settings can also be used to add commands to the document header, for example:
+
+
+```
+#+LATEX_CLASS: report
+#+LATEX_CLASS_OPTIONS: [a4paper]
+#+LATEX_HEADER: \usepackage{times}
+```
+
+If you write scientific documents, the [org-ref][20] package by John Kitchin provides Org-mode modules for citations, cross-references, and bibliographies in Org mode and useful BibTeX tools to go with it.
+
+The Org mode manual's [LaTex export][21] section provides a detailed discussion of the functionality available.
+
+### Conclusion
+
+Org mode is a perfect editor for writing LaTeX. The main advantage is that you lose the clutter of LaTeX syntax and can focus on the text. This comes at no cost because you can still add LaTeX code as much as you need, and you get access to the powerful editing functions in Emacs.
+
+Using Org to write books and articles allows you to focus on the text as you combine two of the oldest and most powerful pieces of open source software.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/emacs-org-mode
+
+作者:[Peter Prevos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/danderzei
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/files_documents_organize_letter.png?itok=GTtiiabr (Filing cabinet for organization)
+[2]: https://opensource.com/article/20/3/getting-started-emacs
+[3]: https://orgmode.org
+[4]: https://www.gnu.org/software/auctex/
+[5]: https://www.gnu.org/software/emacs/
+[6]: https://www.latex-project.org/get/
+[7]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Visiting.html
+[8]: https://orgmode.org/manual/Export-Settings.html
+[9]: https://orgmode.org/manual/Headlines.html#Headlines
+[10]: https://orgmode.org/manual/Global-and-local-cycling.html#Global-and-local-cycling
+[11]: https://orgmode.org/manual/Markup-for-Rich-Contents.html#Markup-for-Rich-Contents
+[12]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Visual-Line-Mode.html
+[13]: https://orgmode.org/manual/Images.html
+[14]: https://orgmode.org/manual/Built_002din-Table-Editor.html#Built_002din-Table-Editor
+[15]: https://orgmode.org/manual/Captions.html#Captions
+[16]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Basic.html#Basic
+[17]: https://orgmode.org/manual/Previewing-LaTeX-fragments.html
+[18]: https://pandoc.org/
+[19]: https://opensource.com/sites/default/files/uploads/org-mode-latex-screenshot.png (Emacs with Org mode source and PDF preview.)
+[20]: https://github.com/jkitchin/org-ref
+[21]: https://orgmode.org/manual/LaTeX-Export.html#LaTeX-Export
diff --git a/sources/tech/20200410 Get started with Bash programming.md b/sources/tech/20200410 Get started with Bash programming.md
new file mode 100644
index 0000000000..875adb9876
--- /dev/null
+++ b/sources/tech/20200410 Get started with Bash programming.md
@@ -0,0 +1,157 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Get started with Bash programming)
+[#]: via: (https://opensource.com/article/20/4/bash-programming-guide)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Get started with Bash programming
+======
+Learn how to write custom programs in Bash to automate your repetitive
+tasks. Download our new eBook to get started.
+![Command line prompt][1]
+
+One of the original hopes for Unix was that it would empower everyday computer users to fine-tune their computers to match their unique working style. The expectations around computer customization have diminished over the decades, and many users consider their collection of apps and websites to be their "custom environment." One reason for that is that the components of many operating systems are not open, so their source code isn't available to normal users.
+
+But for Linux users, custom programs are within reach because the entire system is based around commands available through the terminal. The terminal isn't just an interface for quick commands or in-depth troubleshooting; it's a scripting environment that can reduce your workload by taking care of mundane tasks for you.
+
+### How to learn programming
+
+If you've never done any programming before, it might help to think of it in terms of two different challenges: one is to understand how code is written, and the other is to understand what code to write. You can learn _syntax_—but you won't get far without knowing what words are available to you in the _language_. In practice, you start learning both concepts all at once because you can't learn syntax without words to arrange, so initially, you write simple tasks using basic commands and basic programming structures. Once you feel comfortable with the basics, you can explore more of the language so you can make your programs do more and more significant things.
+
+In [Bash][2], most of the _words_ you use are Linux commands. The _syntax_ is Bash. If you already use Bash on a frequent basis, then the transition to Bash programming is relatively easy. But if you don't use Bash, you'll be pleased to learn that it's a simple language built for clarity and simplicity.
+
+### Interactive design
+
+Sometimes, the hardest thing to figure out when learning to program is what a computer can do for you. Obviously, if a computer on its own could do everything you do with it, then you wouldn't have to ever touch a computer again. But the reality is that humans are important. The key to finding something your computer can help you with is to take notice of tasks you repeatedly do throughout the week. Computers handle repetition particularly well.
+
+But for you to be able to tell your computer to do something, you must know how to do it. This is an area Bash excels in: interactive programming. As you perform an action in the terminal, you are also learning how to script it.
+
+For instance, I was once tasked with converting a large number of PDF books to versions that would be low-ink and printer-friendly. One way to do this is to open the PDF in a PDF editor, select each one of the hundreds of images—page backgrounds and textures counted as images—delete them, and then save it to a new PDF. Just one book would take half a day this way.
+
+My first thought was to learn how to script a PDF editor, but after days of research, I could not find a PDF editing application that could be scripted (outside of very ugly mouse-automation hacks). So I turned my attention to finding out to accomplish the task from within a terminal. This resulted in several new discoveries, including GhostScript, the open source version of PostScript (the printer language PDF is based on). By using GhostScript for the task for a few days, I confirmed that it was the solution to my problem.
+
+Formulating a basic script to run the command was merely a matter of copying the command and options I used to remove images from a PDF and pasting them into a text file. Running the file as a script would, presumably, produce the same results.
+
+### Passing arguments to a Bash script
+
+The difference between running a command in a terminal and running a command in a shell script is that the former is interactive. In a terminal, you can adjust things as you go. For instance, if I just processed **example_1.pdf** and am ready to process the next document, to adapt my command, I only need to change the filename.
+
+A shell script isn't interactive, though. In fact, the only reason a shell _script_ exists is so that you don't have to attend to it. This is why commands (and the shell scripts that run them) accept arguments.
+
+In a shell script, there are a few predefined variables that reflect how a script starts. The initial variable is **$0**, and it represents the command issued to start the script. The next variable is **$1**, which represents the first "argument" passed to the shell script. For example, in the command **echo hello**, the command **echo** is **$0,** and the word **hello** is **$1**. In the command **echo hello world**, the command **echo** is **$0**, **hello** is **$1**, and **world** is **$2**.
+
+In an interactive shell:
+
+
+```
+$ echo hello world
+hello world
+```
+
+In a non-interactive shell script, you _could_ do the same thing in a very literal way. Type this text into a text file and save it as **hello.sh**:
+
+
+```
+`echo hello world`
+```
+
+Now run the script:
+
+
+```
+$ bash hello.sh
+hello world
+```
+
+That works, but it doesn't take advantage of the fact that a script can take input. Change **hello.sh** to this:
+
+
+```
+`echo $1`
+```
+
+Run the script with two arguments grouped together as one with quotation marks:
+
+
+```
+$ bash hello.sh "hello bash"
+hello bash
+```
+
+For my PDF reduction project, I had a real need for this kind of non-interactivity, because each PDF took several minutes to condense. But by creating a script that accepted input from me, I could feed the script several PDF files all at once. The script processed each one sequentially, which could take half an hour or more, but it was a half-hour I could use for other tasks.
+
+### Flow control
+
+It's perfectly acceptable to create Bash scripts that are, essentially, transcripts of the exact process you took to achieve the task you need to be repeated. However, scripts can be made more powerful by controlling how information flows through them. Common methods of managing a script's response to data are:
+
+ * if/then
+ * for loops
+ * while loops
+ * case statements
+
+
+
+Computers aren't intelligent, but they are good at comparing and parsing data. Scripts can feel a lot more intelligent if you build some data analysis into them. For example, the basic **hello.sh** script runs whether or not there's anything to echo:
+
+
+```
+$ bash hello.sh foo
+foo
+$ bash hello.sh
+
+$
+```
+
+It would be more user-friendly if it provided a help message when it receives no input. That's an if/then statement, and if you're using Bash in a basic way, you probably wouldn't know that such a statement existed in Bash. But part of programming is learning the language, and with a little research you'd learn about if/then statements:
+
+
+```
+if [ "$1" = "" ]; then
+ echo "syntax: $0 WORD"
+ echo "If you provide more than one word, enclose them in quotes."
+else
+ echo "$1"
+fi
+```
+
+Running this new version of **hello.sh** results in:
+
+
+```
+$ bash hello.sh
+syntax: hello.sh WORD
+If you provide more than one word, enclose them in quotes.
+$ bash hello.sh "hello world"
+hello world
+```
+
+### Working your way through a script
+
+Whether you're looking for something to remove images from PDF files, or something to manage your cluttered Downloads folder, or something to create and provision Kubernetes images, learning to script Bash is a matter of using Bash and then learning ways to take those scripts from just a list of commands to something that responds to input. It's usually a process of discovery: you're bound to find new Linux commands that perform tasks you never imagined could be performed with text commands, and you'll find new functions of Bash to make your scripts adaptable to all the different ways you want them to run.
+
+One way to learn these tricks is to read other people's scripts. Get a feel for how people are automating rote commands on their systems. See what looks familiar to you, and look for more information about the things that are unfamiliar.
+
+Another way is to download our [introduction to programming with Bash][3] eBook. It introduces you to programming concepts specific to Bash, and with the constructs you learn, you can start to build your own commands. And of course, it's free to download and licensed under a [Creative Commons][4] license, so grab your copy today.
+
+### [Download our introduction to programming with Bash eBook!][3]
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/bash-programming-guide
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/command_line_prompt.png?itok=wbGiJ_yg (Command line prompt)
+[2]: https://opensource.com/resources/what-bash
+[3]: https://opensource.com/downloads/bash-programming-guide
+[4]: https://opensource.com/article/20/1/what-creative-commons
diff --git a/sources/tech/20200410 How Kubernetes saved my desktop application.md b/sources/tech/20200410 How Kubernetes saved my desktop application.md
new file mode 100644
index 0000000000..ecbd6ee273
--- /dev/null
+++ b/sources/tech/20200410 How Kubernetes saved my desktop application.md
@@ -0,0 +1,55 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How Kubernetes saved my desktop application)
+[#]: via: (https://opensource.com/article/20/4/kubernetes-desktop-application)
+[#]: author: (Chris Hermansen https://opensource.com/users/clhermansen)
+
+How Kubernetes saved my desktop application
+======
+Keep this fix in mind if you have a broken Java desktop application but
+aren't a crypto expert.
+![Puzzle pieces coming together to form a computer screen][1]
+
+Recently, fellow Opensource.com scribe James Farrell wrote a wonderful article entitled _[How Ansible brought peace to my home][2]_. In addition to the great article, I really liked the title, one of those unexpected phrases that I’m sure brought a smile to many faces.
+
+I recently had a weird but positive experience of my own that begs a similar sort of unexpected label. I’ve been grappling with a difficult problem that arose when upgrading some server and networking infrastructure that broke a Java application I’ve been supporting since the early 2000s. Strangely enough, I found the solution in what appears to be a very informative and excellent article on Kubernetes, of all things.
+
+Without further ado, here is my problem:
+
+![][3]
+
+I’m guessing that most readers will look at that message and think things like, "I hope there’s more info in the log file," or "I’m really glad I’ve never received a message like that."
+
+Unfortunately, there isn’t a lot of info in the log file, just the same message, in fact. In an effort to debug this, I did three things:
+
+ 1. I searched online for the message. Interestingly, or perhaps ominously, there were only 200 or so hits on this string, [one of which suggested][4] [turn][4][ing][4] [on more debugging output][4], which involved adding the setting
+
+
+```
+**-Djavax.net.debug=ssl:handshake:verbose**[/code] to the **java** command running the application.
+
+ 2. I tried that suggestion, which resulted in a lot of output (good), most of which only vaguely made sense to me as I’m no kind of expert in the underlying bits of stuff like SSL. But one thing I did notice is that there was no information regarding a response from the server in the midst of all of that output;
+
+ 3. So I searched some more.
+
+
+
+
+Another interesting part of this problem is that the code ran fine when executed by the Java command bundled in the OpenJDK, but failed with this error when using a customized runtime [created from the same OpenJDK in this way][5]. So the relatively modest number of apparently similar problems turned up from search #1 above were actually not all that relevant since they all seemed to be dealing mostly with bad SSL certificates on the server in conjunction with the PostgreSQL JDBC’s ability to check the server’s credentials.
+
+I should also mention that it took me quite some time to realize that the problem was introduced by using the custom Java runtime, as I managed to check many other possibilities along the way (and indeed, I did fix a few minor bugs while I was at it). My efforts included things like getting the latest OpenJDK, checking and re-checking all the URLs in case one had a typo, and so forth.
+
+As often happens, after putting the problem aside for a few hours, an idea occurred to me—perhaps I was missing some module in the customized Java runtime. While I didn’t receive any errors directly suggesting that problem, the observable fact that the standard OpenJDK environment worked while the custom one failed seemed to hint at that possibility. I took a quick look in the **jmods/** folder in the OpenJDK installation, but there are some 70 modules there and nothing jumped out at me.
+
+But again, what seemed odd was, with debugging turned on (see #1 above), there was no indication of what the server would accept, just what the client mostly couldn’t offer, many lines like this:
+```
+`Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA`
+```
+So I was at least thinking by this time that maybe what was missing was the module that offered those kinds of cipher suites. So I started searching with strings like "jdbc crypto," and in the midst of that, the most unlikely article showed up: [Optimizing Kubernetes Services—Part 2: Spring Web][6], written by [Juan Medina][7]. Midway down the article, I spotted the following:
+
+![][8]
+
+Huh! Imagine that, his script is creating a custom Java runtime, just like mine. But he says he needs to add in manually the module **jdk.crypto.ec** in order t
\ No newline at end of file
diff --git a/sources/tech/20200412 Use this helpful Bash script when stargazing.md b/sources/tech/20200412 Use this helpful Bash script when stargazing.md
new file mode 100644
index 0000000000..f9e39e5632
--- /dev/null
+++ b/sources/tech/20200412 Use this helpful Bash script when stargazing.md
@@ -0,0 +1,121 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Use this helpful Bash script when stargazing)
+[#]: via: (https://opensource.com/article/20/4/linux-astronomy)
+[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdoss)
+
+Use this helpful Bash script when stargazing
+======
+Keep your eyes on the stars by putting your Linux machine in night
+vision mode with xcalib.
+![Computer laptop in space][1]
+
+We often talk about [Linux][2] being used on servers and by developers, but it is used in many other fields too, including astronomy. There are a lot of astronomy tools available for Linux, such as sky maps, star charts, and interfaces to telescope drive systems for controlling your telescope. But one challenge for astronomers is using a computer while keeping their eyes working in the dark.
+
+When working out in the field at night, astronomers need to preserve their night vision. It can take up to 30 minutes for the human eye to fully dilate and adjust to low light levels, and doing things like checking a phone or laptop at the regular color and brightness levels can cause the eyes to lose their adjustment. This reduces the ability to see in the dark. An example anyone can understand: if you're reading something on your phone in bed at night and get up to go to the bathroom, you know how difficult it can be to see any obstacles that might be in your way.
+
+### A solution
+
+I'd like to present a nifty little script to help the astronomer in your family keep "their eyes" in the dark. It relies on a utility called [xcalib][3], a "tiny monitor calibration loader for X.org." It can be installed easily using your Linux package manager.
+
+On Fedora, for example:
+
+
+```
+$ sudo dnf info xcalib
+$ sudo dnf install xcalib
+```
+
+Or Ubuntu:
+
+
+```
+`$ sudo apt-get install xcalib`
+```
+
+The xcalib application works only with X11, so it is not functional on Wayland systems. But Wayland has this functionality built-in, so you can get the same results through GNOME Settings. If you're using X11, xcalib is an easy way to change the color temperature of your display.
+
+### The script
+
+I discovered [Redscreen][4], a night vision filter script written by Jeff Jahr in 2014. The original script is written for the C shell, but Bash is the common default these days. In fact, the C shell is not installed by default on my current Fedora Linux workstation. So, I decided to write an updated version of the Redscreen script aimed at the newest Bash syntax, but I made one major change: utilizing a case statement.
+
+
+```
+#!/usr/bin/bash
+# redscreen.sh Fri Feb 28 11:36 EST 2020 Alan Formy-Duval
+# Turn screen red - Useful to Astronomers
+# Inspired by redscreen.csh created by Jeff Jahr 2014
+# ()
+
+# This program is free software: you can redistribute it
+# and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation,
+# either version 3 of the License, or (at your option) any
+# later version.
+
+# This program is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for
+# more details.
+
+# You should have received a copy of the GNU General Public
+# License along with this program.
+# If not, see <[http://www.gnu.org/licenses/\>][5].
+
+case $1 in
+ on)
+ # adjust color, gamma, brightness, contrast
+ xcalib -green .1 0 1 -blue .1 0 1 -red 0.5 1 40 -alter
+ exit 1
+ ;;
+ off)
+ xcalib -clear
+ exit 1
+ ;;
+ inv)
+ # Invert screen
+ xcalib -i -a
+ exit 1
+ ;;
+ dim)
+ # Make the screen darker
+ xcalib -clear
+ xcalib -co 30 -alter
+ exit 1
+ ;;
+ *)
+ echo "$0 [on | dim | inv | off]"
+ exit 1
+ ;;
+esac
+```
+
+![Skychart for Linux Version 4.2.1 on Fedora workstation][6]
+
+A lot of astronomy programs include a "night-mode" function, but not all do. Also, this script provides a way to affect the entire screen, not just a specific application. This allows you to use your Linux system out in the field at night for other things than just stargazing—such as checking email or reading Opensource.com—without ruining your night vision.
+
+Whether you are an astronomer or just an amateur stargazer, you can spend all night admiring the heavens using Linux and open source!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/linux-astronomy
+
+作者:[Alan Formy-Duval][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/alanfdoss
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_space_graphic_cosmic.png?itok=wu493YbB (Computer laptop in space)
+[2]: https://opensource.com/resources/linux
+[3]: http://xcalib.sourceforge.net/
+[4]: http://www.jeffrika.com/~malakai/redscreen/index.html
+[5]: http://www.gnu.org/licenses/\>
+[6]: https://opensource.com/sites/default/files/uploads/starchart_in_red.png (A star chart displayed in red screen mode)
diff --git a/sources/tech/20200414 How young people can help fight COVID-19 with code.md b/sources/tech/20200414 How young people can help fight COVID-19 with code.md
new file mode 100644
index 0000000000..73705b5a62
--- /dev/null
+++ b/sources/tech/20200414 How young people can help fight COVID-19 with code.md
@@ -0,0 +1,139 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How young people can help fight COVID-19 with code)
+[#]: via: (https://opensource.com/article/20/4/covid19-hackathon)
+[#]: author: (Melissa Sasi https://opensource.com/users/mesassi)
+
+How young people can help fight COVID-19 with code
+======
+Youth developers are invited to submit ideas by April 15 to counter the
+educational, informational, social, and health challenges uncovered by
+the COVID-19 pandemic.
+![woman on laptop sitting at the window][1]
+
+More than 91% of students around the world are impacted by school closures due to COVID-19, and most governments have temporarily closed academic institutions. That's nearly [1.6 billion young people in 188 countries][2]. Also, most of the learning platforms available online today aren't practical, engaging, or interactive, and lack true virtual collaboration.
+
+This big and wicked challenge got me thinking about how these circumstances are impacting my children, their friends, and my passions of empowering youth, fostering tech entrepreneurship, and inspiring under-represented communities to find their purpose through building digital skills. These all came together in [CodeTheCurve][3], "a global, virtual hackathon for students, educators, teachers, and the research community to build tech skills, entrepreneurial spirit, and professional competencies to build digital creativity and cooperation to mobilize the world."
+
+We hope you'll want to participate, but you need to act fast: the deadline to submit proposals is April 15.
+
+### My story
+
+The passions mentioned above stem from a deeply personal journey: My children and I are victims of parental kidnapping, and access to the internet and digital literacy are my pathways to being a mother from afar. My children, Zahra (age 13), Zahran (15), and Youmna (18), are safe and healthy, and we are frequently connected. They're living the same life youth all over the world are living these days, trying to social distance and remain in good health while figuring out this school thing (or lack thereof)—only one of my children has access to formal virtual learning during to COVID-19 school closures. The other two, without school-driven online learning options, tend to stay up all night playing Fortnight and making TikTok videos.
+
+I have always been passionate about digital inclusion and empowering the world through computer science, and the effects of COVID-19 have increased my desire to make a difference. About four years ago, I created a non-profit organization, [MentorNations][4], to inspire youth and the world via technology. My non-profit has taught tens of thousands of young people in 12 countries to code. In my work at IBM as a developer advocate, I focus on empowering early-stage entrepreneurs, developers, and students with access to tech skills, professional development, and entrepreneurial thinking. My major focus areas include inspiring students to discover their career potential in enterprise computing while recognizing that we are all ANDs and not ORs.
+
+Teaching the next generation about the power of collaboration, teamwork, problem-solving, and critical thinking that happen through open source code and principles empowers them to be creators and innovators who focus on solving relevant and real-world problems.
+
+Looking through the lens of my children, my non-profit work, my roles within a variety of United Nations Task Forces, and my position as IEEE Chair over the Digital Skills Working Group, I wondered, _**what can I do to make a difference with open source technology?**_ So I reached out to my network, and the world responded in a much bigger way than I had ever imagined.
+
+### CodeTheCurve
+
+In response, we launched UNESCO's [CodeTheCurve][3] hackathon in collaboration with 14 partners, including UN EQUALS, SAP, iHackOnline, Angel Hack, Internet Society, and YPO. Participants are invited to bring their open source ideas to combat the current and future environment and challenges relating to COVID-19. This initiative is centered around youth empowerment, gender inclusion, and making the world a better place for our communities, including for people we may not directly encounter daily.
+
+CodeTheCurve is for anyone above the age of 16. To ensure gender, age, and experience diversity, teams must include a developer or data scientist (early-stage chops are fine); at least one person under the age of 25; and at least one male and one female. The 40 teams selected to participate in CodeTheCurve will have access to more than 80 business and technical mentors (experts!) from around the world to help turn their ideas into reality.
+
+My vision for this hackathon is to train young talent; enable them with free, online resources and access to real people with real answers; and encourage the creation of real-world problem solving in real-time. The results of the hackathon, I hope, will be open source utilities and information that can be used, in some way, to combat COVID-19.
+
+#### Week-long learning, bootcamp, and hacking experience
+
+CodeTheCurve is a three-day virtual hackathon experience guided by expert business and technical mentors. Before the hackathon proper, participants begin with two days of self-paced, online learning from content curated by CodeTheCurve collaborators, followed by a two-day, instructor-led learning journey where the 40 selected teams will collaborate in virtual breakout rooms with activity kits, hands-on computing resources in machine learning, and expert-guided plenary sessions.
+
+#### CodeTheCurve hackathon themes
+
+CodeTheCurve includes three themes:
+
+ * Education
+ * Information and data management
+ * Current and post-COVID-19 health and social issues
+
+
+
+#### Professional development, entrepreneurship, and hands-on open source skills
+
+The 40 teams will be empowered with expert-guided, engaging activities, including the following skill-building opportunities:
+
+ * **Hand-on tech skills**
+ * Using Jupyter Notebooks for data science
+ * Data protection, privacy, security, and encryption
+ * Machine learning and artificial intelligence
+ * Architectural diagrams and frameworks
+ * Technical roadmaps
+ * **Professional development**
+ * Design thinking
+ * Personal branding
+ * Communication skills
+ * How not to feel like an imposter
+ * Conflict resolution
+ * Working in global, virtual teams
+ * Media literacy
+ * Ethics in machine learning and artificial intelligence
+ * **Entrepreneurship**
+ * Problem statements
+ * Mission and vision statements
+ * Value propositions
+ * Audience and target markets
+ * Business model canvassing
+ * Pitch decks
+ * Pitch practice
+
+
+
+### April 15: CodeTheCurve deadline
+
+Did I mention that the initial application deadline is April 15? Here's the full timeline:
+
+ * Video submission deadline: **April 15**
+ * 40 selected teams announced: **April 20**
+ * Learning resources for pre-collaboration: **April 20-21**
+ * Instructor-led learning: **April 22-23**
+ * Hacking: **April 24-26**
+ * CodeTheCurve winners announced: **April 30**
+
+
+
+#### Prizes. Prizes. Prizes.
+
+Prizes include free access to [IBM LinuxONE Community Cloud][5] for one year, free training courses from SAP, four pitch opportunities at IBM and SAP events, free access to enterprise-grade IBM Z and its machine learning suite for six months, and one-on-one technical and business mentorship for a full year with industry experts.
+
+### How to apply
+
+Interested in applying? Know someone who should apply? Simply [submit a video][6] of your **amazing** open source idea, the problem you're trying to solve, and who you expect to reach.
+
+If you'd like to learn more, here are some other articles about CodeTheCurve:
+
+ * [UN News CodeTheCurve article][7]
+ * [UNESCO CodeTheCurve blog][8]
+ * [Forbes CodeTheCurve article][9]
+ * [IBM CodeTheCurve blog][10]
+
+
+
+I cannot wait to see all the amazing open source ideas the world brings our way!
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/covid19-hackathon
+
+作者:[Melissa Sasi][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mesassi
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-window-focus.png?itok=g0xPm2kD (young woman working on a laptop)
+[2]: https://en.unesco.org/covid19/educationresponse
+[3]: https://www.codethecurve.org/
+[4]: https://mentornations.org/
+[5]: https://developer.ibm.com/linuxone/
+[6]: http://ibm.biz/codethecurve-apply
+[7]: https://news.un.org/en/story/2020/04/1061142
+[8]: http://ibm.biz/unesco-pr
+[9]: https://www.forbes.com/sites/danielnewman/2020/04/10/digital-transformation-for-good-shines-as-we-fight-covid-19/#78d51a4c4946
+[10]: http://ibm.biz/codethecurve
diff --git a/sources/tech/20200414 Try this Kubernetes HTTP router and reverse proxy.md b/sources/tech/20200414 Try this Kubernetes HTTP router and reverse proxy.md
new file mode 100644
index 0000000000..fc78ee9bce
--- /dev/null
+++ b/sources/tech/20200414 Try this Kubernetes HTTP router and reverse proxy.md
@@ -0,0 +1,196 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Try this Kubernetes HTTP router and reverse proxy)
+[#]: via: (https://opensource.com/article/20/4/http-kubernetes-skipper)
+[#]: author: (Sandor Szücs https://opensource.com/users/sszuecs)
+
+Try this Kubernetes HTTP router and reverse proxy
+======
+Skipper is designed to handle large numbers of HTTP route definitions,
+beyond what you would want to manage in Nginx or Apache.
+![Traffic circle with arrows pointing which way to go][1]
+
+Skipper is an open source HTTP router and reverse proxy for service composition. As its [GitHub page][2] states, it's designed to handle large amounts of dynamically configured HTTP route definitions (>600,000 routes) with detailed lookup conditions and flexible augmentation of the request flow with filters. It can be used out of the box or extended with custom lookup, filter logic, and configuration sources.
+
+### Proxies
+
+When some people think of a proxy, they imagine a webpage that serves as a gateway to an intranet or a suspicious-looking webpage designed to unblock social media sites on a school or work network. A forward proxy is one that operators of desktop infrastructure use to save internet bandwidth, enforce parental controls, or limit social media access. Another kind of proxy is one in which an individual user navigates to a page, provides credentials, and is then forwarded to a protected intranet resource. The inverse of that kind of proxy is the reverse proxy, which accepts all traffic and forwards it to a specific resource, like a server or container. That's the kind of work Skipper does for infrastructure.
+
+When I read [Matt Klein's post][3] on modern network load balancing and proxying, I realized that we, as [Skipper][4] maintainers, should explain more features and details about why and how you can leverage HTTP proxies. In this article, I will treat the terminology "HTTP (reverse) proxy" and "HTTP router" as the same.
+
+### HTTP routing
+
+According to [Wikipedia][5]: "Routing is the process of selecting a path for traffic in a network." This definition refers to routing at [OSI layer 3][6], most commonly based on [IP][7] with routing protocols like [BGP][8] or [OSPF][9]. Since this article isn't about one of those, I will try to explain what HTTP routers are about. But first, I want to introduce Skipper, an [OSI layer 7][10] HTTP router library written in [Go][11] and a core component of retailer [Zalando][12]'s e-commerce shop and the [Kubernetes][13] Ingress infrastructure.
+
+At Zalando, we use Skipper as a [Kubernetes Ingress][14] controller to support our users with visibility, reliability, security, and additional features to offload common applications.
+
+Any organization running HTTP services, often in a microservice architecture, needs to route HTTP requests to the right applications. HTTP routers route based on information provided by the HTTP request. For example, the following shows an HTTP/1.1 request.
+
+
+```
+GET /details HTTP/1.1
+Host: [www.zalando.de][15]
+User-Agent: curl/7.49.0
+Accept: */*
+Authorization: Bearer <token>
+...
+```
+
+We can route based on the method **GET**, the path **/details**, the **Host** header [**www.zalando.de**][16], or any arbitrary part of the request.
+
+One common problem an application owner faces is splitting an API into multiple applications, so you need to split the responsibility of a component into subcomponents. Another common task is to support refactoring; maybe you have rewritten one part of your app, and you want to deploy it separately now.
+
+For example, imagine you you have a store that has a list of products and their details, and you need to split it into _shop_ and _product_ backend applications. At **/**, your shop shows the list of products, and at **/details**, it shows product details, such as color, size, sustainability, and price.
+
+![Figure 1: shop][17]
+
+You need to split the responsibility of the product detail into its own application, such that **/** stays in the _shop_ application and **/details** is refactored to the _product_ application.
+
+![Figure 2: product and shop][18]
+
+To make sure an HTTP proxy finds the right backend for an incoming request, it uses a routing table to check the destination to make sure it's correct.
+
+### Routing tables
+
+In Skipper, the routing table is created by pulling information generated by [dataclients][19] from different sources. One source can be a [routes file][20], similar to what you may see in more popular HTTP servers, like Apache or Nginx.
+
+Depending on the size of your organization—or better, the number of backend applications—the routing table can grow quite large. Skipper implements the routing table as a tree that can scale beyond 600,000 routes (far more than you'd want to manage in an Nginx or Apache config).
+
+Following along with the example application above, Table 1 shows the routing table from [Figure 2][21]. The store **/** should be routed to **shop,** and the **/detail** routed to the **product** application.
+
+path | app
+---|---
+/ | shop
+/detail | product
+
+Table 1: Routing table
+
+The available dataclients in Skipper fetch routes from different sources and what a route consists of.
+
+### Dataclient
+
+The routing configuration in Skipper's routes file [dataclient][22] is similar to what you might know from HTTP proxies in Nginx or Apache. In Skipper, a routes file specifies all routes in [eskip][23] syntax, as shown in Figure 3.
+
+
+```
+r1: P1() && P2() && .. && PN()
+ -> f1()
+ -> f2()
+ ...
+ -> fN()
+ -> <backend>;
+r2: ...
+...
+```
+
+Figure 3: Routes file in eskip
+
+In the above:
+
+ * **r1, r2, ...** are unique routeIDs.
+ * **P1, P2,..,PN** are predicates that define the matching.
+ * **f1, f2,..,fN** are filters that are applied after the route was selected. Filters can change the request and response.
+ * Finally, the Skipper backend is defined. This can be a single URL, a list of load-balanced URLs, and others for special cases such as [direct response][24].
+
+
+
+The [routes string][25] is another dataclient that is handy for tests. For example, if you need a pseudo backend for your demo that replies a green background with HTML, you could use:
+
+
+```
+$ skipper -routes-string='*
+-> inlineContent(
+ "<html><body style=\"background-color: green;\"></body></html>"
+ )'
+```
+
+Skipper's most popular dataclient, by far, is the Kubernetes dataclient, which is used to fetch information from a [Kubernetes API server][26] and create a routing table from [Skipper Ingress][27] resources and the [RouteGroup][28] custom resource definition (CRD).
+
+To summarize the above, dataclients fetch information from different providers to build Skipper's routing table. Table 1 shows a routing table for the shop/description example, and Skipper uses predicates to select the route to process the request.
+
+### Predicates
+
+In Skipper, an incoming request is matched to [predicates][29] of all the routes to find the best matching route for an incoming request. Predicates are functions that match based on the incoming request. In the example from Figure 2 and Table 1, Skipper would have a routing table similar to Figure 4:
+
+
+```
+shop: Path("/")
+ -> "";
+product: Path("/detail")
+ -> "";
+```
+
+Figure 4: Skipper routing table
+
+This means HTTP requests with a path **/** would be matched by the **Path("/")** predicate, such that Skipper will execute the shop route. Requests with a path **/detail** would be matched by **Path("/detail")** and routed to the product application.
+
+In general, routing behavior can be changed by predicates. There are a lot of predicates you can choose from. For example, **Method("POST")** will be true only if a POST request would be passed. A route with more predicates is considered more specific. Also, a route with more predicates has more weight in the route selection than one that has less.
+
+Special cases are **Path()** and **PathSubtree()**, which is matched first in a tree and reduces the number of routes, which are scanned as a list. For example, the tree structure shown in Figure 5 helps to scale the number of routes to more than 600,000 in one of Zalando's production setups.
+
+![Skipper tree example][30]
+
+### Filters
+
+After a route is selected, the request [filters][31] are applied. Filters work on request or response; they can change the incoming request to the backend, and they can change the response to the client.
+
+For example, **setRequestHeader("Foo", "bar")** sets the HTTP header **"Foo"** to the value **"bar"**, such that the backend sees this header in the request.
+
+The response filter **responseCookie("keks", "val", 3600)** sets a Cookie named **"keks"** in the response to the caller, which might be a browser in this case. The cookie would have the value **"val"** and is valid for one hour.
+
+One filter that works on request and response is **enableAccessLog(40, 5)**. This would do access logs for all responses from the backend with status codes 40x or 5xx.
+
+As you can see from the examples, filters can change the request or the response or just do some work based on it. Another filter example is **auth filters** or **ratelimits**. These would stop requests from passing to the backend if the request should not be allowed to pass. For example, to serve static content from a directory called **/var/www**, you can use the filter **static("/var/www")**.
+
+### Learn more
+
+This article provided a basic overview of Skipper and its capabilities. For more information, consult [Skipper's documentation][32], and please share your questions or feedback in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/http-kubernetes-skipper
+
+作者:[Sandor Szücs][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sszuecs
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LAW-patent_reform_520x292_10136657_1012_dc.png?itok=Cd2PmDWf (Traffic circle with arrows pointing which way to go)
+[2]: https://github.com/zalando/skipper
+[3]: https://blog.envoyproxy.io/introduction-to-modern-network-load-balancing-and-proxying-a57f6ff80236
+[4]: https://opensource.zalando.com/skipper
+[5]: https://en.wikipedia.org/wiki/Routing
+[6]: https://en.wikipedia.org/wiki/OSI_model#Layer_3:_Network_Layer
+[7]: https://en.wikipedia.org/wiki/Internet_Protocol
+[8]: https://en.wikipedia.org/wiki/Border_Gateway_Protocol
+[9]: https://en.wikipedia.org/wiki/Open_Shortest_Path_First
+[10]: https://en.wikipedia.org/wiki/OSI_model#Layer_7:_Application_Layer
+[11]: https://golang.org/
+[12]: https://en.zalando.de/
+[13]: https://kubernetes.io
+[14]: https://kubernetes.io/docs/concepts/services-networking/ingress/
+[15]: http://www.zalando.de
+[16]: https://en.zalando.de/?_rfl=de
+[17]: https://opensource.com/sites/default/files/uploads/skipper_1_shop.png (Figure 1: shop)
+[18]: https://opensource.com/sites/default/files/uploads/skipper_2_product-shop.png (Figure 2: product and shop)
+[19]: https://opensource.zalando.com/skipper/reference/backends/
+[20]: https://opensource.zalando.com/skipper/data-clients/eskip-file/
+[21]: tmp.ftM58r5YpM#fig2
+[22]: https://opensource.zalando.com/skipper/tutorials/development/#dataclients
+[23]: https://godoc.org/github.com/zalando/skipper/eskip
+[24]: https://opensource.zalando.com/skipper/reference/backends/#shunt-backend
+[25]: https://opensource.zalando.com/skipper/data-clients/route-string/
+[26]: https://kubernetes.io/docs/concepts/overview/components/#kube-apiserver
+[27]: https://opensource.zalando.com/skipper/kubernetes/ingress-usage/
+[28]: https://opensource.zalando.com/skipper/kubernetes/routegroups/
+[29]: https://opensource.zalando.com/skipper/reference/predicates/
+[30]: https://opensource.com/sites/default/files/uploads/skipper_5_tree.png (Skipper tree example)
+[31]: https://opensource.zalando.com/skipper/reference/filters/
+[32]: https://opensource.zalando.com/skipper/
diff --git a/sources/tech/20200415 6 open source teaching tools for virtual classrooms.md b/sources/tech/20200415 6 open source teaching tools for virtual classrooms.md
new file mode 100644
index 0000000000..807ebfae3d
--- /dev/null
+++ b/sources/tech/20200415 6 open source teaching tools for virtual classrooms.md
@@ -0,0 +1,96 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (6 open source teaching tools for virtual classrooms)
+[#]: via: (https://opensource.com/article/20/4/open-source-remote-teaching-tools)
+[#]: author: (Mathias Hoffmann https://opensource.com/users/mhopensource)
+
+6 open source teaching tools for virtual classrooms
+======
+Create podcasts, online lectures, tutorials, and other teaching
+resources for learning at home with open source tools.
+![Person reading a book and digital copy][1]
+
+As schools and universities are shutting down around the globe due to COVID-19, many of us in academia are wondering how we can get up to speed and establish a stable workflow to get our podcasts, online lectures, and tutorials out there for our students.
+
+Open source software (OSS) has a key role to play in this situation for many reasons, including:
+
+ * **Speed:** OSS can roll out quickly and in large numbers (e.g., to an army of teaching assistants for multiple tutorial sessions in big lectures) without licensing issues and in a decentralized manner.
+ * **Cost:** OSS does not cost anything upfront, which is important for financially stretched schools and universities that need solutions to complex challenges on very short notice.
+
+
+
+With everything going online, we need new ways to engage with students. Here is a list of tools that I have found useful to share my own lectures.
+
+### Create podcasts, videos, or live streams with OBS
+
+[Open Broadcast Studio (OBS)][2] is a professional, open source audio and video recording tool that allows you to record, stream instantly, and do much more. OBS is available for all major platforms (Windows, macOS, and Linux), so interoperability with your colleagues and their various devices is ensured.
+
+Even if you're already using online conferencing software as a recording system, OBS can be a great backup solution. Since it records locally, you're protected against any network lags or disconnections. You also have complete control over your data, so many educational institutions may find it to be a more secure solution than some other options.
+
+Compatibility is also an advantage: OBS stores recordings in a standard intermediate format (MKV), which can be transferred to MP4 or other formats. Also, support for Nvidia graphics cards under OBS is great, as the company is one of the main sponsors of the OBS project. This allows you to make full use of your hardware and speed up the recording process.
+
+### Video and sound editing
+
+After you record your podcast or video, you may find that it needs editing. There are many reasons you may need to edit your audio or video. For example, many university online platforms restrict the size of files you can upload, so you may have to cut long videos. Or, the sound may be too quiet, or maybe it was too noisy when you recorded it, so you need to make adjustments to the audio.
+
+Two of the open source apps to explore are [OpenShot][3] and [Shotcut][4]. Of the two, Shotcut is a more advanced program, which implies a slightly steeper learning curve. Both are cross-platform and have full support for hardware encoding with NVidia and other graphics cards, which will substantially lower processing time compared to CPU-only processing.
+
+You can also extract a soundtrack in either program (although I have found it to be much faster with Shotcut) and export it to an audio-editing program. I find [Audacity][5], another open source, cross-platform (Mac, Linux, Windows) tool, to work extremely well.
+
+My typical workflow looks something like this:
+
+ * Import the recording into Shotcut
+ * Extract the audio, save it to an audio file
+ * Import it into Audacity, normalize and amplify the audio, maybe do some noise reduction
+ * Save the audio to a new file
+ * Import the new audio file into Shotcut, align it with the audio-free video, and cut appropriately
+ * Export into an MP4 video (this last step usually takes some time, so have a coffee…)
+
+
+
+### Electronic blackboards
+
+If you want to annotate your slides or develop ideas on an electronic blackboard, you need note-taking software and a device with a touchscreen or a graphics tablet. A great open source tool (developed with Swiss taxpayer funding) for blackboarding is [OpenBoard][6]. It is cross-platform; although it is officially only available for Linux on Ubuntu 16.04, you can install a [Flatpak][7] and it will work on any Linux flavor. It is really a nice tool; its only shortcoming is that annotating slides is not very good.
+
+My main open source annotation and electric blackboard tool is [Xournal++][8], which is available in some Linux distros repos (e.g., Linux Mint) and otherwise via [Flathub][9]. Like all the tools mentioned earlier, it is also available on Mac and Windows. If you know of any open source, cross-platform note-taking tools, please share them in the comments.
+
+### Built-in solutions have their limits
+
+You might wonder why you should bother with alternative recording software in the first place. After all, most modern operating systems have built-in screen recorders that will also capture audio. However, these built-in solutions have their limits. One key limitation is that you cannot usually capture more than one video source at a time (e.g., a webcam with your talking head and a set of slides plus a whiteboard from a graphics tablet).
+
+The ability to use multiple video sources is very useful, though, since it can be dull for students to just listen to your voice and see your slides for extended periods. Face-to-face interactions—even if done virtually—help keep listeners' attention and make it easier for them to cope with imperfect recording quality and background noise. In addition, many of the built-in tools do not allow you to capture selected areas of the screen, and in general, you cannot change the resolution or the number of frames per second, which can be important for keeping your podcast's memory and bandwidth usage in check.
+
+### Conclusion
+
+When planning your online teaching, you will want to use a blend of audio, video, slides, and electronic blackboards to create an immersive experience even while students are learning remotely. Open source software offers advanced, effective tools for creating such online educational experiences.
+
+* * *
+
+_This article is based on "[Open source software for online teaching in the times of corona][10]" on Mathias Hoffman's blog and is reused with permission._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/open-source-remote-teaching-tools
+
+作者:[Mathias Hoffmann][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/mhopensource
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/read_book_guide_tutorial_teacher_student_apaper.png?itok=_GOufk6N (Person reading a book and digital copy)
+[2]: https://obsproject.com/
+[3]: http://www.openshot.org/
+[4]: http://www.shotcut.org/
+[5]: https://www.audacityteam.org/
+[6]: http://www.openboard.ch/
+[7]: http://www.flathub.org
+[8]: https://github.com/xournalpp/xournalpp
+[9]: https://flathub.org/apps/details/com.github.xournalpp.xournalpp
+[10]: http://mathiashoffmann.net/2020/03/22/open-source-software-for-online-teaching-in-the-times-of-corona
diff --git a/sources/tech/20200415 How to automate your cryptocurrency trades with Python.md b/sources/tech/20200415 How to automate your cryptocurrency trades with Python.md
new file mode 100644
index 0000000000..c216d22663
--- /dev/null
+++ b/sources/tech/20200415 How to automate your cryptocurrency trades with Python.md
@@ -0,0 +1,424 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to automate your cryptocurrency trades with Python)
+[#]: via: (https://opensource.com/article/20/4/python-crypto-trading-bot)
+[#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99)
+
+How to automate your cryptocurrency trades with Python
+======
+In this tutorial, learn how to set up and use Pythonic, a graphical
+programming tool that makes it easy for users to create Python
+applications using ready-made function modules.
+![scientific calculator][1]
+
+Unlike traditional stock exchanges like the New York Stock Exchange that have fixed trading hours, cryptocurrencies are traded 24/7, which makes it impossible for anyone to monitor the market on their own.
+
+Often in the past, I had to deal with the following questions related to my crypto trading:
+
+ * What happened overnight?
+ * Why are there no log entries?
+ * Why was this order placed?
+ * Why was no order placed?
+
+
+
+The usual solution is to use a crypto trading bot that places orders for you when you are doing other things, like sleeping, being with your family, or enjoying your spare time. There are a lot of commercial solutions available, but I wanted an open source option, so I created the crypto-trading bot [Pythonic][2]. As [I wrote][3] in an introductory article last year, "Pythonic is a graphical programming tool that makes it easy for users to create Python applications using ready-made function modules." It originated as a cryptocurrency bot and has an extensive logging engine and well-tested, reusable parts such as schedulers and timers.
+
+### Getting started
+
+This hands-on tutorial teaches you how to get started with Pythonic for automated trading. It uses the example of trading [Tron][4] against [Bitcoin][5] on the [Binance][6] exchange platform. I choose these coins because of their volatility against each other, rather than any personal preference.
+
+The bot will make decisions based on [exponential moving averages][7] (EMAs).
+
+![TRX/BTC 1-hour candle chart][8]
+
+TRX/BTC 1-hour candle chart
+
+The EMA indicator is, in general, a weighted moving average that gives more weight to recent price data. Although a moving average may be a simple indicator, I've had good experiences using it.
+
+The purple line in the chart above shows an EMA-25 indicator (meaning the last 25 values were taken into account).
+
+The bot monitors the pitch between the current EMA-25 value (t0) and the previous EMA-25 value (t-1). If the pitch exceeds a certain value, it signals rising prices, and the bot will place a buy order. If the pitch falls below a certain value, the bot will place a sell order.
+
+The pitch will be the main indicator for making decisions about trading. For this tutorial, it will be called the _trade factor_.
+
+### Toolchain
+
+The following tools are used in this tutorial:
+
+ * Binance expert trading view (visualizing data has been done by many others, so there's no need to reinvent the wheel by doing it yourself)
+ * Jupyter Notebook for data-science tasks
+ * Pythonic, which is the overall framework
+ * PythonicDaemon as the pure runtime (console- and Linux-only)
+
+
+
+### Data mining
+
+For a crypto trading bot to make good decisions, it's essential to get open-high-low-close ([OHLC][9]) data for your asset in a reliable way. You can use Pythonic's built-in elements and extend them with your own logic.
+
+The general workflow is:
+
+ 1. Synchronize with Binance time
+ 2. Download OHLC data
+ 3. Load existing OHLC data from the file into memory
+ 4. Compare both datasets and extend the existing dataset with the newer rows
+
+
+
+This workflow may be a bit overkill, but it makes this solution very robust against downtime and disconnections.
+
+To begin, you need the **Binance OHLC Query** element and a **Basic Operation** element to execute your own code.
+
+![Data-mining workflow][10]
+
+Data-mining workflow
+
+The OHLC query is set up to query the asset pair **TRXBTC** (Tron/Bitcoin) in one-hour intervals.
+
+![Configuration of the OHLC query element][11]
+
+Configuring the OHLC query element
+
+The output of this element is a [Pandas DataFrame][12]. You can access the DataFrame with the **input** variable in the **Basic Operation** element. Here, the **Basic Operation** element is set up to use Vim as the default code editor.
+
+![Basic Operation element set up to use Vim][13]
+
+Basic Operation element set up to use Vim
+
+Here is what the code looks like:
+
+
+```
+import pickle, pathlib, os
+import pandas as pd
+
+outout = None
+
+if isinstance(input, pd.DataFrame):
+ file_name = 'TRXBTC_1h.bin'
+ home_path = str(pathlib.Path.home())
+ data_path = os.path.join(home_path, file_name)
+
+ try:
+ df = pickle.load(open(data_path, 'rb'))
+ n_row_cnt = df.shape[0]
+ df = pd.concat([df,input], ignore_index=True).drop_duplicates(['close_time'])
+ df.reset_index(drop=True, inplace=True)
+ n_new_rows = df.shape[0] - n_row_cnt
+ log_txt = '{}: {} new rows written'.format(file_name, n_new_rows)
+ except:
+ log_txt = 'File error - writing new one: {}'.format(e)
+ df = input
+
+ pickle.dump(df, open(data_path, "wb" ))
+ output = df
+```
+
+First, check whether the input is the DataFrame type. Then look inside the user's home directory (**~/**) for a file named **TRXBTC_1h.bin**. If it is present, then open it, concatenate new rows (the code in the **try** section), and drop overlapping duplicates. If the file doesn't exist, trigger an _exception_ and execute the code in the **except** section, creating a new file.
+
+As long as the checkbox **log output** is enabled, you can follow the logging with the command-line tool **tail**:
+
+
+```
+`$ tail -f ~/Pythonic_2020/Feb/log_2020_02_19.txt`
+```
+
+For development purposes, skip the synchronization with Binance time and regular scheduling for now. This will be implemented below.
+
+### Data preparation
+
+The next step is to handle the evaluation logic in a separate grid; therefore, you have to pass over the DataFrame from Grid 1 to the first element of Grid 2 with the help of the **Return element**.
+
+In Grid 2, extend the DataFrame by a column that contains the EMA values by passing the DataFrame through a **Basic Technical Analysis** element.
+
+![Technical analysis workflow in Grid 2][14]
+
+Technical analysis workflow in Grid 2
+
+Configure the technical analysis element to calculate the EMAs over a period of 25 values.
+
+![Configuration of the technical analysis element][15]
+
+Configuring the technical analysis element
+
+When you run the whole setup and activate the debug output of the **Technical Analysis** element, you will realize that the values of the EMA-25 column all seem to be the same.
+
+![Missing decimal places in output][16]
+
+Decimal places are missing in the output
+
+This is because the EMA-25 values in the debug output include just six decimal places, even though the output retains the full precision of an 8-byte float value.
+
+For further processing, add a **Basic Operation** element:
+
+![Workflow in Grid 2][17]
+
+Workflow in Grid 2
+
+With the **Basic Operation** element, dump the DataFrame with the additional EMA-25 column so that it can be loaded into a Jupyter Notebook;
+
+![Dump extended DataFrame to file][18]
+
+Dump extended DataFrame to file
+
+### Evaluation logic
+
+Developing the evaluation logic inside Juypter Notebook enables you to access the code in a more direct way. To load the DataFrame, you need the following lines:
+
+![Representation with all decimal places][19]
+
+Representation with all decimal places
+
+You can access the latest EMA-25 values by using [**iloc**][20] and the column name. This keeps all of the decimal places.
+
+You already know how to get the latest value. The last line of the example above shows only the value. To copy the value to a separate variable, you have to access it with the **.at** method, as shown below.
+
+You can also directly calculate the trade factor, which you will need in the next step.
+
+![Buy/sell decision][21]
+
+Buy/sell decision
+
+### Determine the trading factor
+
+As you can see in the code above, I chose 0.009 as the trade factor. But how do I know if 0.009 is a good trading factor for decisions? Actually, this factor is really bad, so instead, you can brute-force the best-performing trade factor.
+
+Assume that you will buy or sell based on the closing price.
+
+![Validation function][22]
+
+Validation function
+
+In this example, **buy_factor** and **sell_factor** are predefined. So extend the logic to brute-force the best performing values.
+
+![Nested for loops for determining the buy and sell factor][23]
+
+Nested _for_ loops for determining the buy and sell factor
+
+This has 81 loops to process (9x9), which takes a couple of minutes on my machine (a Core i7 267QM).
+
+![System utilization while brute forcing][24]
+
+System utilization while brute-forcing
+
+After each loop, it appends a tuple of **buy_factor**, **sell_factor**, and the resulting **profit** to the **trading_factors** list. Sort the list by profit in descending order.
+
+![Sort profit with related trading factors in descending order][25]
+
+Sort profit with related trading factors in descending order
+
+When you print the list, you can see that 0.002 is the most promising factor.
+
+![Sorted list of trading factors and profit][26]
+
+Sorted list of trading factors and profit
+
+When I wrote this in March 2020, the prices were not volatile enough to present more promising results. I got much better results in February, but even then, the best-performing trading factors were also around 0.002.
+
+### Split the execution path
+
+Start a new grid now to maintain clarity. Pass the DataFrame with the EMA-25 column from Grid 2 to element 0A of Grid 3 by using a **Return** element.
+
+In Grid 3, add a **Basic Operation** element to execute the evaluation logic. Here is the code of that element:
+
+![Implemented evaluation logic][27]
+
+Implemented evaluation logic
+
+The element outputs a **1** if you should buy or a **-1** if you should sell. An output of **0** means there's nothing to do right now. Use a **Branch** element to control the execution path.
+
+![Branch element: Grid 3 Position 2A][28]
+
+Branch element: Grid 3, Position 2A
+
+Due to the fact that both **0** and **-1** are processed the same way, you need an additional Branch element on the right-most execution path to decide whether or not you should sell.
+
+![Branch element: Grid 3 Position 3B][29]
+
+Branch element: Grid 3, Position 3B
+
+Grid 3 should now look like this:
+
+![Workflow on Grid 3][30]
+
+Workflow on Grid 3
+
+### Execute orders
+
+Since you cannot buy twice, you must keep a persistent variable between the cycles that indicates whether you have already bought.
+
+You can do this with a **Stack element**. The Stack element is, as the name suggests, a representation of a file-based stack that can be filled with any Python data type.
+
+You need to define that the stack contains only one Boolean element, which determines if you bought (**True**) or not (**False**). As a consequence, you have to preset the stack with one **False**. You can set this up, for example, in Grid 4 by simply passing a **False** to the stack.
+
+![Forward a False-variable to the subsequent Stack element][31]
+
+Forward a **False** variable to the subsequent Stack element
+
+The Stack instances after the branch tree can be configured as follows:
+
+![Configuration of the Stack element][32]
+
+Configuring the Stack element
+
+In the Stack element configuration, set **Do this with input** to **Nothing**. Otherwise, the Boolean value will be overwritten by a 1 or 0.
+
+This configuration ensures that only one value is ever saved in the stack (**True** or **False**), and only one value can ever be read (for clarity).
+
+Right after the Stack element, you need an additional **Branch** element to evaluate the stack value before you place the **Binance Order** elements.
+
+![Evaluate the variable from the stack][33]
+
+Evaluating the variable from the stack
+
+Append the Binance Order element to the **True** path of the Branch element. The workflow on Grid 3 should now look like this:
+
+![Workflow on Grid 3][34]
+
+Workflow on Grid 3
+
+The Binance Order element is configured as follows:
+
+![Configuration of the Binance Order element][35]
+
+Configuring the Binance Order element
+
+You can generate the API and Secret keys on the Binance website under your account settings.
+
+![Creating an API key in Binance][36]
+
+Creating an API key in the Binance account settings
+
+In this tutorial, every trade is executed as a market trade and has a volume of 10,000 TRX (~US$ 150 on March 2020). (For the purposes of this tutorial, I am demonstrating the overall process by using a Market Order. Because of that, I recommend using at least a Limit order.)
+
+The subsequent element is not triggered if the order was not executed properly (e.g., a connection issue, insufficient funds, or incorrect currency pair). Therefore, you can assume that if the subsequent element is triggered, the order was placed.
+
+Here is an example of output from a successful sell order for XMRBTC:
+
+![Output of a successfully placed sell order][37]
+
+Successful sell order output
+
+This behavior makes subsequent steps more comfortable: You can always assume that as long the output is proper, the order was placed. Therefore, you can append a **Basic Operation** element that simply writes the output to **True** and writes this value on the stack to indicate whether the order was placed or not.
+
+If something went wrong, you can find the details in the logging message (if logging is enabled).
+
+![Logging output of Binance Order element][38]
+
+Logging output from Binance Order element
+
+### Schedule and sync
+
+For regular scheduling and synchronization, prepend the entire workflow in Grid 1 with the **Binance Scheduler** element.
+
+![Binance Scheduler at Grid 1, Position 1A][39]
+
+Binance Scheduler at Grid 1, Position 1A
+
+The Binance Scheduler element executes only once, so split the execution path on the end of Grid 1 and force it to re-synchronize itself by passing the output back to the Binance Scheduler element.
+
+![Grid 1: Split execution path][40]
+
+Grid 1: Split execution path
+
+Element 5A points to Element 1A of Grid 2, and Element 5B points to Element 1A of Grid 1 (Binance Scheduler).
+
+### Deploy
+
+You can run the whole setup 24/7 on your local machine, or you could host it entirely on an inexpensive cloud system. For example, you can use a Linux/FreeBSD cloud system for about US$5 per month, but they usually don't provide a window system. If you want to take advantage of these low-cost clouds, you can use PythonicDaemon, which runs completely inside the terminal.
+
+![PythonicDaemon console interface][41]
+
+PythonicDaemon console
+
+PythonicDaemon is part of the basic installation. To use it, save your complete workflow, transfer it to the remote running system (e.g., by Secure Copy [SCP]), and start PythonicDaemon with the workflow file as an argument:
+
+
+```
+`$ PythonicDaemon trading_bot_one`
+```
+
+To automatically start PythonicDaemon at system startup, you can add an entry to the crontab:
+
+
+```
+`# crontab -e`
+```
+
+![Crontab on Ubuntu Server][42]
+
+Crontab on Ubuntu Server
+
+### Next steps
+
+As I wrote at the beginning, this tutorial is just a starting point into automated trading. Programming trading bots is approximately 10% programming and 90% testing. When it comes to letting your bot trade with your money, you will definitely think thrice about the code you program. So I advise you to keep your code as simple and easy to understand as you can.
+
+If you want to continue developing your trading bot on your own, the next things to set up are:
+
+ * Automatic profit calculation (hopefully only positive!)
+ * Calculation of the prices you want to buy for
+ * Comparison with your order book (i.e., was the order filled completely?)
+
+
+
+You can download the whole example on [GitHub][2].
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/python-crypto-trading-bot
+
+作者:[Stephan Avenwedde][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/hansic99
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/calculator_money_currency_financial_tool.jpg?itok=2QMa1y8c (scientific calculator)
+[2]: https://github.com/hANSIc99/Pythonic
+[3]: https://opensource.com/article/19/5/graphically-programming-pythonic
+[4]: https://tron.network/
+[5]: https://bitcoin.org/en/
+[6]: https://www.binance.com/
+[7]: https://www.investopedia.com/terms/e/ema.asp
+[8]: https://opensource.com/sites/default/files/uploads/1_ema-25.png (TRX/BTC 1-hour candle chart)
+[9]: https://en.wikipedia.org/wiki/Open-high-low-close_chart
+[10]: https://opensource.com/sites/default/files/uploads/2_data-mining-workflow.png (Data-mining workflow)
+[11]: https://opensource.com/sites/default/files/uploads/3_ohlc-query.png (Configuration of the OHLC query element)
+[12]: https://pandas.pydata.org/pandas-docs/stable/getting_started/dsintro.html#dataframe
+[13]: https://opensource.com/sites/default/files/uploads/4_edit-basic-operation.png (Basic Operation element set up to use Vim)
+[14]: https://opensource.com/sites/default/files/uploads/6_grid2-workflow.png (Technical analysis workflow in Grid 2)
+[15]: https://opensource.com/sites/default/files/uploads/7_technical-analysis-config.png (Configuration of the technical analysis element)
+[16]: https://opensource.com/sites/default/files/uploads/8_missing-decimals.png (Missing decimal places in output)
+[17]: https://opensource.com/sites/default/files/uploads/9_basic-operation-element.png (Workflow in Grid 2)
+[18]: https://opensource.com/sites/default/files/uploads/10_dump-extended-dataframe.png (Dump extended DataFrame to file)
+[19]: https://opensource.com/sites/default/files/uploads/11_load-dataframe-decimals.png (Representation with all decimal places)
+[20]: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html
+[21]: https://opensource.com/sites/default/files/uploads/12_trade-factor-decision.png (Buy/sell decision)
+[22]: https://opensource.com/sites/default/files/uploads/13_validation-function.png (Validation function)
+[23]: https://opensource.com/sites/default/files/uploads/14_brute-force-tf.png (Nested for loops for determining the buy and sell factor)
+[24]: https://opensource.com/sites/default/files/uploads/15_system-utilization.png (System utilization while brute forcing)
+[25]: https://opensource.com/sites/default/files/uploads/16_sort-profit.png (Sort profit with related trading factors in descending order)
+[26]: https://opensource.com/sites/default/files/uploads/17_sorted-trading-factors.png (Sorted list of trading factors and profit)
+[27]: https://opensource.com/sites/default/files/uploads/18_implemented-evaluation-logic.png (Implemented evaluation logic)
+[28]: https://opensource.com/sites/default/files/uploads/19_output.png (Branch element: Grid 3 Position 2A)
+[29]: https://opensource.com/sites/default/files/uploads/20_editbranch.png (Branch element: Grid 3 Position 3B)
+[30]: https://opensource.com/sites/default/files/uploads/21_grid3-workflow.png (Workflow on Grid 3)
+[31]: https://opensource.com/sites/default/files/uploads/22_pass-false-to-stack.png (Forward a False-variable to the subsequent Stack element)
+[32]: https://opensource.com/sites/default/files/uploads/23_stack-config.png (Configuration of the Stack element)
+[33]: https://opensource.com/sites/default/files/uploads/24_evaluate-stack-value.png (Evaluate the variable from the stack)
+[34]: https://opensource.com/sites/default/files/uploads/25_grid3-workflow.png (Workflow on Grid 3)
+[35]: https://opensource.com/sites/default/files/uploads/26_binance-order.png (Configuration of the Binance Order element)
+[36]: https://opensource.com/sites/default/files/uploads/27_api-key-binance.png (Creating an API key in Binance)
+[37]: https://opensource.com/sites/default/files/uploads/28_sell-order.png (Output of a successfully placed sell order)
+[38]: https://opensource.com/sites/default/files/uploads/29_binance-order-output.png (Logging output of Binance Order element)
+[39]: https://opensource.com/sites/default/files/uploads/30_binance-scheduler.png (Binance Scheduler at Grid 1, Position 1A)
+[40]: https://opensource.com/sites/default/files/uploads/31_split-execution-path.png (Grid 1: Split execution path)
+[41]: https://opensource.com/sites/default/files/uploads/32_pythonic-daemon.png (PythonicDaemon console interface)
+[42]: https://opensource.com/sites/default/files/uploads/33_crontab.png (Crontab on Ubuntu Server)
diff --git a/sources/tech/20200415 Tweaking history on Linux.md b/sources/tech/20200415 Tweaking history on Linux.md
new file mode 100644
index 0000000000..b17a666a8a
--- /dev/null
+++ b/sources/tech/20200415 Tweaking history on Linux.md
@@ -0,0 +1,189 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Tweaking history on Linux)
+[#]: via: (https://www.networkworld.com/article/3537214/tweaking-history-on-linux.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+Tweaking history on Linux
+======
+The bash shell's history command in Linux makes it easy to review and reuse commands, but there's a lot you do to control how much it remembers and how much forgets.
+[Claudio Testa][1] [(CC0)][2]
+
+The bash **history** command on Linux systems helps with remembering commands you’ve previously run and repeating those commands without having to retype them.
+
+You could decide, however, that you’d be just as happy to forget that you referenced a dozen man pages, listed your files every 10 minutes or viewed previously run commands by typing “history”. In this post, we’re going to look at how you can get the history command to remember just what you want it to remember and forget commands that are likely to be of little "historic value".
+
+### Viewing your command history
+
+To view previously run commands, you simply type “history”. You’ll probably see a long list of commands. The number of commands remembered depends on an environment variable called **$HISTSIZE** that is set up in your **~/.bashrc** file, but there’s nothing stopping you from changing this setting if you want to save more or fewer commands.
+
+To view history, use the **history** command:
+
+```
+$ history
+209 uname -v
+210 date
+211 man chage
+...
+```
+
+To see the maximum number of commands that will be displayed:
+
+```
+$ echo $HISTSIZE
+500
+```
+
+You can change **$HISTSIZE** and make the change permanent by running commands like these:
+
+```
+$ export HISTSIZE=1000
+$ echo “HISTSIZE=1000” >> ~/.bashrc
+```
+
+There’s also a difference between how much history is preserved for you and how much is displayed when you type “history”. The **$HISTSIZE** variable controls how much history is displayed while the **$HISTFILESIZE** variable controls how many commands are retained in your **.bash_history** file.
+
+[][3]
+
+```
+$ echo $HISTSIZE
+1000
+$ echo $HISTFILESIZE
+2000
+```
+
+You can verify the second variable by counting the lines in your history file:
+
+```
+$ wc -l .bash_history
+2000 .bash_history
+```
+
+One thing to keep in mind is that commands that you enter during a login session aren’t added to your **.bash_history** file until you log off, even though they show up in the **history** command output right away.
+
+### Using history
+
+There are three ways to reissue commands that you find in your history. The simplest way, especially if the command you want to reuse was run recently, is often to type a ! followed by enough of the first letters in the command's name to uniquely identify it.
+
+```
+$ !u
+uname -v
+#37-Ubuntu SMP Thu Mar 26 20:41:27 UTC 2020
+```
+
+Another easy way to repeat a command is to simply press your up-arrow key until the command is displayed and then press enter.
+
+Alternately, if you run the history command and see the command you want to rerun listed, you can type an ! followed by the sequence number shown to the left of the command.
+
+```
+$ !209
+uname -v
+#37-Ubuntu SMP Thu Mar 26 20:41:27 UTC 2020
+```
+
+### Hiding history
+
+If you want to stop recording commands for some period of time, you can use this command:
+
+```
+$ set +o history
+```
+
+Commands will not show up when you type "history" nor will they be added to your **.bash_history** file when you exit the session by logging off or exiting the terminal.
+
+To reverse this setting, use **set -o history**. To make it permanent, you can add it to your **.bashrc** file, though failing to make use of command history altogether is generally not a good idea.
+
+```
+$ echo 'set +o history' >> ~/.bashrc
+```
+
+To temporarily clear history, so that only commands that you enter afterwards show up when you type "history", use the **history -c** (clear) command:
+
+```
+$ history | tail -3
+209 uname -v
+210 date
+211 man chage
+$ history -c
+$ history
+1 history
+```
+
+NOTE: The commands entered after typing "history -c" will not be added to your .bash_history file.
+
+### Controlling history
+
+The command history settings on many systems will default to including one called **$HISTCONTROL** that ensures that, even if you run the same command seven times in a row, it will only be remembered once. It also ensures that commands that you type after first entering one or more blanks will be omitted from your command history.
+
+```
+$ grep HISTCONTROL .bashrc
+HISTCONTROL=ignoreboth
+```
+
+The "ignoreboth" means "ignore both duplicate commands and command starting with blanks". For example, if you type these commands:
+
+```
+$ echo try this
+$ date
+$ date
+$ date
+$ pwd
+$ history
+```
+
+your history command should report something like this:
+
+```
+$ history
+$ echo try this
+$ date
+$ history
+```
+
+Notice that the sequential date commands were reduced to one and the indented command was omitted.
+
+### Overlooking history
+
+To ignore certain commands so that they never show up when you type "history" and are never added to your **.bash_history** file, use the **$HISTIGNORE** setting. For example:
+
+```
+$ export HISTIGNORE=”history:cd:exit:ls:pwd:man”
+```
+
+This setting will cause all **history**, **cd**, **exit**, **ls**, **pwd** and **man** commands to be omitted from your **history** output and your **.bash_history** file.
+
+If you want to make this setting permanent, you have to add it to your **.bashrc** file.
+
+```
+$ echo 'HISTIGNORE="history:cd:exit:ls:pwd:man"' >> .bashrc
+```
+
+This setting just means that when you look back through previously run commands, the list won’t be cluttered by commands that you're unlikely to be looking for when you are looking through your command history.
+
+### Remembering, ignoring and forgetting the past
+
+Command history is useful because it helps you remember what commands you’ve recently used and reminds you about changes you’ve recently made. It also makes it easier to rerun commands, especially those with a string of arguments that you don't necessarily want to recreate. Tailoring your history settings can make your use of command history a little easier and more efficient.
+
+Join the Network World communities on [Facebook][4] and [LinkedIn][5] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3537214/tweaking-history-on-linux.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://unsplash.com/photos/iqeG5xA96M4
+[2]: https://creativecommons.org/publicdomain/zero/1.0/
+[3]: https://www.networkworld.com/blog/itaas-and-the-corporate-storage-technology/?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE22140&utm_content=sidebar (ITAAS and Corporate Storage Strategy)
+[4]: https://www.facebook.com/NetworkWorld/
+[5]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200415 Writing Java with Quarkus in VS Code.md b/sources/tech/20200415 Writing Java with Quarkus in VS Code.md
new file mode 100644
index 0000000000..2d61db71de
--- /dev/null
+++ b/sources/tech/20200415 Writing Java with Quarkus in VS Code.md
@@ -0,0 +1,239 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Writing Java with Quarkus in VS Code)
+[#]: via: (https://opensource.com/article/20/4/java-quarkus-vs-code)
+[#]: author: (Daniel Oh https://opensource.com/users/daniel-oh)
+
+Writing Java with Quarkus in VS Code
+======
+In this tutorial, I'll walk you through how to rebuild, package, and
+deploy cloud-native applications automatically with Quarkus.
+![Person drinking a hat drink at the computer][1]
+
+In the previous articles in this series about cloud-native [Java][2] applications, I shared [_6 requirements of cloud-native software_][3] and [_4 things cloud-native Java must provide_][4]. But now you might want to implement these advanced Java applications in your local machine without climbing a steep learning curve. In this article, I will walk through using the open source technologies [Quarkus][5] and [Visual Studio Code][6] (VS Code) to accelerate the development of both traditional cloud-native Java stacks and also serverless, reactive applications with easier and more familiar methods.
+
+Quarkus is a Kubernetes-native Java stack tailored for GraalVM and OpenJDK HotSpot. It's crafted from best-of-breed Java libraries and standards with live coding, unified configuration, superfast startup, small memory footprint, and unified imperative and reactive development. VS Code is an open source integrated development environment (IDE) for editing code.
+
+### Generate a Quarkus project
+
+Begin by navigating to Quarkus' [Start coding][7] page to generate a Quarkus project that includes a RESTful endpoint. Leave all variables (i.e., Group, Artifact, Build Tool, Extensions) on the default settings, then click **Generate your application** at the top-right of the page. Note that the RESTEasy JAX-RS extension is preselected as default.
+
+![Quarkus Generate application button][8]
+
+The ZIP file will automatically download on your local machine. Extract the file with the following command:
+
+
+```
+$ unzip code-with-quarkus.zip
+Archive: code-with-quarkus.zip
+ creating: code-with-quarkus/
+ inflating: code-with-quarkus/pom.xml
+ ...
+```
+
+### Install VS Code
+
+Download and install VS Code in your preferred way, whether that's [from the website][9] or through your package manager (dnf, apt, brew, etc). Once that's done, open the unzipped Quarkus project using VS Code's command-line tool:
+
+
+```
+$ cd code-with-quarkus/
+$ code .
+```
+
+You will see the [Apache Maven][10] project structure with:
+
+ * **ExampleResource** exposed on **/hello**
+ * Associated JUnit test
+ * Accessible landing page via
+ * Dockerfiles for both [native compilation][11] and JVM HotSpot
+ * A unified application configuration file
+
+
+
+Add Quarkus tools to your IDE through the VS Code's extension feature.
+
+![Add Quarkus tools to VS Code IDE][12]
+
+### Start coding
+
+Run the application using Quarkus development mode. To run the application, you need:
+
+ * JDK 1.8+ installed with JAVA_HOME configured appropriately
+ * Apache Maven 3.6.3+
+
+
+
+Move to the **code-with-quarkus** directory then type **mvn compile quarkus:dev** in VS Code's terminal.
+
+![Run application][13]
+
+You will see that the Java application is running well with:
+
+ * About one second to startup
+ * Live coding activated
+ * EnabledCDI and RESTEASY features
+
+
+
+When you access the endpoint via a web browser, you will see the return code, **hello**.
+
+!["Hello" return][14]
+
+Now, you're ready to change the code! Move back to VS Code, then open the **ExampleResource.java** file in **src/main/java/org/acme**. Replace the return code with "**Welcome, Cloud-Native Java with Quarkus!"** Don't forget to **Save** the file.
+
+![Editing the return][15]
+
+Go back to the web browser and reload the page.
+
+![New return][16]
+
+_It's like magic!_ Behind the scenes, Quarkus rebuilt, packaged, and deployed the application for you automatically, and it only took half a second. This is one of the essential cloud-native Java runtime features for increasing development productivity.
+
+![Quarkus output][17]
+
+Continue running your cloud-native Java application in Quarkus.
+
+### Integrate data transactions via Quakrus Tool
+
+To add an in-memory database (H2) transaction capability, press **F1** then click on **Quarkus: Add extensions to the current project**.
+
+![Adding extensions in Quarkus][18]
+
+Enter **h2** in the search bar, then double-click on **JDBC Driver - H2 Data** in the result.
+
+![JDBC Driver - H2 Data extension][19]
+
+Select the following three extensions, which will simplify your persistence code and return JSON format data:
+
+ * Hibernate ORM with Panache Data
+ * JDBC Driver - H2
+ * RESTEasy JSON-B Web
+
+
+
+Press **Enter** to add those dependencies.
+
+![Add Quarkus extensions][20]
+
+You should see the following in a new VS Code terminal:
+
+![VS Code adding extensions][21]
+
+You should also find the following pulled dependencies in **POM.xml**:
+
+![dependencies in POM.xml][22]
+
+### Create an Inventory entity
+
+With your project in place, you can get to work defining the business logic.
+
+The first step is to define the model (entity) of an Inventory object. Since Quarkus uses Hibernate ORM Panache, create an **Inventory.java** file in the **src.main.java.org.acme** directory, and paste the following code into it:
+
+
+```
+package org.acme;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+
+import io.quarkus.hibernate.orm.panache.PanacheEntity;
+
+@[Entity][23]
+@Cacheable
+public class Inventory extends PanacheEntity {
+
+ public [String][24] itemId;
+ public [String][24] location;
+ public int quantity;
+ public [String][24] link
+
+ public Inventory() {
+
+ }
+
+}
+```
+
+#### Define the RESTful endpoint of Inventory
+
+Next, mirror the abstraction of service so that you can inject the Inventory service into various places (like a RESTful resource endpoint) in the future. Create an **InventoryResource.java** file in the **src.main.java.org.acme** directory and add this code to it:
+
+
+```
+package org.acme;
+
+import java.util.List;
+import javax.enterprise.context.ApplicationScoped;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+@Path("/services/inventory")
+@ApplicationScoped
+@Produces("application/json")
+@Consumes("application/json")
+public class InventoryResource {
+
+ @GET
+
+ public List<Inventory> getAll() {
+ return Inventory.listAll();
+ }
+}
+```
+
+Don't forget to save these files. Go back to your web browser and access a new endpoint, . You will see:
+
+![Inventory endpoint][25]
+
+### Wrapping up
+
+If you have an issue or get an error when you implement this, you can find and reuse the [code in my GitHub repository][26].
+
+If you want to learn more, Quarkus has some [practical and useful guides][27] that show how to develop advanced cloud-native Java applications using Quarkus extensions with event-driven programming, serverless development, and Kubernetes deployment.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/java-quarkus-vs-code
+
+作者:[Daniel Oh][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/daniel-oh
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coffee_tea_laptop_computer_work_desk.png?itok=D5yMx_Dr (Person drinking a hat drink at the computer)
+[2]: https://opensource.com/resources/java
+[3]: https://opensource.com/article/20/1/cloud-native-software
+[4]: https://opensource.com/article/20/1/cloud-native-java
+[5]: https://quarkus.io/
+[6]: https://code.visualstudio.com/
+[7]: https://code.quarkus.io/
+[8]: https://opensource.com/sites/default/files/uploads/quarkus_generateapplication.png (Quarkus Generate application button)
+[9]: https://code.visualstudio.com/download
+[10]: https://maven.apache.org/
+[11]: https://quarkus.io/guides/building-native-image
+[12]: https://opensource.com/sites/default/files/uploads/add-quarkus-to-ide.png (Add Quarkus tools to VS Code IDE)
+[13]: https://opensource.com/sites/default/files/uploads/run-application.png (Run application)
+[14]: https://opensource.com/sites/default/files/uploads/endpoint-hello.png ("Hello" return)
+[15]: https://opensource.com/sites/default/files/uploads/edit-return-code.png (Editing the return)
+[16]: https://opensource.com/sites/default/files/uploads/new-return-code.png (New return)
+[17]: https://opensource.com/sites/default/files/uploads/quarkus-magic.png (Quarkus output)
+[18]: https://opensource.com/sites/default/files/uploads/quarkus-add-extensions.png (Adding extensions in Quarkus)
+[19]: https://opensource.com/sites/default/files/uploads/jbdc-driver-h2-data.png (JDBC Driver - H2 Data extension)
+[20]: https://opensource.com/sites/default/files/uploads/add-extensions.png (Add Quarkus extensions)
+[21]: https://opensource.com/sites/default/files/uploads/vscode-adding-extensions.png (VS Code adding extensions)
+[22]: https://opensource.com/sites/default/files/uploads/dependencies-pomxml.png (dependencies in POM.xml)
+[23]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+entity
+[24]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
+[25]: https://opensource.com/sites/default/files/uploads/inventory-endpoint.png (Inventory endpoint)
+[26]: https://github.com/danieloh30/code-with-quarkus
+[27]: https://quarkus.io/guides/
diff --git a/sources/tech/20200417 How to set up and run WordPress for your classroom.md b/sources/tech/20200417 How to set up and run WordPress for your classroom.md
new file mode 100644
index 0000000000..bb8b87d560
--- /dev/null
+++ b/sources/tech/20200417 How to set up and run WordPress for your classroom.md
@@ -0,0 +1,164 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to set up and run WordPress for your classroom)
+[#]: via: (https://opensource.com/article/20/4/wordpress-virtual-machine)
+[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
+
+How to set up and run WordPress for your classroom
+======
+Follow these simple steps to customize WordPress for use in the
+classroom using free open source software.
+![Painting art on a computer screen][1]
+
+There are many good reasons to set up WordPress for your classroom. As more schools switch to online classes, WordPress can become the go-to content management system. Teachers using WordPress can provide a number of different educational choices to differentiate instruction for their students. Blogging is an accessible way to create content that energizes student learning. Teachers can write short stories, poems, and provide picture galleries that function as story starters. Students can comment and those comments can be moderated by their teacher.
+
+There are free options like [WordPress.com][2] and [Edublogs][3]. However, these free versions are limited, and you may want to explore all your options. You can install [Virtualbox][4] on any Windows, macOS, or Linux computer. You can use your own computer or an extra you happen to have access to in a virtual environment.
+
+On Linux, you can install Virtualbox from your package manager. For instance, on Debian, Elementary OS, or Ubuntu:
+
+
+```
+`$ sudo apt install virtualbox`
+```
+
+On Fedora:
+
+
+```
+`$ sudo dnf install virtualbox`
+```
+
+### Download a Wordpress image
+
+Wordpress is easy to install, but server configuration and management can be difficult for the uninitiated. That's why there's [Turnkey Linux][5], a project dedicated to creating virtual machine images and containers of popular server software, preconfigured and ready to run. With Turnkey Linux, you just download a disk image containing the operating system and the software you want to run, and then import that image into Virtualbox.
+
+To get started with Wordpress, download the **VM** virtual machine image from [turnkeylinux.org/wordpress][6] (in the **Builds** section). Make sure you download the image labeled **VM**, because that's the only format meant for Virtualbox.
+
+### Import the image into Virtualbox
+
+After installing Virtualbox, launch the application and import the virtual machine image into Virtualbox.
+
+![][7]
+
+Networking on the imported image is set to NAT by default. You will want to change the network settings to "bridged."
+
+![Virtualbox menu][8]
+
+After restarting the virtual machine, you are prompted to add passwords for MySQL, Adminer, and the WordPress **admin** user.
+
+Then you see the network configuration console for the installation. Launch a web browser and navigate to the **web** address provided (in this example, it's 192.168.86.149).
+
+![Console][9]
+
+In a web browser, you see a login screen for your Wordpress installation. Click on the **Login** link.
+
+![Wordpress welcome][10]
+
+Enter **admin** as the username, followed by the password you created earlier. Click the **Login** link. On this first login as **admin**, you can choose a new password. Be sure to remember it!
+
+![Login screen][11]
+
+After logging in, you're presented with the WordPress Dashboard. The software will likely notify you, in the upper left corner of the window, that a new version of Wordpress exists. Update to the latest versions as prompted so your site is secure.
+
+It's important to note that your Wordpress blog isn't visible by anyone on the Internet yet. It only exists in your local network: only people in your building who are connected to the same router or wifi access point as you can see your Wordpress site right now. The worldwide Internet can't get to it because you're behind a firewall (embedded in your router, and possible also in your computer).
+
+![Wordpress dashboard][12]
+
+Following the upgrade, the application restarts, and you're ready to begin configuring WordPress to your liking.
+
+![Wordpress configuration][13]
+
+On the far left, there is a button to **Customize Your Site**.
+
+There, you can choose the name of your site. You can accept the default theme, which is "Twenty Nineteen," or choose another. My favorite is "Twenty Ten," but browse through the themes available to find your personal favorite. WordPress comes with five free themes installed. You can download other free themes from the [WordPress][14][.org][15] site or choose to purchase a premium theme.
+
+When you click the **Customize Your Site** button, you're presented with new menu options. Select **Site Identity** and change the name of your site. You might use the name of your school or classroom. There's also room to choose a byline (the credit given to the author of a blog post). You can choose the colors for your site and where you will place menus and widgets. WordPress widgets and content and features to the sidebars for your site. Homepage settings are important, as they allow you to choose between a static page that might have a description of your school or classroom or having your blog entries displayed prominently. You can add additional CSS.
+
+![Turnkey theme][16]
+
+You can edit your front page, add additional pages like "About," or add a blog post. You can also manage widgets, manage menus, turn comments on or off, or add a link to learn more about WordPress.
+
+Customizing your site allows you to configure a number of options quickly and easily.
+
+WordPress has dozens of widgets that you can place in different areas of your page. Widgets are independent sections of content that can be placed into specific areas provided by your theme. These areas are called sidebars.
+
+### Adding content
+
+After you have WordPress configured to your liking, you probably want to get busy creating content. The best way to do that is to head back to the WordPress Dashboard.
+
+On the left side, near the top of the page, you see **Posts**. Select that link and a dropdown appears. Choose **Add New** to create your very first blog post.
+
+![Add post dropdown][17]
+
+Fill in your title in the top block and then move down to the body. It's like using a word processor. WordPress has all the tools you need to write. You can set the font size from _small_ to _huge_. You can start a paragraph with dropped capitals. The text and background color can be changed. Your posts can include quote blocks and embedded content. A wide variety of embedded content is supported so you can make your posts a dynamic multimedia experience.
+
+![Wordpress classroom blog][18]
+
+### Going online
+
+So far, your Wordpress blog only exists on your local network. Anyone using the same router as you (your housemates or classroom) can see your Wordpress site by navigating to 192.168.86.149, but once you're away from that router, the site becomes inaccessible.
+
+If you want to go online with your custom Wordpress site, you have to allow traffic through your router, and then direct that traffic to the computer running Virtualbox. If you've installed Virtualbox on a laptop, then your website would disappear any time you closed your laptop, which is why servers that never get shutdown exist. But if this is just a fun lesson on how to run a Wordpress site, then having a website that's only available during class hours is fine.
+
+If you have access to your router, then you can log into it and make the adjustments yourself. If you don't own or control your router, then you must talk to your systems administrator for access.
+
+A _router_ is the box you got from your internet service provider. You might also call it your _modem_.
+
+Every device is different, so there's no way for me to definitively tell you what you need to click on to adjust your settings. Generally, you access your home router through a web browser. Your router's address is often printed on the bottom of the router and begins with either 192.168 or 10.
+
+Navigate to the router address and log in with the credentials you were provided when you got your internet service. It's often as simple as `admin` with a numeric password (sometimes this password is printed on the router, too). If you don't know the login, call your internet provider and ask for details.
+
+Different routers use different terms for the same thing; keywords to look for are **Port forwarding**, **Virtual server**, and **Firewall**. Whatever your router calls it, you want to accept traffic coming to port 80 of your router and forward that traffic to the same port of your virtual machines's IP address (in this example, that is 192.168.86.149, but it could be different for you).
+
+![Example router setting screen][19]
+
+Now you're allowing traffic through the web port of your router's firewall. To view your Wordpress site over the Internet, get your worldwide IP address. You can get your global IP by going to the site [icanhazip.com][20]. Then go to a different computer, open a browser, and navigate to that IP address. As long as Virtualbox is running, you'll see your Wordpress site on the Internet. You can do this from anywhere in the world, because your site is on the Internet now.
+
+Most websites use a domain name so you don't have to remember global IP addresses. You can purchase a domain name from services like [webhosting.coop][21] or [gandi.net][22], or a temporary one from [freenom.com][23]. Mapping that to your Wordpress site, however, is out of scope for this article.
+
+### Wordpress for everyone
+
+[WordPress][24] is open source and is licensed under the [GNU Public License][25]. You are welcome to contribute to WordPress as either a [developer][26] or enthusiast. WordPress is committed to being inclusive and accessible as possible.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/wordpress-virtual-machine
+
+作者:[Don Watkins][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/don-watkins
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/painting_computer_screen_art_design_creative.png?itok=LVAeQx3_ (Painting art on a computer screen)
+[2]: https://wordpress.com/
+[3]: https://edublogs.org/
+[4]: https://www.virtualbox.org/
+[5]: https://www.turnkeylinux.org
+[6]: https://www.turnkeylinux.org/wordpress
+[7]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_1.png
+[8]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_2.png (Virtualbox menu)
+[9]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_3.png (Console)
+[10]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_4.png (Wordpress welcome)
+[11]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_5.png (Login screen)
+[12]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_6.png (Wordpress dashboard)
+[13]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_7.png (Wordpress configuration)
+[14]: http://Wordpress.org
+[15]: http://WordPress.org
+[16]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_8.png (Turnkey theme)
+[17]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_12.png (Add post dropdown)
+[18]: https://opensource.com/sites/default/files/uploads/how_to_get_started_with_wp_in_the_classroom_13.png (Wordpress classroom blog)
+[19]: https://opensource.com/sites/default/files/router-web.jpg (Example router setting screen)
+[20]: http://icanhazip.com/
+[21]: https://webhosting.coop/domain-names
+[22]: https://www.gandi.net
+[23]: http://freenom.com/
+[24]: https://wordpress.org/
+[25]: https://github.com/WordPress/WordPress/blob/master/license.txt
+[26]: https://wordpress.org/five-for-the-future/
diff --git a/sources/tech/20200417 Is reporting 100- of code coverage reasonable.md b/sources/tech/20200417 Is reporting 100- of code coverage reasonable.md
new file mode 100644
index 0000000000..6d57fb30f8
--- /dev/null
+++ b/sources/tech/20200417 Is reporting 100- of code coverage reasonable.md
@@ -0,0 +1,174 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Is reporting 100% of code coverage reasonable?)
+[#]: via: (https://opensource.com/article/20/4/testing-code-coverage)
+[#]: author: (Eric Herman https://opensource.com/users/ericherman)
+
+Is reporting 100% of code coverage reasonable?
+======
+The time required to reach reporting 100% of code coverage is
+considerably less than what I would have estimated before this
+exploration.
+![Code going into a computer.][1]
+
+The [Foundation for Public Code][2] works to enable open and collaborative public-purpose software for public organizations (like local governments) internationally. We do this by supporting software at the codebase level through codebase stewardship. We also publish the [Standard for Public Code][3] (draft version 0.1.4 at the time of this writing), which helps open source codebase communities build solutions that can be reused successfully by other organizations. It includes guidance for policymakers, managers, developers, designers, and vendors.
+
+Among other things, the standard addresses [code coverage][4], or how much of the code is executed when an automated test suite runs. It's one way to measure the likelihood that the code contains undetected software bugs. In the standard's ["Use continuous integration" requirements][5], it says, "source code test and documentation coverage **should** be monitored." Additionally, the [guidance to check][6] this requirement states, "code coverage tools check whether coverage is at 100% of the code."
+
+Over my software development career, which spans more than two decades, I have worked on codebases large and small and some with very high percentages of code coverage. Yet none of the non-trivial codebases I have contributed to have reported 100% test coverage. This made me question whether the "_check whether coverage is at 100%_" guidance would be followed.
+
+When I think about the nature of the test coverage gaps in the codebases I have worked on, they typically have been around system states that are very difficult (and in some cases, impossible) to create. For instance, in earlier versions of Java, I recall we were required to write catch blocks for exceptions that could never be thrown.
+
+Previously, I reasoned that 100% test coverage is something to aspire to, but it is probably not worth the cost on most codebases and may not be realistic in a few.
+
+Coverage tools have been getting smarter and more tunable over time. Languages have been getting lighter, and libraries have been getting easier to mock and test. So how unreasonable is 100% coverage of functionality today?
+
+### Resource exhaustion
+
+The high-quality but low test-coverage codebases I contribute to happen to be written in C or C++. A quick glance at these codebases shows that there is a class of common low-coverage situations that I'll lump together under the umbrella of resource exhaustion: out of memory, out of disk space, etc.
+
+Here is a simple example of code that does not check for resource exhaustion; in this case, memory allocation failure:
+
+
+```
+char *buf = malloc(80);
+sprintf(buf, "hello, world");
+```
+
+This example code needs to allocate a small buffer, so it calls **malloc(80)**, and **malloc** usually returns a pointer to 80 bytes of memory … but that can fail. In the (unlikely) case that **malloc** returns **NULL**, the code above will proceed to call **sprintf** with a **NULL** pointer which causes a crash. It is typical in C code to do something more like this:
+
+
+```
+char *buf = malloc(80);
+if (buf == NULL) {
+ fprintf(stderr, "malloc returned NULL for 80 bytes?\n");
+ return NULL;
+}
+sprintf(buf, "hello, world");
+```
+
+This code guards against **malloc** returning **NULL**, which is better. However, creating tests for correct behavior in the face of this kind of resource exhaustion can be really hard. It's not impossible, of course, and there are multiple approaches. Many approaches result in fragile tests, which require a lot of maintenance over time, and these tests can be very time-consuming to build in the first place.
+
+### Exploration
+
+Pondering this, I decided to run a little experiment to see if I could learn something about the costs and consequences of this strict, 100% criterion.
+
+Since I do some embedded-systems development, I have a few C libraries that I've developed and reused over the years in my embedded projects. I decided to look at some of these libraries and see just how hard it would be to bring them up to 100% code coverage. In the process, I paid attention to the impact on code clarity, code structure, and performance.
+
+#### A library with preexisting dependency injection
+
+Step one is measuring by adding code coverage to a codebase. Since this is C, **gcc** provides quite a lot by default with the **\--coverage** option, and **lcov** (with **genhtml**) does a good job of making reports; thus, this step was easy. I expected the starting coverage to be pretty good—it was, but it had a few untested branches, as well as the predicted gaps around error conditions and error reporting.
+
+I made error reporting pluggable, so it was easier to capture and make assertions around error messages in previously untested branches.
+
+Since this code already allowed for pluggable implementations of **malloc** and **free**, it was straightforward to write little malloc and free wrappers that I could inject memory allocation failures into. Within an hour or two, that was covered.
+
+In the process, I realized that there was one condition where, from the perspective of the calling client code, it was impossible to distinguish between the situation where an error occurs and one where **NULL** is a valid return value. For you C programmers, it was essentially similar to the following:
+
+
+```
+/* stashes a copy of the value
+ * returns the previously stashed value */
+char *foo_stash(foo_s *context,
+ char *stash_me,
+ size_t stash_me_len)
+{
+ char *copy = malloc(stash_me_len);
+ if (copy == NULL) {
+ return NULL;
+ }
+ memcpy(copy, stash_me, stash_me_len);
+ char *previous = context->stash;
+ context->stash = copy;
+ /* previous may be NULL */
+ return previous;
+}
+```
+
+I adjusted the API to allow the error information to be explicitly available. If you are a C developer, you know there are various ways this can be accomplished. I chose an approach similar to this:
+
+
+```
+/* stashes a copy of the value
+ * returns the previously stashed value
+ * on error, the 'err' pointer is set to 1 */
+char *foo_stash2(foo_s *context,
+ char *stash_me,
+ size_t stash_me_len,
+ int *err)
+{
+ char *copy = malloc(stash_me_len);
+ if (copy == NULL) {
+ *err = 1;
+ return NULL;
+ }
+ memcpy(copy, stash_me, stash_me_len);
+ char *previous = context->stash;
+ context->stash = copy;
+ /* previous may be NULL */
+ return previous;
+}
+```
+
+Without testing for resource exhaustion, it may have taken a long time for me to notice this (now obvious) shortcoming of the API.
+
+To get **lcov** to report 100% test coverage, I had to tell the compiler to [not inline any code][7], something I learned it does even at optimization level zero.
+
+When embedded in actual firmware, the compiler optimized away the unused indirection; therefore, the added indirection in the source code imposed no real-world performance penalty in the compiled firmware.
+
+Of course, this was the easy library.
+
+#### A more typical library
+
+Once I established a method of injecting memory allocation failures in tests, I decided to move onto another library, but one for which malloc and free were not already pluggable. I had questions. How invasive will this be to the codebase? Will it clutter the code, making it less clear? How time-consuming will it be?
+
+While I don't always record coverage metrics, I am a big believer in testing: more than 20 years ago, I learned that my code improves if I write the tests and client code [before][8] the implementation code, and I have worked that way ever since. (In [_Test-Driven Development: By Example_][9], you can find my name in the acknowledgments.) Yet, when I added code coverage reporting to the second library, I was surprised to see that (at some point in the past) I had added a pair of functions to the library without adding tests for them. The other untested areas were, unsurprisingly, code to handle memory-allocation failure.
+
+Writing tests for the pair of untested functions was, of course, quick and easy. The coverage tools also revealed that I had a function with an untested code branch that, given only a quick glance, contained a bug. The fix was trivial, yet I was surprised to find a bug, given the different projects where I use this library. Nonetheless, there it was, a humbling reminder that, all too often, bugs lurk in untested code.
+
+Next up was the more challenging stuff: testing for resource exhaustion. I started by introducing some global variables for the malloc/free function pointers, as well as a variable to hold a memory-tracking object. Once that was working, I moved those variables from global scope into a context argument that was already present. Refactoring the code to allow for the necessary indirection took only a couple of hours (less time than I expected), and the complexity added was negligible.
+
+### Reflections
+
+My conclusion from the first library was that it was well worth the time. The code is now more flexible, the API is now more complete for the caller, and writing the failure injection harness was pretty easy.
+
+From the second library, I was reminded that even less-pluggable code could be made testable without adding undue levels of complexity. The code improved, I fixed a bug, and I can be more confident in the code. Also, the additional modularity of being able to plug in an alternative memory allocator is a feature that may prove more valuable in the future.
+
+Exclusion comments are a feature of **lcov** to cause coverage reporting to ignore a block of code. Interestingly, I didn't feel the need to use exclusion comments in either library.
+
+I am more certain than ever that even very good code is improved by investing in test coverage.
+
+Both of these codebases are small, had some modularity already, began from a point of good testing, are single-threaded, and contain no graphical UI code. If I were to try to tackle this on one of the larger, more monolithic codebases I contribute to, it would be harder and require a larger time investment. There would likely be some sections of code where I might still conclude that the best thing to do would be to "cheat" by tuning the tooling to not report on some section of code.
+
+That said, I estimate that the time required to reach reporting 100% of code coverage is considerably less than what I would have estimated before this exploration.
+
+If you happen to be a C coder and want to see a running example of this, including **gcov** / **lcov** usage, I extracted the out-of-memory injecting code and put it in an [example repository][10].
+
+Have you pushed a codebase to 100% coverage by tests, or tried to? What was your experience? Please share it in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/testing-code-coverage
+
+作者:[Eric Herman][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/ericherman
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_computer_development_programming.png?itok=4OM29-82 (Code going into a computer.)
+[2]: https://publiccode.net/
+[3]: https://standard.publiccode.net
+[4]: https://en.wikipedia.org/wiki/Code_coverage
+[5]: https://standard.publiccode.net/criteria/continuous-integration.html#requirements
+[6]: https://standard.publiccode.net/criteria/continuous-integration.html#how-to-test
+[7]: https://twitter.com/Eric_Herman/status/1224983465784938496
+[8]: https://opensource.com/article/20/2/automate-unit-tests
+[9]: https://www.oreilly.com/library/view/test-driven-development/0321146530/
+[10]: https://github.com/ericherman/context-alloc
diff --git a/sources/tech/20200419 A stress-free guide to keeping WordPress sites updated.md b/sources/tech/20200419 A stress-free guide to keeping WordPress sites updated.md
new file mode 100644
index 0000000000..98ee9b1b1e
--- /dev/null
+++ b/sources/tech/20200419 A stress-free guide to keeping WordPress sites updated.md
@@ -0,0 +1,116 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (A stress-free guide to keeping WordPress sites updated)
+[#]: via: (https://opensource.com/article/20/4/updating-wordpress)
+[#]: author: (Sara Kelly https://opensource.com/users/sarapk)
+
+A stress-free guide to keeping WordPress sites updated
+======
+This practical guide to a necessary task will show you how to maximize
+site performance and avoid bugs and other issues with regular updates.
+![Working from home at a laptop][1]
+
+We all know how important it is to keep WordPress sites updated. New updates provide the latest bug and security fixes against any nasties lurking on the web. But, more critically, an outdated site can also lead to poor performance, such as slow loading speed or an outdated look and feel.
+
+Unfortunately, keeping your WordPress site up-to-date is not as easy as clicking a button. There are several components to consider, from theme to plugins to PHP. Even worse, updating too quickly can wreak another kind of havoc. Have you ever experienced the dreaded, "There has been a critical error on your website" warning after an innocent little update? I know I have, many times!
+
+Here is a practical guide on what to look out for, as well as when and what to update, to ensure your WordPress site works well.
+
+### Updating WordPress
+
+Let's start with the basics. Check your WordPress version is up-to-date by visiting Dashboard > Updates.
+
+![WordPress update screen][2]
+
+### Choosing a WordPress theme
+
+Before we deep dive into updating themes, I'd like to take a few steps back. Choose an up-to-date theme from the get-go and do your homework before installing it! There is nothing worse than pouring your heart and soul into customizing a new theme, only to discover it is buggy.
+
+Questions to ask when choosing a theme include:
+
+ * When was it first created?
+ * What is the current version available?
+ * Does the theme provider still maintain an active demo site and helpdesk?
+ * What do recent reviews say about the theme?
+
+
+
+If the theme provider is no longer maintaining the theme, save yourself the trouble and move on. Also, don't assume that just because you paid for a theme, that is necessarily maintained. I recently fell into this trap when I purchased [Pinable][3]. I loved the Pinterest look and feel. However, soon after installation, I noticed the lack of customization within the theme settings, major compatibility issues arose with my plugins, and the customer service was nonexistent. I should have known better. The theme was created in 2013 and selling for a bargain.
+
+If you already have a theme, then pay attention to how frequently updates become available. If there are never any updates, the theme provider may have closed up shop. It is only a matter of time before the impact of an outdated theme will cause problems.
+
+A quick aside while we are on the topic—up-to-date themes also give access to the two new alignment options in the WordPress block editor, which enable wide-width and full-width images. These help your blog posts look more professional. While there are a number of [tutorials][4] on the web that show you how to manually update your functions, PHP file, and CSS to enable the new alignment blocks, the code does not always work on older themes (especially masonry themes).
+
+![Wordpress theme][5]
+
+### Updating themes
+
+To check the current version of your theme, go to Appearance > Themes and click on the active theme to see the current version. If an upgrade is available, there will be an alert banner. Click on "update now" to initiate the update. You can also check for updates by going to Dashboard > Updates.
+
+![Themify screenshot][6]
+
+If you purchased a theme from a marketplace such as [Envato][7] or [Themify][8], check the theme documentation to learn what is required to initiate updates, as it will not show up automatically in the dashboard. In most cases, you will be required to download and install a specific plugin or manually upload new versions when they become available. In the latter case, you will need to delete or rename the old theme file via your cPanel before you can install the new one. A guide to installing themes via cPanel is available [here][9].
+
+If you plan to customize your theme extensively and are worried about the impact of this when upgrading, consider creating a child theme first. A child theme lets you make changes without touching the original theme's code. You can then update your site without losing any customizations you've made. Read more about child themes [here][10].
+
+As I said before, the source of most issues tends to be the theme. Learn what is required to keep your theme up to date, and do so regularly. If your theme provider is no longer creating updates, then find a new theme.
+
+### Easy does it for plugins
+
+If you manage multiple plugins, then you will be used to the frequent dashboard reminders to update! Before we get onto that, though, let's touch on some basics.
+
+As a general rule, you don't want to have too many plugins. They slow down the speed of your site by creating more code that the browser has to load. Always delete any inactive plugins. I prefer to manage plugins on the Plugins tab. Here you can see all active and inactive plugins, the current version, and whether an update is available. To update the plugin, simply click "update."
+
+![Plugin update page][11]
+
+Nonetheless, I implore you to wait a week or two before installing new updates. Updating my plugins too quickly has caused me no end of grievances. To begin with, updates are prone to human error. Don't be the guinea pig that tests out the latest version. Sometimes, the newest version of a plugin is not compatible with an older version of WordPress or your theme. Check these are up-to-date first.
+
+### Website down after updating plugins?
+
+If your site has stopped working or performance has dropped noticeably after updating your plugins, then all is not lost. Forget about those newfangled plugins that promise to test speed and identify buggy plugins (the last thing you want is more plugins)! Disable all your plugins, then activate one at a time while you test the speed and performance of your site on a website such as [Pingdom][12]. This is a great exercise to perform periodically, even if your website has not crashed. Once you identify the plugin causing the problem, delete it.
+
+In the event you cannot access WordPress because there is a critical error, then you will need to access your files via cPanel and delete all the plugin folders from there ([full instructions here][13]). Don't worry; doing this will not impact your website's content. You can then proceed to reinstall and activate the plugins one-by-one via WordPress.
+
+Cache plugins tend to be the biggest culprit in my experience. Issues with cache plugins can be minimized by clearing the cache frequently. Do not install multiple cache plugins that perform the same function, as they will only serve to slow down your site. The only way to truly get around cache plugin issues is to either not use them, use a plugin recommended by your hosting provider, or become an expert on cache. [This blog][14] on common cache issues in WordPress is a good place to start.
+
+### Back up before updating PHP
+
+If you are concerned about your website speed and have spent enough time browsing Google for answers, then you likely have seen the advice, "You gotta update your PHP!" Please tread carefully with manual PHP updates, though! If you have a good hosting provider, you should never need to do this. Rather, select the option for automatic PHP version management with your host. Newer versions of PHP may not be stable or compatible with the version of WordPress you are running. Let your hosting provider be the one to determine when updates are ready.
+
+However, if you are adamant that an old version of PHP is causing your website to be slow, take care to follow these steps before initiating an update. First, back up your site. Investing in a premium version of [Jetpack][15] is worth its weight in gold. Jetpack can perform real-time as well as daily backups, depending on your plan. Not to mention, their customer service and troubleshooting support are excellent. Secondly, inform your hosting provider that you plan to update the PHP and seek their advice first. If your host is unable to advise or wants to charge you for the privilege, you should probably think about changing hosts.
+
+You can update PHP either via cPanel or via your hosting platform under Devs > PHP Manager. After that, you are on your own, as that is where my expertise on PHP ends.
+
+If you have any other tips or pitfalls regarding updating WordPress, drop them in the comments box below.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/updating-wordpress
+
+作者:[Sara Kelly][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sarapk
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/wfh_work_home_laptop_work.png?itok=VFwToeMy (Working from home at a laptop)
+[2]: https://opensource.com/sites/default/files/uploads/wp_update_1.png (Wordpress update screen)
+[3]: https://www.theme-junkie.com/themes/pinable/
+[4]: https://www.billerickson.net/full-and-wide-alignment-in-gutenberg/
+[5]: https://opensource.com/sites/default/files/uploads/wp_theme_2.png (Wordpress theme)
+[6]: https://opensource.com/sites/default/files/uploads/themify_3.png (Themify screenshot)
+[7]: https://elements.envato.com/
+[8]: https://themify.me/
+[9]: https://hostadvice.com/how-to/how-to-install-a-wordpress-theme-using-cpanel/
+[10]: https://developer.wordpress.org/themes/advanced-topics/child-themes/
+[11]: https://opensource.com/sites/default/files/uploads/plugins_4.png (Plugin update page)
+[12]: https://tools.pingdom.com/
+[13]: https://www.wpbeginner.com/plugins/how-to-deactivate-all-plugins-when-not-able-to-access-wp-admin/
+[14]: https://mhthemes.com/support/knb/solving-common-cache-issues-on-wordpress-websites/
+[15]: https://jetpack.com/upgrade/backup/?utm_source=google&utm_campaign=google_jetpack_search_brand_desktop_sg_en&utm_medium=paid_search&utm_term=%2Bwordpress%20%2Bjetpack%20%2Bbackup&creative=379260213317&campaignid=2061290863&utm_content=77066462603&matchtype=b&device=c&network=g&gclid=Cj0KCQjwu6fzBRC6ARIsAJUwa2RuPx5Dzr72eBEtZegsf11MmOBgLiwLX2HcEUXVaULIgv1MdZqGmeAaArmFEALw_wcB&gclsrc=aw.ds
diff --git a/sources/tech/20200419 Getting Started With Pacman Commands in Arch-based Linux Distributions.md b/sources/tech/20200419 Getting Started With Pacman Commands in Arch-based Linux Distributions.md
new file mode 100644
index 0000000000..f2fd06793f
--- /dev/null
+++ b/sources/tech/20200419 Getting Started With Pacman Commands in Arch-based Linux Distributions.md
@@ -0,0 +1,250 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Getting Started With Pacman Commands in Arch-based Linux Distributions)
+[#]: via: (https://itsfoss.com/pacman-command/)
+[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
+
+Getting Started With Pacman Commands in Arch-based Linux Distributions
+======
+
+_**Brief: This beginner’s guide shows you what you can do with pacmancommands in Linux, how to use them to find new packages, install and upgrade new packages, and clean your system.**_
+
+The [pacman][1] package manager is one of the main difference between [Arch Linux][2] and other major distributions like Red Hat and Ubuntu/Debian. It combines a simple binary package format with an easy-to-use [build system][3]. The aim of pacman is to easily manage packages, either from the [official repositories][4] or the user’s own builds.
+
+If you ever used Ubuntu or Debian-based distributions, you might have used the apt-get or apt commands. Pacman is the equivalent in Arch Linux. If you [just installed Arch Linux][5], one of the first few [things to do after installing Arch Linux][6] is to learn to use pacman commands.
+
+In this beginner’s guide, I’ll explain some of the essential usage of the pacmand command that you should know for managing your Arch-based system.
+
+### Essential pacman commands Arch Linux users should know
+
+![][7]
+
+Like other package managers, pacman can synchronize package lists with the software repositories to allow the user to download and install packages with a simple command by solving all required dependencies.
+
+#### Install packages with pacman
+
+You can install a single package or multiple packages using pacman command in this fashion:
+
+```
+pacman -S _package_name1_ _package_name2_ ...
+```
+
+![Installing a package][8]
+
+The -S stands for synchronization. It means that pacman first synchronizes
+
+The pacman database categorises the installed packages in two groups according to the reason why they were installed:
+
+ * **explicitly-installed**: the packages that were installed by a generic pacman -S or -U command
+ * **dependencies**: the packages that were implicitly installed because [required][9] by another package that was explicitly installed.
+
+
+
+#### Remove an installed package
+
+To remove a single package, leaving all of its dependencies installed:
+
+```
+pacman -R package_name_
+```
+
+![Removing a package][10]
+
+To remove a package and its dependencies which are not required by any other installed package:
+
+```
+pacman -Rs _package_name_
+```
+
+To remove dependencies that are no longer needed. For example, the package which needed the dependencies was removed.
+
+```
+pacman -Qdtq | pacman -Rs -
+```
+
+#### Upgrading packages
+
+Pacman provides an easy way to [update Arch Linux][11]. You can update all installed packages with just one command. This could take a while depending on how up-to-date the system is.
+
+The following command synchronizes the repository databases _and_ updates the system’s packages, excluding “local” packages that are not in the configured repositories:
+
+```
+pacman -Syu
+```
+
+ * S stands for sync
+ * y is for refresh (local
+ * u is for system update
+
+
+
+Basically it is saying that sync to central repository (master package database), refresh the local copy of the master package database and then perform the system update (by updating all packages that have a newer version available).
+
+![System update][12]
+
+Attention!
+
+If you are an Arch Linux user before upgrading, it is advised to visit the [Arch Linux home page][2] to check the latest news for out-of-the-ordinary updates. If manual intervention is needed an appropriate news post will be made. Alternatively you can subscribe to the [RSS feed][13] or the [arch-announce mailing list][14].
+
+Be also mindful to look over the appropriate [forum][15] before upgrading fundamental software (such as the kernel, xorg, systemd, or glibc), for any reported problems.
+
+**Partial upgrades are unsupported** at a rolling release distribution such as Arch and Manjaro. That means when new library versions are pushed to the repositories, all the packages in the repositories need to be rebuilt against the libraries. For example, if two packages depend on the same library, upgrading only one package, might break the other package which depends on an older version of the library.
+
+#### Use pacman to search for packages
+
+Pacman queries the local package database with the -Q flag, the sync database with the -S flag and the files database with the -F flag.
+
+Pacman can search for packages in the database, both in packages’ names and descriptions:
+
+```
+pacman -Ss _string1_ _string2_ ...
+```
+
+![Searching for a package][16]
+
+To search for already installed packages:
+
+```
+pacman -Qs _string1_ _string2_ ...
+```
+
+To search for package file names in remote packages:
+
+```
+pacman -F _string1_ _string2_ ...
+```
+
+To view the dependency tree of a package:
+
+```
+pactree _package_naenter code hereme_
+```
+
+#### Cleaning the package cache
+
+Pacman stores its downloaded packages in /var/cache/pacman/pkg/ and does not remove the old or uninstalled versions automatically. This has some advantages:
+
+ 1. It allows to [downgrade][17] a package without the need to retrieve the previous version through other sources.
+ 2. A package that has been uninstalled can easily be reinstalled directly from the cache folder.
+
+
+
+However, it is necessary to clean up the cache periodically to prevent the folder to grow in size.
+
+The [paccache(8)][18] script, provided within the [pacman-contrib][19] package, deletes all cached versions of installed and uninstalled packages, except for the most recent 3, by default:
+
+```
+paccache -r
+```
+
+![Clear cache][20]
+
+To remove all the cached packages that are not currently installed, and the unused sync database, execute:
+
+```
+pacman -Sc
+```
+
+To remove all files from the cache, use the clean switch twice, this is the most aggressive approach and will leave nothing in the cache folder:
+
+```
+pacman -Scc
+```
+
+#### Installing local or third-party packages
+
+Install a ‘local’ package that is not from a remote repository:
+
+```
+pacman -U _/path/to/package/package_name-version.pkg.tar.xz_
+```
+
+Install a ‘remote’ package, not contained in an official repository:
+
+```
+pacman -U http://www.example.com/repo/example.pkg.tar.xz
+```
+
+### Bonus: Troubleshooting common errors with pacman
+
+Here are some common errors you may encounter while managing packages with pacman.
+
+#### Failed to commit transaction (conflicting files)
+
+If you see the following error:
+
+```
+error: could not prepare transaction
+error: failed to commit transaction (conflicting files)
+package: /path/to/file exists in filesystem
+Errors occurred, no packages were upgraded.
+```
+
+This is happening because pacman has detected a file conflict and will not overwrite files for you.
+
+A safe way to solve this is to first check if another package owns the file (pacman -Qo _/path/to/file_). If the file is owned by another package, file a bug report. If the file is not owned by another package, rename the file which ‘exists in filesystem’ and re-issue the update command. If all goes well, the file may then be removed.
+
+Instead of manually renaming and later removing all the files that belong to the package in question, you may explicitly run _**pacman -S –overwrite glob package**_ to force pacman to overwrite files that match _glob_.
+
+#### Failed to commit transaction (invalid or corrupted package)
+
+Look for .part files (partially downloaded packages) in /var/cache/pacman/pkg/ and remove them. It is often caused by usage of a custom XferCommand in pacman.conf.
+
+#### Failed to init transaction (unable to lock database)
+
+When pacman is about to alter the package database, for example installing a package, it creates a lock file at /var/lib/pacman/db.lck. This prevents another instance of pacman from trying to alter the package database at the same time.
+
+If pacman is interrupted while changing the database, this stale lock file can remain. If you are certain that no instances of pacman are running then delete the lock file.
+
+Check if a process is holding the lock file:
+
+```
+lsof /var/lib/pacman/db.lck
+```
+
+If the above command doesn’t return anything, you can remove the lock file:
+
+```
+rm /var/lib/pacman/db.lck
+```
+
+If you find the PID of the process holding the lock file with lsof command output, kill it first and then remove the lock file.
+
+I hope you like my humble effort in explaining the basic pacman commands. Please leave your comments below and don’t forget to subscribe on our social media. Stay safe!
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/pacman-command/
+
+作者:[Dimitrios Savvopoulos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/dimitrios/
+[b]: https://github.com/lujun9972
+[1]: https://www.archlinux.org/pacman/
+[2]: https://www.archlinux.org/
+[3]: https://wiki.archlinux.org/index.php/Arch_Build_System
+[4]: https://wiki.archlinux.org/index.php/Official_repositories
+[5]: https://itsfoss.com/install-arch-linux/
+[6]: https://itsfoss.com/things-to-do-after-installing-arch-linux/
+[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/essential-pacman-commands.jpg?ssl=1
+[8]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-S.png?ssl=1
+[9]: https://wiki.archlinux.org/index.php/Dependency
+[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-R.png?ssl=1
+[11]: https://itsfoss.com/update-arch-linux/
+[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-Syu.png?ssl=1
+[13]: https://www.archlinux.org/feeds/news/
+[14]: https://mailman.archlinux.org/mailman/listinfo/arch-announce/
+[15]: https://bbs.archlinux.org/
+[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-pacman-Ss.png?ssl=1
+[17]: https://wiki.archlinux.org/index.php/Downgrade
+[18]: https://jlk.fjfi.cvut.cz/arch/manpages/man/paccache.8
+[19]: https://www.archlinux.org/packages/?name=pacman-contrib
+[20]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/sudo-paccache-r.png?ssl=1
diff --git a/sources/tech/20200420 New open source GIS projects for Kubernetes applications.md b/sources/tech/20200420 New open source GIS projects for Kubernetes applications.md
new file mode 100644
index 0000000000..a8fdec6e71
--- /dev/null
+++ b/sources/tech/20200420 New open source GIS projects for Kubernetes applications.md
@@ -0,0 +1,99 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (New open source GIS projects for Kubernetes applications)
+[#]: via: (https://opensource.com/article/20/4/gis-kubernetes)
+[#]: author: (Adam Timm https://opensource.com/users/timmam)
+
+New open source GIS projects for Kubernetes applications
+======
+pg_tileserv and pg_featureserv make it easier for developers to add
+location services to Kubernetes applications.
+![A map with a route highlighted][1]
+
+Spatial data from geographic information systems (GIS) is all around us. From smartphones that make our lives better and more convenient to precision agriculture that is increasing the amount of food farmers can produce while reducing the cost, whether or not we realize it, almost every part of our lives is touched by spatial data.
+
+This increase of spatial data is simultaneously bringing an increase of open spatial datasets that people can consume and use to build all sorts of new applications. However, these types of datasets have not always been easy to work with. Also, due to the size of some of the geographic data, they can be difficult to bring to modern application deployment frameworks such as Kubernetes.
+
+To help with these issues, [Crunchy Data][2] recently announced two new open source projects, [pg_tileserv][3] and [pg_featureserv][4], to make it easier to develop cloud-native spatial applications. These projects, part of open source [Crunchy Spatial][5], help developers leverage the robust [PostGIS][6] geospatial database extension to [PostgreSQL][7] without having to write complex SQL statements.
+
+So what are pg_tileserv and pg_featuresev, how do they make it easier for developers to add location services to their Kubernetes applications, and what does this mean for the future of spatial applications?
+
+### Traditional GIS vs. modern spatial microservices
+
+Traditionally, when an organization or individual works with spatial data, they start with a product that grew up as a GIS. There are many high-quality open source GIS products ([QGIS][8], [GeoServer][9], [GeoNode][10], etc.), but they may not align with modern, cloud-native approaches to software design.
+
+The popularity of Kubernetes creates challenges for these legacy applications around automation and deployment, as they require a lot of manual configuration, for example, when data sources are added and modified. In many setups, these spatial applications must exist outside Kubernetes and cannot leverage many of the conveniences it provides.
+
+In contrast, modern spatial services should be driven by the spatial data that they are processing and serving out. They should align with modern software development practices and scale efficiently and integrate easily with developer workflows.
+
+Applications that are spatially aware also need to ensure they can handle the unique characteristics of spatial data (e.g., geometries, projections, etc.). To do all of this in independent microservices can be challenging unless you have a highly capable database to do the majority of the work for you. This is where pg_tileserv and pg_featureserv help, as both projects leverage the power of PostGIS, an open source geospatial extension to PostgreSQL, to provide advanced spatial capabilities from a simple REST framework
+
+### Generate map vector tiles with pg_tileserv
+
+![pg_tileserv][11]
+
+pg_tileserv is a lightweight vector tile server written in Go that enables you to generate [vector tiles][12] directly from PostGIS. It does this by implementing the **ST_AsMVT()** function in a best-practice method that translates an HTTP request to the database. It includes common defaults that allow you to pass a database connection URL to the server and be up and running in no time. There's no heavyweight software to install and configure, and it's designed for cloud-native GIS applications.
+
+For specific examples on how to use it, check out our blog posts on [tile serving][13] and [spatial tile serving with PostgreSQL functions][14].
+
+### Annotate your maps with pg_featureserv
+
+![pg_featureserv][15]
+
+pg_featureserv is a lightweight service written in Go that enables you to serve features directly out of PostGIS. It implements the [OGC API][16] for features and provides a standard REST endpoint for your spatial data and functions contained in PostGIS. Just like pg_tileserv, there's no heavyweight software to install; just pass a database connection URL to your PostGIS database, and you're off to the races. For a specific example of how to use it, check out our post on [querying spatial features][17].
+
+### Focus on spatial data, not GIS
+
+With our deep background in developing PostGIS and building PostGIS-backed applications, we wanted to help developers unlock all the value of spatial data in a way that is easy to deploy, scale, and maintain. As the source code of pg_tileserv and pg_featureserv show, we are just leveraging functions already in PostGIS. This allows developers to quickly add spatial data to their applications and data scientists to focus on the data.
+
+![GIS architecture][18]
+
+The benefits of this approach are:
+
+ * Faster performance because PostgreSQL and PostGIS are doing the work for you
+ * Less configuration to maintain because the database structure is the configuration
+ * By design, it runs in the cloud at enterprise scale from the start
+ * Shorter times to update customer-facing applications—when you update your data in the database, your application is updated instantly
+ * Ability to focus more on maintaining your data and delivering value to your users and less on wrangling software
+
+
+
+Also, since these services respond to the configuration of your database, they also expose functions contained in the database. Rather than developing their data functions to incorporate them into software later, data scientists can create functions in the database that are immediately made available via a REST API. The software begins to fade into the background so an organization can focus on the data.
+
+Suffice it to say, we're pretty excited about these new geospatial services, and we definitely want your feedback on them. Feel free to check out [pg_tileserve][3] and [pg_featureserv][4], try deploying them alongside your PostGIS databases with the [PostgreSQL Operator][19], and share your feedback in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/gis-kubernetes
+
+作者:[Adam Timm][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/timmam
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/map_route_location_gps_path.png?itok=RwtS4DsU (A map with a route highlighted)
+[2]: https://www.crunchydata.com/
+[3]: https://github.com/CrunchyData/pg_tileserv
+[4]: https://github.com/CrunchyData/pg_featureserv
+[5]: https://www.crunchydata.com/products/crunchy-spatial/
+[6]: https://postgis.net/
+[7]: https://www.postgresql.org
+[8]: https://www.qgis.org/en/site/
+[9]: http://geoserver.org/
+[10]: http://geonode.org/
+[11]: https://opensource.com/sites/default/files/pg_tileserv.jpg (pg_tileserv)
+[12]: https://info.crunchydata.com/blog/dynamic-vector-tiles-from-postgis
+[13]: https://info.crunchydata.com/blog/crunchy-spatial-tile-serving
+[14]: https://info.crunchydata.com/blog/crunchy-spatial-tile-serving-with-postgresql-functions
+[15]: https://opensource.com/sites/default/files/pg_featureserv.jpg (pg_featureserv)
+[16]: http://www.ogcapi.org/
+[17]: https://info.crunchydata.com/blog/crunchy-spatial-querying-spatial-features-with-pg_featureserv
+[18]: https://opensource.com/sites/default/files/uploads/architecture_0.png (GIS architecture)
+[19]: https://github.com/CrunchyData/postgres-operator
diff --git a/sources/tech/20200421 How I use Hugo for my classroom-s open source CMS.md b/sources/tech/20200421 How I use Hugo for my classroom-s open source CMS.md
new file mode 100644
index 0000000000..bef4b09a9a
--- /dev/null
+++ b/sources/tech/20200421 How I use Hugo for my classroom-s open source CMS.md
@@ -0,0 +1,99 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How I use Hugo for my classroom's open source CMS)
+[#]: via: (https://opensource.com/article/20/4/hugo-classroom)
+[#]: author: (Peter Cheer https://opensource.com/users/petercheer)
+
+How I use Hugo for my classroom's open source CMS
+======
+This open source software streamlines text editing while leaving room
+for customization.
+![Digital hand surrounding by objects, bike, light bulb, graphs][1]
+
+People love Markdown text with good reason—it is easy to write, easy to read, easy to edit, and it can be converted to a wide range of other text mark up formats. While Markdown text is very good for content creation and manipulation, it imposes limitations on the options for content display.
+
+If we could combine the virtues of Markdown with the power and flexibility of Cascading Style Sheets, HTML5, and JavaScript, that would be something special. One of the programs trying to do this is [Hugo][2]. Hugo was created in 2013 by Steve Francia; it is cross-platform and open source under an Apache 2.0 license with an active developer community and a growing user base.
+
+The basic concept is that pieces of content, such as web pages or blog posts, written in Markdown and associated with metadata, are converted into HTML and combined with templates and themes to produce a complete web site. The power and flexibility come through these themes and templates or changing the default behaviors of Hugo. This power comes with a degree of unavoidable complexity, but there are lots of [pre-built templates][3] available if you lack the time or inclination to make your own.
+
+Installing Hugo on my Linux machine was quick and easy. Starting a new project is as simple as typing **hugo new site quickstart** at the command line which creates a new project with this folder structure:
+
+ * **archetypes**: Content template files that contain preconfigured front matter metadata (date, title, draft). You can create new archetypes with custom front matter fields.
+ * **assets**: Stores all the files, which are processed by Hugo Pipes (e.g., CSS/Sass files). This directory is not created by default.
+ * **config.toml**: The default site config file.
+ * **content**: Where all the content Markdown files live.
+ * **data**: Used to store configuration files that can be used by Hugo when generating your website.
+ * **layouts**: Stores templates as .html files.
+ * **static**: Stores all the static content—images, CSS, JavaScript, etc.
+ * **themes**: For the Hugo theme of your choice.
+
+
+
+The Markdown files in the content folder can be created manually or by Hugo and edited with any text editor or your Markdown creation tool of choice. If created manually, you will need to add any metadata that is needed. I prefer to use [Ghostwriter][4] for writing Markdown. Images are usually kept in a sub-folder in the static folder. Site development can proceed quickly, as Hugo includes a web server for testing and pre-viewing.
+
+To check your work, type **hugo server** at the command line to start the server. By default, Hugo will not publish:
+
+ * Content with a future **publishdate** value.
+ * Content with **draft: true** status.
+ * Content with a past **expirydate** value.
+
+
+
+Adding **hugo server -D** will include draft articles, and Hugo can be configured to mark all new articles as draft. After starting the web server, you can see your work in a web browser at localhost:1313. Once the server is started by default, it will automatically reload the browser window when it detects a change to one of your files.
+
+There are tasks Markdown cannot do that need some HTML code. Hugo recognizes this but believes in keeping Markdown code as clean, simple, and uncluttered as possible. Hugo does this with shortcodes such as **{{< youtube id= "w7Ft2ymGmfc" autoplay= "true">}}**, which will embed the YouTube video with id. w7Ft2ymGmfc. There are quite a few pre-built shortcodes for common tasks, but it is also possible to create your own for particular jobs.
+
+I work in education quite a lot and wanted to include some interactive puzzles and questions on my Hugo-generated website. To get the output looking like this:
+
+![JClic shortcode][5]
+
+I created the activities with an open source Java program called [JClic][6], exported them as HTML5, put that into static/activities/excel, and displayed it in an iframe.
+
+The HTML code, which would spoil the nice clean Markdown content, looks like this:
+
+
+```
+ <[iframe][7]
+ src="/activity/excel/index.html"
+ title="Activity"
+ height="400"
+ frameborder="0"
+ marginwidth="0"
+ marginheight="0"
+ scrolling="no"
+ style="border: 1px solid #CCC; border-width: 1px; margin-bottom: 20px; width: 100%;"
+ allowfullscreen="true">
+ </[iframe][7]>
+```
+
+The code is saved in layouts/shortcodes as **activity.html**
+
+This makes the shortcode placed inside my Markdown file **{{<activity>}}**, which is much neater.
+
+When your project is ready, you can build it with the **hugo** command; this will create a public folder and generate the website in it. Hugo has a number of built-in deployment options for different hosting providers—basically, you deploy your site by copying the public folder to your production web server. There is a lot more to Hugo that I haven't even gotten to yet, including configuration options, importing content from other static site generators and Wordpress, display data from JSON files, syntax highlighting of source code, and the fact that it is very fast (an advantage when working with large sites).
+
+In many software tools, ease-of-use comes at the expense of flexibility, or vice-versa; Hugo makes a largely successful attempt at including both. For basic use with Markdown content and a pre-built theme, Hugo is easy to use and produces rapid results. Alternatively, if you have the need to alter the configuration settings or dive in and create your own themes, shortcodes, templates, or metadata schemes, that choice is open to you.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/hugo-classroom
+
+作者:[Peter Cheer][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/petercheer
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003588_01_rd3os.combacktoschoolseriesk12_rh_021x_0.png?itok=fvorN0e- (Digital hand surrounding by objects, bike, light bulb, graphs)
+[2]: https://gohugo.io/
+[3]: https://themes.gohugo.io/
+[4]: http://github.com/wereturtle/ghostwriter
+[5]: https://opensource.com/sites/default/files/uploads/jclic_shortcode.png (JClic shortcode)
+[6]: https://clic.xtec.cat/legacy/en/index.html
+[7]: http://december.com/html/4/element/iframe.html
diff --git a/sources/tech/20200421 How I use Python to map the global spread of COVID-19.md b/sources/tech/20200421 How I use Python to map the global spread of COVID-19.md
new file mode 100644
index 0000000000..2f5f8dbef0
--- /dev/null
+++ b/sources/tech/20200421 How I use Python to map the global spread of COVID-19.md
@@ -0,0 +1,170 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How I use Python to map the global spread of COVID-19)
+[#]: via: (https://opensource.com/article/20/4/python-map-covid-19)
+[#]: author: (AnuragGupta https://opensource.com/users/999anuraggupta)
+
+How I use Python to map the global spread of COVID-19
+======
+Create a color coded geographic map of the potential spread of the virus
+using these open source scripts.
+![Globe up in the clouds][1]
+
+The spread of disease is a real concern for a world in which global travel is commonplace. A few organizations track significant epidemics (and any pandemic), and fortunately, they publish their work as open data. The raw data can be difficult for humans to process, though, and that's why data science is so vital. For instance, it could be useful to visualize the worldwide spread of COVID-19 with Python and Pandas.
+
+It can be hard to know where to start when you're faced with large amounts of raw data. The more you do it, however, the more patterns begin to emerge. Here's a common scenario, applied to COVID-19 data:
+
+ 1. Download COVID-19 country spread daily data into a Pandas DataFrame object from GitHub. For this, you need the Python Pandas library.
+ 2. Process and clean the downloaded data and make it suitable for visualizing. The downloaded data (as you will see for yourself) is in quite good condition. The one problem with this data is that it uses the names of countries, but it's better to use three-digit ISO 3 codes. To generate the three-digit ISO 3 codes, use a small Python library called pycountry. Having generated these codes, you can add an extra column to our DataFrame and populate it with these codes.
+ 3. Finally, for the visualization, use the **express** module of a library called Plotly. This article uses what are called choropleth maps (available in Plotly) to visualize the worldwide spread of the disease.
+
+
+
+### Step 1: Corona data
+
+We will download the latest corona data from:
+
+
+
+We will load the data directly into a Pandas DataFrame. Pandas provides a function, **read_csv()**, which can take a URL and return a DataFrame object as shown below:
+
+
+```
+import pycountry
+import plotly.express as px
+import pandas as pd
+URL_DATASET = r''
+df1 = pd.read_csv(URL_DATASET)
+print(df1.head(3)) # Get first 3 entries in the dataframe
+print(df1.tail(3)) # Get last 3 entries in the dataframe
+```
+
+The screenshot of output (on Jupyter) is:
+
+![Jupyter screenshot][2]
+
+From output, you can see that the DataFrame (df1) has the following columns:
+
+ 1. Date
+ 2. Country
+ 3. Confirmed
+ 4. Recovered
+ 5. Dead
+
+
+
+Further, you can see that the **Date** column has entries starting from January 22 to March 31. This database is updated daily, so you will get the current values.
+
+### Step 2: Cleaning and modifying the data frame
+
+We need to add another column to this DataFrame, which has the three-letter ISO alpha-3 codes. To do this, I followed these steps:
+
+ 1. Create a list of all countries in the database. This was required because in the **df**, in the column **Country**, each country was figuring for each date. So in effect, the **Country** column had multiple entries for each country. To do this, I used the **unique().tolist()** functions.
+ 2. Then I took a dictionary **d_country_code** (initially empty) and populated it with keys consisting of country names and values consisting of their three-letter ISO codes.
+ 3. To generate the three-letter ISO code for a country, I used the function **pycountry.countries.search_fuzzy(country)**. You need to understand that the return value of this function is a "list of **Country** objects." I passed the return value of this function to a name country_data. Further, in this list of objects, the first object i.e., at index 0, is the best fit. Further, this **\** object has an attribute **alpha_3**. So, I can "access" the 3 letter ISO code by using **country_data[0].alpha_3**. However, it is possible that some country names in the DataFrame may not have a corresponding ISO code (For example, disputed territories). So, for such countries, I gave an ISO code of "i.e. a blank string. Further, you need to wrap this code in a try-except block. The statement: **print(_‘could not add ISO 3 code for ->'_, country)** will give a printout of those countries for which the ISO 3 codes could not be found. In fact, you will find such countries as shown with white color in the final output.
+ 4. Having got the three-letter ISO code for each country (or an empty string for some), I added the country name (as key) and its corresponding ISO code (as value) to the dictionary **d_country_code**. For adding these, I used the **update()** method of the Python dictionary object.
+ 5. Having created a dictionary of country names and their codes, I added them to the DataFrame using a simple for loop.
+
+
+
+### Step 3: Visualizing the spread using Plotly
+
+A choropleth map is a map composed of colored polygons. It is used to represent spatial variations of a quantity. We will use the express module of Plotly conventionally called **px**. Here we show you how to create a choropleth map using the function: **px.choropleth**.
+
+The signature of this function is:
+
+
+```
+`plotly.express.choropleth(data_frame=None, lat=None, lon=None, locations=None, locationmode=None, geojson=None, featureidkey=None, color=None, hover_name=None, hover_data=None, custom_data=None, animation_frame=None, animation_group=None, category_orders={}, labels={}, color_discrete_sequence=None, color_discrete_map={}, color_continuous_scale=None, range_color=None, color_continuous_midpoint=None, projection=None, scope=None, center=None, title=None, template=None, width=None, height=None)`
+```
+
+The noteworthy points are that the **choropleth()** function needs the following things:
+
+ 1. A geometry in the form of a **geojson** object. This is where things are a bit confusing and not clearly mentioned in its documentation. You may or may not provide a **geojson** object. If you provide a **geojson** object, then that object will be used to plot the earth features, but if you don't provide a **geojson** object, then the function will, by default, use one of the built-in geometries. (In our example here, we will use a built-in geometry, so we won't provide any value for the **geojson** argument)
+ 2. A pandas DataFrame object for the attribute **data_frame**. Here we provide our DataFrame ie **df1** we created earlier.
+ 3. We will use the data of **Confirmed** column to decide the color of each country polygon.
+ 4. Further, we will use the **Date** column to create the **animation_frame**. Thus as we slide across the dates, the colors of the countries will change as per the values in the **Confirmed** column.
+
+
+
+The complete code is given below:
+
+
+```
+import pycountry
+import plotly.express as px
+import pandas as pd
+# ----------- Step 1 ------------
+URL_DATASET = r''
+df1 = pd.read_csv(URL_DATASET)
+# print(df1.head) # Uncomment to see what the dataframe is like
+# ----------- Step 2 ------------
+list_countries = df1['Country'].unique().tolist()
+# print(list_countries) # Uncomment to see list of countries
+d_country_code = {} # To hold the country names and their ISO
+for country in list_countries:
+ try:
+ country_data = pycountry.countries.search_fuzzy(country)
+ # country_data is a list of objects of class pycountry.db.Country
+ # The first item ie at index 0 of list is best fit
+ # object of class Country have an alpha_3 attribute
+ country_code = country_data[0].alpha_3
+ d_country_code.update({country: country_code})
+ except:
+ print('could not add ISO 3 code for ->', country)
+ # If could not find country, make ISO code ' '
+ d_country_code.update({country: ' '})
+
+# print(d_country_code) # Uncomment to check dictionary
+
+# create a new column iso_alpha in the df
+# and fill it with appropriate iso 3 code
+for k, v in d_country_code.items():
+ df1.loc[(df1.Country == k), 'iso_alpha'] = v
+
+# print(df1.head) # Uncomment to confirm that ISO codes added
+# ----------- Step 3 ------------
+fig = px.choropleth(data_frame = df1,
+ locations= "iso_alpha",
+ color= "Confirmed", # value in column 'Confirmed' determines color
+ hover_name= "Country",
+ color_continuous_scale= 'RdYlGn', # color scale red, yellow green
+ animation_frame= "Date")
+
+fig.show()
+```
+
+The output is something like the following:
+
+![Map][3]
+
+You can download and run the [complete code][4].
+
+To wrap up, here are some excellent resources on choropleth in Plotly:
+
+ *
+ * [https://plotly.com/python/reference/#choropleth][5]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/python-map-covid-19
+
+作者:[AnuragGupta][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/999anuraggupta
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/cloud-globe.png?itok=_drXt4Tn (Globe up in the clouds)
+[2]: https://opensource.com/sites/default/files/uploads/jupyter_screenshot.png (Jupyter screenshot)
+[3]: https://opensource.com/sites/default/files/uploads/map_2.png (Map)
+[4]: https://github.com/ag999git/jupyter_notebooks/blob/master/corona_spread_visualization
+[5]: tmp.azs72dmHFd#choropleth
diff --git a/sources/tech/20200421 How to take advantage of Linux-s extensive vocabulary.md b/sources/tech/20200421 How to take advantage of Linux-s extensive vocabulary.md
new file mode 100644
index 0000000000..249d9d84f5
--- /dev/null
+++ b/sources/tech/20200421 How to take advantage of Linux-s extensive vocabulary.md
@@ -0,0 +1,273 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to take advantage of Linux's extensive vocabulary)
+[#]: via: (https://www.networkworld.com/article/3539011/how-to-takke-advantage-of-linuxs-extensive-vocabulary.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+How to take advantage of Linux's extensive vocabulary
+======
+Linux systems don't only know a lot of words, it has commands that can help you use them by finding words that are on the tip of your tongue or fixing your typos.
+Sandra Henry-Stocker
+
+While you might not think of Linux as a writing tutor, it does have some commendable language skills – at least when it comes to English. While the average American probably has a vocabulary between 20,000 and 50,000 words, Linux can claim over 100,000 words (spellings, not definitions). And you can easily put this vocabulary to work for you in a number of ways. Let’s look at how Linux can help with your word challenges.
+
+### Help with finding words
+
+First, let’s focus on finding words.If you use the **wc** command to count the number of words in the **/usr/share/dict/words** file on your system, you should see something like this:
+
+```
+$ wc -l /usr/share/dict/words
+102402 /usr/share/dict/words
+```
+
+As you can see, the **words** file on this system contains 102,402 words. So, when you’re trying to nail down just the right word and are having trouble, you stand a good chance of finding it on your system by remembering (or guessing at) some part of it. But you'll need a little help narrowing down those 102,402 words to a group worth your time to review. In this command, we’re looking for words that start with the letters “revi”.
+
+[[Get regularly scheduled insights by signing up for Network World newsletters.]][1]
+
+```
+$ grep ^reviv /usr/share/dict/words
+revival
+revival's
+revivalist
+revivalist's
+revivalists
+revivals
+revive
+revived
+revives
+revivification
+revivification's
+revivified
+revivifies
+revivify
+revivifying
+reviving
+```
+
+That’s sixteen words that start with the string “revi”. The **^** character represents the beginning of the word and, as you might have suspected, each word in the file is on a line by itself.
+
+A good number of the words in the **/usr/share/dict/words** file are names. If you want to find words regardless of whether they're capitalized, add the **-i** (ignore case) option to your **grep** command.
+
+```
+$ grep -i ^wool /usr/share/dict/words
+Woolf
+Woolf's
+Woolite
+Woolite's
+Woolongong
+Woolongong's
+Woolworth
+Woolworth's
+wool
+...
+```
+
+You can also look for words that end in or contain a certain string of letters. In this next command, we look for words that contain the string “nativ” at any location.
+
+```
+$ grep 'nativ' /usr/share/dict/words
+alternative
+alternative's
+alternatively
+alternatives
+imaginative
+imaginatively
+native
+native's
+natives
+nativities
+nativity
+nativity's
+nominative
+nominative's
+nominatives
+unimaginative
+```
+
+In this next command, we look for words that end in “emblance”, the **$** character representing the end of the line. Only two words in the **words** file fit the bill.
+
+[][2]
+
+```
+$ grep 'emblance$' /usr/share/dict/words
+resemblance
+semblance
+```
+
+If we, for some reason, want to find words with exactly 21 letters, we could use this command:
+
+```
+$ grep '^.....................$' /usr/share/dict/words
+counterintelligence's
+electroencephalograms
+electroencephalograph
+```
+
+On the other hand, making sure we've typed the correct number of dots can be tedious. This next command is little easier to manage:
+
+```
+$ grep -E '^[[:alpha:]]{21}$' /usr/share/dict/words
+electroencephalograms
+electroencephalograph
+```
+
+This command does the same thing:
+
+```
+$ grep -E '^\w{21}$' /usr/share/dict/words
+electroencephalograms
+electroencephalograph
+```
+
+The one important difference between these commands is that the one with the dots matches any string of 21 characters. The two specifying "alpha" or "\w" only match letters, so they find only two matching words.
+
+Now let’s look for words that contain 20 letters (or more) in a row.
+
+```
+$ grep -E '(\w{20})' /usr/share/dict/words
+Andrianampoinimerina
+Andrianampoinimerina's
+counterrevolutionaries
+counterrevolutionary
+counterrevolutionary's
+electroencephalogram
+electroencephalogram's
+electroencephalograms
+electroencephalograph
+electroencephalograph's
+electroencephalographs
+uncharacteristically
+```
+
+That command returns words with apostrophes because they contain 20 letters in a row before they get to that point.
+
+Next, we’ll check out words with 21 or more characters. The 1 and 20 in combination with the **v** (invert) option in this command cause **grep** to skip over words with anywhere from 1 to 20 characters.
+
+```
+$ grep -vwE '\w{1,20}' /usr/share/dict/words
+counterrevolutionaries
+electroencephalograms
+electroencephalograph
+electroencephalographs
+```
+
+In this next command, we look for words that start with “ex” and have four additional letters.
+
+```
+$ grep '^ex.\{4\}$' /usr/share/dict/words
+exacts
+exalts
+exam's
+exceed
+excels
+except
+excess
+excise
+excite
+excuse
+…
+```
+
+In case you're curious, the **words** file on this system contains 43 such words:
+
+```
+$ grep '^ex.\{4\}$' /usr/share/dict/words | wc -l
+43
+```
+
+To get help with spelling, you should try **aspell**. It can help you with individual words or run a spell check scan through an entire text file. In this first example, we ask **aspell** to help with a single word. It finds the word we’re after along with a couple other possibilities.
+
+### Checking a word
+
+```
+$ aspell -a
+@(#) International Ispell Version 3.1.20 (but really Aspell 0.60.7)
+prolifferate <== entered word
+& prolifferate 3 0: proliferate, proliferated, proliferates <== replacement options
+```
+
+If **aspell** doesn’t provide a list of words, that means that the spelling you offered was correct. Here's an example:
+
+```
+$ aspell -a
+@(#) International Ispell Version 3.1.20 (but really Aspell 0.60.7)
+proliferate <== entered text
+* <== no suggestions
+```
+
+Typing **^C** (control-c) exits **aspell**.
+
+### Checking a file
+
+When checking a file with **aspell**, you get suggestions for each misspelled word. When **aspell** spots typos, it highlights the misspelled words one at a time and gives you a chance to choose from a list of properly spelled words that are similar enough to the misspelled words to be good candidates for replacing them.
+
+To start checking a file, type **aspell -c** followed by the file name.
+
+```
+$ aspell -c thesis
+```
+
+You'll see something like this:
+
+```
+This thesis focusses on …
+
+1) focuses 6) Fosse's
+2) focused 7) flosses
+3) cusses 8) courses
+4) fusses 9) focus
+5) focus's 0) fuses
+i) Ignore I) Ignore all
+r) Replace R) Replace all
+a) Add l) Add Lower
+b) Abort x) Exit
+```
+
+Make your selection by pressing the key listed next to the word you want (1, 2, etc.) and **aspell** will replace the misspelled word in the file and move on to the next one if there are others. Notice that you also have options to replace the word by typing another one. Press "x" when you're done.
+
+### Help with crossword puzzles
+
+If you’re working on a crossword puzzle and need to find a five-letter word that starts with a “d” and has a “u” as its fourth letter, you can use a command like this:
+
+```
+$ grep -i '^d..u.$' /usr/share/dict/words
+datum
+debug
+debut
+demur
+donut
+```
+
+### Help with word scrambles
+
+If you’re working on a puzzle that requires you to de-scramble the letters in a string until you've found a proper word, you can offer the list of letters to grep like this example in which **grep** turns the letters "yxusonlia" into the word “anxiously”.
+
+```
+$ grep -P '^(?:([yxusonlia])(?!.*?\1)){9}$' /usr/share/dict/words
+anxiously
+```
+
+Linux’s word skills are impressive and sometimes even fun. Whether you're hoping to find words you can't quite call to mind or get a little help cheating on word puzzles, Linux offers some clever options.
+
+Join the Network World communities on [Facebook][3] and [LinkedIn][4] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3539011/how-to-takke-advantage-of-linuxs-extensive-vocabulary.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://www.networkworld.com/newsletters/signup.html
+[2]: https://www.networkworld.com/blog/itaas-and-the-corporate-storage-technology/?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE22140&utm_content=sidebar (ITAAS and Corporate Storage Strategy)
+[3]: https://www.facebook.com/NetworkWorld/
+[4]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200423 4 open source chat applications you should use right now.md b/sources/tech/20200423 4 open source chat applications you should use right now.md
new file mode 100644
index 0000000000..25aa100c53
--- /dev/null
+++ b/sources/tech/20200423 4 open source chat applications you should use right now.md
@@ -0,0 +1,139 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (4 open source chat applications you should use right now)
+[#]: via: (https://opensource.com/article/20/4/open-source-chat)
+[#]: author: (Sudeshna Sur https://opensource.com/users/sudeshna-sur)
+
+4 open source chat applications you should use right now
+======
+Collaborating remotely is an essential capability now, making open
+source real-time chat an essential piece of your toolbox.
+![Chat bubbles][1]
+
+The first thing we usually do after waking up in the morning is to check our cellphone to see if there are important messages from our colleagues and friends. Whether or not it's a good idea, this behavior has become part of our daily lifestyle.
+
+> _"Man is a rational animal. He can think up a reason for anything he wants to believe."_
+> _– Anatole France_
+
+No matter the soundness of the reason, we all have a suite of communication tools—email, phone calls, web-conferencing tools, or social networking—we use on a daily basis. Even before COVID-19, working from home already made these communication tools an essential part of our world. And as the pandemic has made working from home the new normal, we're facing unprecedented changes to how we communicate, which makes these tools not merely essential but now required.
+
+### Why chat?
+
+When working remotely as a part of a globally distributed team, we must have a collaborative environment. Chat applications play a vital role in helping us stay connected. In contrast to email, chat applications provide fast, real-time communications with colleagues around the globe.
+
+There are a lot of factors involved in choosing a chat application. To help you pick the right one for you, in this article, I'll explore four open source chat applications and one open source video-communication tool (for when you need to be "face-to-face" with your colleagues), then outline some of the features you should look for in an effective communication application.
+
+### 4 open source chat apps
+
+#### Rocket.Chat
+
+![Rocket.Chat][2]
+
+[Rocket.Chat][3] is a comprehensive communication platform that classifies channels as public (open to anyone who joins) or private (invitation-only) rooms. You can also send direct messages to people who are logged in; share documents, links, photos, videos, and GIFs; make video calls; and send audio messages without leaving the platform.
+
+Rocket.Chat is free and open source, but what makes it unique is its self-hosted chat system. You can download it onto your server, whether it's an on-premises server or a virtual private server on a public cloud.
+
+Rocket.Chat is completely free, and its [source code][4] is available on GitHub. Many open source projects use Rocket.Chat as their official communication platform. It is constantly evolving with new features and improvements.
+
+The things I like the most about Rocket.Chat are its ability to be customized according to user requirements and that it uses machine learning to do automatic, real-time message translation between users. You can also download Rocket.Chat for your mobile device and use it on the go.
+
+#### IRC
+
+![IRC on WeeChat 0.3.5][5]
+
+[Internet Relay Chat (IRC)][6] is a real-time, text-based form of communication. Although it's one of the oldest forms of electronic communication, it remains popular among many well-known software projects.
+
+IRC channels are discrete chat rooms. It allows you to have conversations with multiple people in an open channel or chat with someone privately one-on-one. If a channel name starts with a #, you can assume it to be official, whereas chat rooms that begin with ## are unofficial and usually casual.
+
+[Getting started with IRC][7] is easy. Your IRC handle or nickname is what allows people to find you, so it must be unique. But your choice of IRC client is completely your decision. If you want a more feature-rich application than a standard IRC client, you can connect to IRC with [Riot.im][8].
+
+Given its age, why should you still be on IRC? For one reason, it remains the home for many of the free and open source projects we depend on. If you want to participate in open source software and communities, IRC is the option to get started.
+
+#### Zulip
+
+![Zulip][9]
+
+[Zulip][10] is a popular group-chat application that follows the topic-based threading model. In Zulip, you subscribe to streams, just like in IRC channels or Rocket.Chat. But each Zulip stream opens a topic that is unique, which helps you track conversations later, thus making it more organized.
+
+Like other platforms, it supports emojis, inline images, video, and tweet previews. It also supports LaTeX for sharing math formulas or equations and Markdown and syntax highlighting for sharing code.
+
+Zulip is cross-platform and offers APIs for building your own integrations. Something I especially like about Zulip is its integration feature with GitHub: if I'm working on an issue, I can use Zulip's marker to link back to the pull request ID.
+
+Zulip is open source (you can access its [source code][11] on GitHub) and free to use, but it has paid offerings for on-premises support, [LDAP][12] integration, and more storage.
+
+#### Let's Chat
+
+![Let's Chat][13]
+
+[Let's Chat][14] is a self-hosted chat solution for small teams. It runs on Node.js and MongoDB and can be deployed to local servers or hosted services with a few clicks. It's free and open source, with the [source code][15] available on GitHub.
+
+What differentiates Let's Chat from other open source chat tools is its enterprise features: it supports LDAP and [Kerberos][16] authentication. It also has all the features a new user would want: you can search message history in the archives and tag people with mentions like @username.
+
+What I like about Let's Chat is that it has private and password-protected rooms, image embeds, GIPHY support, and code pasting. It is constantly evolving and adding more features to its bucket.
+
+### Bonus: Open source video chat with Jitsi
+
+![Jitsi][17]
+
+Sometimes text chat isn't enough, and you need to talk to someone face-to-face. In times like these, when in-person meetings aren't an option, video chat is the best alternative. [Jitsi][18] is a complete, open source, multi-platform, and WebRTC-compliant videoconferencing tool.
+
+Jitsi began with Jitsi Desktop and has evolved into multiple [projects][19], including Jitsi Meet, Jitsi Videobridge, jibri, and libjitsi, with [source code][20] published for each on GitHub.
+
+Jitsi is secure and scalable and supports advanced video-routing concepts such as simulcast and bandwidth estimation, as well as typical capabilities like audio, recording, screen-sharing, and dial-in features. You can set a password to secure your video-chat room and protect it against intruders, and it also supports live-streaming over YouTube. You can also build your own Jitsi server and host it on-premises or on a virtual private server, such as a Digital Ocean Droplet.
+
+What I like most about Jitsi is that it is free and frictionless; anyone can start a meeting in no time by visiting [meet.jit.si][21], and users are good to go with no need for registration or installation. (However, registration gives you calendar integrations.) This low-barrier-to-entry alternative to popular videoconferencing services is helping Jitsi's popularity spread rapidly.
+
+### Tips for choosing a chat application
+
+The variety of open source chat applications can make it hard to pick one. The following are some general guidelines for choosing a chat app.
+
+ * Tools that have an interactive interface and simple navigation are ideal.
+ * It's better to look for a tool that has great features and allows people to use it in various ways.
+ * Integrations with tools you use can play an important role in your decision. Some tools have great and seamless integrations with GitHub, GitLab, and certain applications, which is a useful feature.
+ * It's convenient to use tools that have a pathway to hosting on cloud-based services.
+ * The security of the chat service should be taken into account. The ability to host services on a private server is necessary for many organizations and individuals.
+ * It's best to select communication tools that have rich privacy settings and allow for both private and public chat rooms.
+
+
+
+Since people are more dependent than ever on online services, it is smart to have a backup communication platform available. For example, if a project is using Rocket.Chat, it should also have the option to hop into IRC, if necessary. Since these services are continuously updating, you may find yourself connected to multiple channels, and this is where integration becomes so valuable.
+
+Of the different open source chat services available, which ones do you like and use? How do these tools help you work remotely? Please share your thoughts in the comments.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/open-source-chat
+
+作者:[Sudeshna Sur][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sudeshna-sur
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/talk_chat_communication_team.png?itok=CYfZ_gE7 (Chat bubbles)
+[2]: https://opensource.com/sites/default/files/uploads/rocketchat.png (Rocket.Chat)
+[3]: https://rocket.chat/
+[4]: https://github.com/RocketChat/Rocket.Chat
+[5]: https://opensource.com/sites/default/files/uploads/irc.png (IRC on WeeChat 0.3.5)
+[6]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
+[7]: https://opensource.com/article/16/6/getting-started-irc
+[8]: https://opensource.com/article/17/5/introducing-riot-IRC
+[9]: https://opensource.com/sites/default/files/uploads/zulip.png (Zulip)
+[10]: https://zulipchat.com/
+[11]: https://github.com/zulip/zulip
+[12]: https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol
+[13]: https://opensource.com/sites/default/files/uploads/lets-chat.png (Let's Chat)
+[14]: https://sdelements.github.io/lets-chat/
+[15]: https://github.com/sdelements/lets-chat
+[16]: https://en.wikipedia.org/wiki/Kerberos_(protocol)
+[17]: https://opensource.com/sites/default/files/uploads/jitsi_0_0.jpg (Jitsi)
+[18]: https://jitsi.org/
+[19]: https://jitsi.org/projects/
+[20]: https://github.com/jitsi
+[21]: http://meet.jit.si
diff --git a/sources/tech/20200426 6 tips for securing your WordPress website.md b/sources/tech/20200426 6 tips for securing your WordPress website.md
new file mode 100644
index 0000000000..757ff42d30
--- /dev/null
+++ b/sources/tech/20200426 6 tips for securing your WordPress website.md
@@ -0,0 +1,175 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (6 tips for securing your WordPress website)
+[#]: via: (https://opensource.com/article/20/4/wordpress-security)
+[#]: author: (Lucy Carney https://opensource.com/users/lucy-carney)
+
+6 tips for securing your WordPress website
+======
+Even beginners can—and should—take these steps to protect their
+WordPress sites against cyberattacks.
+![A lock on the side of a building][1]
+
+Already powering over 30% of the internet, WordPress is the fastest-growing content management system (CMS) in the world—and it's not hard to see why. With tons of customization available through coding and plugins, top-notch SEO, and a supreme reputation for blogging, WordPress has certainly earned its popularity.
+
+However, with popularity comes other, less appealing attention. WordPress is a common target for intruders, malware, and cyberattacks—in fact, WordPress accounted for around [90% of hacked CMS platforms][2] in 2019.
+
+Whether you're a first-time WordPress user or an experienced developer, there are important steps you can take to protect your WordPress website. The following six key tips will get you started.
+
+### 1\. Choose reliable hosting
+
+Hosting is the unseen foundation of all websites—without it, you can't publish your site online. But hosting does much more than simply host your site. It's also responsible for site speed, performance, and security.
+
+The first thing to do is to check if a host includes SSL security in its plans.
+
+SSL is an essential security feature for all websites, whether you're running a small blog or a large online store. You'll need a more [advanced SSL certificate][3] if you're accepting payments, but for most sites, the basic free SSL should be fine.
+
+Other security features to look out for include:
+
+ * Frequent, automatic offsite backups
+ * Malware and antivirus scanning and removal
+ * Distributed denial of service (DDoS) protection
+ * Real-time network monitoring
+ * Advanced firewall protection
+
+
+
+In addition to these digital security features, it's worth thinking about your hosting provider's _physical_ security measures as well. These include limiting access to data centers with security guards, CCTV, and two-factor or biometric authentication.
+
+### 2\. Use security plugins
+
+One of the best—and easiest—ways of protecting your website's security is to install a security plugin, such as [Sucuri][4], which is an open source, GPLv2 licensed project. Security plugins are vitally important because they automate security, which means you can focus on running your site rather than committing all your time to fighting off online threats.
+
+These plugins detect and block malicious attacks and alert you about any issues that require your attention. In short, they constantly work in the background to protect your site, meaning you don't have to stay awake 24/7 to fight off hackers, bugs, and other digital nasties.
+
+A good security plugin will provide all the essential security features you need for free, but some advanced features require a paid subscription. For example, you'll need to pay if you want to unlock [Sucuri's website firewall][5]. Enabling a web application firewall (WAF) blocks common threats and adds an extra layer of security to your site, so it's a good idea to look for this feature when choosing a security plugin.
+
+### 3\. Choose trustworthy plugins and themes
+
+The joy of WordPress is that it is open source, so anyone and everyone can pitch in with themes and plugins that they've developed. This can also pose problems when it comes to picking a high-quality theme or plugin.
+
+It serves to be cautious when picking a free theme or plugin, as some are poorly designed—or worse, may hide malicious code.
+
+To avoid this, always source free themes and plugins from reputable sources, such as the WordPress library. Always read reviews and research the developer to see if they've built any other programs.
+
+Outdated or poorly designed themes and plugins can leave "backdoors" open for attackers or bugs to get into your site, which is why it pays to be careful in your choices. However, you should also be wary of nulled or cracked themes. These are premium themes that have been compromised by hackers and are for sale illegally. You might buy a nulled theme believing that it's all above-board—only to have your site damaged by hidden malicious code.
+
+To avoid nulled themes, don't get drawn in by discounted prices, and always stick to reputable stores, such as the official [WordPress directory][6]. If you're looking elsewhere, stick to large and trusted stores, such as [Themify][7], a theme and plugin store that has been running since 2010. Themify ensures all its WordPress themes pass the [Google Mobile-Friendly][8] test and are open source under the [GNU General Public License][9].
+
+### 4\. Run regular updates
+
+It's a fundamental WordPress rule: _always keep your site up to date._ However, it's a rule not everyone sticks to—in fact, only [43% of WordPress sites][10] are running the latest version.
+
+The problem is that when your site becomes outdated, it becomes susceptible to glitches, bugs, intrusions, and crashes because it falls behind on security and performance fixes. Outdated sites can't fix bugs the same way as updated sites can, and attackers can tell which sites are outdated. This means they can search for the most vulnerable sites and attack accordingly.
+
+This is why you should always run your site on the latest version of WordPress. And in order to keep your security at its strongest, you must update your plugins and themes as well as your core WordPress software.
+
+If you choose a managed WordPress hosting plan, you might find that your provider will check and run updates for you—be clear whether your host offers software _and_ plugin updates. If not, you can install an open source plugin manager, such as the GPLv2-licensed [Easy Updates Manager plugin][11], as an alternative.
+
+### 5\. Strengthen your logins
+
+Aside from creating a secure WordPress website through carefully choosing your theme and installing security plugins, you also need to safeguard against unauthorized access through logins.
+
+#### Password protection
+
+The first and simplest way to strengthen your login security is to change your password—especially if you're using an [easily guessed phrase][12] such as "123456" or "qwerty."
+
+Instead, try to use a long passphrase rather than a password, as they are harder to crack. The best way is to use a series of unrelated words strung together that you find easy to remember.
+
+Here are some other tips:
+
+ * Never reuse passwords
+ * Don't include obvious words such as family members' names or your favorite football team
+ * Never share your login details with anyone
+ * Include capitals and numbers to add complexity to your passphrase
+ * Don't write down or store your login details anywhere
+ * Use a [password manager][13]
+
+
+
+#### Change your login URL
+
+It's a good idea to change your default login web address from the standard format: yourdomain.com/wp-admin. This is because hackers know this is the default URL, so you risk brute-force attacks by not changing it.
+
+To avoid this, change the URL to something different. Use an open source plugin such as the GPLv2-licensed [WPS Hide Login][14] for safe, quick, and easy customization.
+
+#### Apply two-factor authentication
+
+For extra protection against unauthorized logins and brute-force attacks, you should add two-factor authentication. This means that even if someone _does_ get access to your login details, they'll need a code that's sent directly to your phone to gain access to your WordPress site's admin.
+
+Adding two-factor authentication is pretty easy. Simply install yet another plugin—this time, search the WordPress Plugin Directory for "two-factor authentication," and select the plugin you want. One option is [Two Factor][15], a popular GPLv2 licensed project that has over 10,000 active installations.
+
+#### Limit login attempts
+
+WordPress tries to be helpful by letting you guess your login details as many times as you like. However, this is also helpful to hackers trying to gain unauthorized access to your WordPress site to release malicious code.
+
+To combat brute-force attacks, install a plugin that limits login attempts and set how many guesses you want to allow.
+
+### 6\. Disable file editing
+
+This isn't such a beginner-friendly step, so don't attempt it unless you're a confident coder—and always back up your site first!
+
+That said, disabling file editing _is_ an important measure if you're really serious about protecting your WordPress website. If you don't hide your files, it means anyone can edit your theme and plugin code straight from the admin area—which is dangerous if an intruder gets in.
+
+To deny unauthorized access, go to your **wp-config.php** file and enter:
+
+
+```
+<Files wp-config.php>
+order allow,deny
+deny from all
+</Files>
+```
+
+Or, to remove the theme and plugin editing options from your WordPress admin area completely, edit your **wp-config.php** file by adding:
+
+
+```
+`define( 'DISALLOW_FILE_EDIT', true );`
+```
+
+Once you've saved and reloaded the file, the plugin and theme editors will disappear from your menus within the WordPress admin area, stopping anyone from editing your theme or plugin code—including you**.** Should you need to restore access to your theme and plugin code, just delete the code you added to your **wp-config.php** file when you disabled editing.
+
+Whether you block unauthorized access or totally disable file editing, it's important to take action to protect your site's code. Otherwise, it's easy for unwelcome visitors to edit your files and add new code. This means an attacker could use the editor to gather data from your WordPress site or even use your site to launch attacks on others.
+
+For an easier way of hiding your files, you can use a security plugin that will do it for you, such as Sucuri.
+
+### WordPress security recap
+
+WordPress is an excellent open source platform that should be enjoyed by beginners and developers alike without the fear of becoming a victim of an attack. Sadly, these threats aren't going anywhere anytime soon, so it's vital to stay on top of your site's security.
+
+Using the measures outlined above, you can create a stronger, more secure level of protection for your WordPress site and ensure a much more enjoyable experience for yourself.
+
+Staying secure is an ongoing commitment rather than a one-time checklist, so be sure to revisit these steps regularly and stay alert when building and using your CMS.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/wordpress-security
+
+作者:[Lucy Carney][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/lucy-carney
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUSINESS_3reasons.png?itok=k6F3-BqA (A lock on the side of a building)
+[2]: https://cyberforces.com/en/wordpress-most-hacked-cms
+[3]: https://opensource.com/article/19/11/internet-security-tls-ssl-certificate-authority
+[4]: https://wordpress.org/plugins/sucuri-scanner/
+[5]: https://sucuri.net/website-firewall/
+[6]: https://wordpress.org/themes/
+[7]: https://themify.me/
+[8]: https://developers.google.com/search/mobile-sites/
+[9]: http://www.gnu.org/licenses/gpl.html
+[10]: https://wordpress.org/about/stats/
+[11]: https://wordpress.org/plugins/stops-core-theme-and-plugin-updates/
+[12]: https://www.forbes.com/sites/kateoflahertyuk/2019/04/21/these-are-the-worlds-most-hacked-passwords-is-yours-on-the-list/#4f157c2f289c
+[13]: https://opensource.com/article/16/12/password-managers
+[14]: https://wordpress.org/plugins/wps-hide-login/
+[15]: https://en-gb.wordpress.org/plugins/two-factor/
diff --git a/sources/tech/20200427 New zine- How Containers Work.md b/sources/tech/20200427 New zine- How Containers Work.md
new file mode 100644
index 0000000000..fa2198ebbc
--- /dev/null
+++ b/sources/tech/20200427 New zine- How Containers Work.md
@@ -0,0 +1,121 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (New zine: How Containers Work!)
+[#]: via: (https://jvns.ca/blog/2020/04/27/new-zine-how-containers-work/)
+[#]: author: (Julia Evans https://jvns.ca/)
+
+New zine: How Containers Work!
+======
+
+On Friday I published a new zine: “How Containers Work!”. I also launched a fun redesign of [wizardzines.com][1].
+
+You can get it for $12 at . If you buy it, you’ll get a PDF that you can either print out or read on your computer. Or you can get a pack of [all 8 zines][2] so far.
+
+Here’s the cover and table of contents:
+
+[![][3]][4]
+
+### why containers?
+
+I’ve spent a lot of time [figuring][5] [out][6] [how to][7] [run][8] [things][9] [in][10] [containers][11] over the last 3-4 years. And at the beginning I was really confused! I knew a bunch of things about Linux, and containers didn’t seem to fit in with anything I thought I knew (“is it a process? what’s a network namespace? what’s happening?“). The whole thing seemed really weird.
+
+It turns out that containers ARE actually pretty weird. They’re not just one thing, they’re what you get when you glue together 6 different features that were mostly designed to work together but have a bunch of confusing edge cases.
+
+As usual, the thing that helped me the most in my container adventures is a good understanding of the **fundamentals** – what exactly is actually happening on my server when I run a container?
+
+So that’s what this zine is about – cgroups, namespaces, pivot_root, seccomp-bpf, and all the other Linux kernel features that make containers work.
+
+Once I understood those ideas, it got a **lot** easier to debug when my containers were doing surprising things in production. I learned a couple of interesting and strange things about containers while writing this zine too – I’ll probably write a blog post about one of them later this week.
+
+### containers aren’t magic
+
+This picture (page 6 of the zine) shows you how to run a fish container image with only 15 lines of bash. This is heavily inspired by [bocker][12], which “implements” Docker in about 100 lines of bash.
+
+
+
+The main things I see missing from that script compared to what Docker actually does when running a container (other than using an actual container image and not just a tarball) are:
+
+ * it doesn’t drop any capabilities – the container is still running as root and has full root privileges (just in a different mount + PID namespace)
+ * it doesn’t block any system calls with seccomp-bpf
+
+
+
+### container command line tools
+
+The zine also goes over a bunch of command line tools & files that you can use to inspect running containers or play with Linux container features. Here’s a list:
+
+ * `mount -t overlay` (create and view overlay filesystems)
+ * `unshare` (create namespaces)
+ * `nsenter` (use an existing namespace)
+ * `getpcaps` (get a process’s capabilities)
+ * `capsh` (drop or add capabilities, etc)
+ * `cgcreate` (create a cgroup)
+ * `cgexec` (run a command in an existing cgroup)
+ * `chroot` (change root directory. not actually what containers use but interesting to play with anyway)
+ * `/sys/fs/cgroups` (for information about cgroups, like `memory.usage_in_bytes`)
+ * `/proc/PID/ns` (all a process’s namespaces)
+ * `lsns` (another way to view namespaces)
+
+
+
+I also made a short youtube video a while back called [ways to spy on a Docker container][13] that demos some of these command line tools.
+
+### container runtime agnostic
+
+I tried to keep this zine pretty container-runtime-agnostic – I mention Docker a couple of times because it’s so widely used, but it’s about the Linux kernel features that make containers work in general, not Docker or LXC or systemd-nspawn or Kubernetes or whatever. If you understand the fundamentals you can figure all those things out!
+
+### we redesigned wizardzines.com!
+
+On Friday I also launched a redesign of [wizardzines.com][1]! [Melody Starling][14] (who is amazing) did the design. I think now it’s better organized but the tiny touch that I’m most delighted by is that now the zines jump with joy when you hover over them.
+
+One cool thing about working with a designer is – they don’t just make things _look_ better, they help _organize_ the information better so the website makes more sense and it’s easier to find things! This is probably obvious to anyone who knows anything about design but I haven’t worked with designers very much (or maybe ever?) so it was really cool to see.
+
+One tiny example of this: Melody had the idea of adding a tiny FAQ on the landing page for each zine, where I can put the answers to all the questions people always ask! Here’s what the little FAQ box looks like:
+
+[![][15]][4]
+
+I probably want to edit those questions & answers over time but it’s SO NICE to have somewhere to put them.
+
+### what’s next: maybe debugging! or working more on flashcards!
+
+The two projects I’m thinking about the most right now are
+
+ 1. a zine about debugging, which I started last summer and haven’t gotten around to finishing yet
+ 2. a [flashcards project][16] that I’ve been adding to slowly over the last couple of months. I think could become a nice way to explain basic ideas.
+
+
+
+Here’s a link to where to [get the zine][4] again :)
+
+--------------------------------------------------------------------------------
+
+via: https://jvns.ca/blog/2020/04/27/new-zine-how-containers-work/
+
+作者:[Julia Evans][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://jvns.ca/
+[b]: https://github.com/lujun9972
+[1]: https://wizardzines.com
+[2]: https://wizardzines.com/zines/all-the-zines/
+[3]: https://jvns.ca/images/containers-cover.jpg
+[4]: https://wizardzines.com/zines/containers
+[5]: https://stripe.com/en-ca/blog/operating-kubernetes
+[6]: https://jvns.ca/blog/2016/09/15/whats-up-with-containers-docker-and-rkt/
+[7]: https://jvns.ca/blog/2016/10/10/what-even-is-a-container/
+[8]: https://jvns.ca/blog/2016/12/22/container-networking/
+[9]: https://jvns.ca/blog/2016/10/26/running-container-without-docker/
+[10]: https://jvns.ca/blog/2017/02/17/mystery-swap/
+[11]: https://jvns.ca/blog/2016/10/02/a-list-of-container-software/
+[12]: https://github.com/p8952/bocker
+[13]: https://www.youtube.com/watch?v=YCVSdnYzH34&t=1s
+[14]: https://melody.dev
+[15]: https://jvns.ca/images/wizardzines-faq.png
+[16]: https://flashcards.wizardzines.com
diff --git a/sources/tech/20200428 Learn Bash with this book of puzzles.md b/sources/tech/20200428 Learn Bash with this book of puzzles.md
new file mode 100644
index 0000000000..08a07b93c5
--- /dev/null
+++ b/sources/tech/20200428 Learn Bash with this book of puzzles.md
@@ -0,0 +1,60 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Learn Bash with this book of puzzles)
+[#]: via: (https://opensource.com/article/20/4/bash-it-out-book)
+[#]: author: (Carlos Aguayo https://opensource.com/users/hwmaster1)
+
+Learn Bash with this book of puzzles
+======
+'Bash it out' covers basic, medium, and advanced Bash scripting using 16
+puzzles.
+![Puzzle pieces coming together to form a computer screen][1]
+
+Computers are both my hobby and my profession. I have about 10 of them scattered around my apartment, all running Linux (including my Macs). Since I enjoy upgrading my computers and my computer skills, when I came across [_Bash it out_][2] by Sylvain Leroux, I jumped on the chance to buy it. I use the command line a lot on Debian Linux, and it seemed like a great opportunity to expand my Bash knowledge. I smiled when the author explained in the preface that he uses Debian Linux, which is one of my two favorite distributions.
+
+Bash lets you automate tasks, so it's a labor-saving, interesting, and useful tool. Before reading the book, I already had a fair amount of experience with Bash on Unix and Linux. I'm not an expert, in part because the scripting language is so extensive and powerful. I first became intrigued with Bash when I saw it on the welcome screen of [EndeavourOS][3], an Arch-based Linux distribution.
+
+The following screenshots show some options from EndeavourOS. Beleieve it or not, these panels just point to Bash scripts, each of which accomplish some relatively complex tasks. And because it's all open source, I can modify any of these scripts if I want.
+
+![EndeavourOS after install][4]
+
+![EndeavourOS install apps][5]
+
+### Always something to learn
+
+My impressions of this book are very favorable. It's not long, but it is well-thought-out. The author has very extensive knowledge of Bash and an uncanny ability to explain how to use it. The book covers basic, medium, and advanced Bash scripting using 16 puzzles, which he calls "challenges." This taught me to see Bash scripting as a programming puzzle to solve, which makes it more interesting to play with.
+
+An exciting aspect of Bash is that it's deeply integrated with the Linux system. While part of its power lies in its syntax, it's also powerful because it has access to so much. You can script repetitive tasks, or tasks that are easy but you're just tired of performing manually. Nothing is too great or too small, and _Bash it out_ helps you understand both what you can do, and how to achieve it.
+
+This review would not be complete if I didn't mention David Both's free resource [_A sysadmin's guide to Bash scripting_][6] on Opensource.com. This 17-page PDF guide is different from _Bash it out_, but together they make a winning combination for anyone who wants to learn about it.
+
+I am not a computer programmer, but _Bash it out_ has increased my desire to get into more advanced levels of Bash scripting—I might inadvertently end up as a computer programmer without planning to.
+
+One reason I love Linux is because of how powerful and versatile the operating system is. However much I know about Linux, there is always something new to learn that makes me appreciate Linux even more.
+
+In a competitive and ever-changing job market, it behooves all of us to continuously update our skills. This book helped me learn Bash in a very hands-on way. It almost felt as if the author was in the same room with me, patiently guiding me in my learning.
+
+The author, Leroux, has an uncanny ability to engage readers. This is a rare gift that I think is even more valuable than his technical expertise. In fact, I am writing this book review to thank the author for anticipating my own learning needs; although we have never met, I have benefited in real ways from his gifts.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/bash-it-out-book
+
+作者:[Carlos Aguayo][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/hwmaster1
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/puzzle_computer_solve_fix_tool.png?itok=U0pH1uwj (Puzzle pieces coming together to form a computer screen)
+[2]: https://www.amazon.com/Bash-Out-Strengthen-challenges-difficulties/dp/1521773262/
+[3]: https://endeavouros.com/
+[4]: https://opensource.com/sites/default/files/uploads/endeavouros-welcome.png (EndeavourOS after install)
+[5]: https://opensource.com/sites/default/files/uploads/endeavouros-install-apps.png (EndeavourOS install apps)
+[6]: https://opensource.com/downloads/bash-scripting-ebook
diff --git a/sources/tech/20200429 Open source live streaming with Open Broadcaster Software.md b/sources/tech/20200429 Open source live streaming with Open Broadcaster Software.md
new file mode 100644
index 0000000000..748786de77
--- /dev/null
+++ b/sources/tech/20200429 Open source live streaming with Open Broadcaster Software.md
@@ -0,0 +1,137 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Open source live streaming with Open Broadcaster Software)
+[#]: via: (https://opensource.com/article/20/4/open-source-live-stream)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Open source live streaming with Open Broadcaster Software
+======
+If you have something to say, a skill to teach, or just something fun to
+share, broadcast it to the world with OBS.
+![An old-fashioned video camera][1]
+
+If you have a talent you want to share with the world, whether it's making your favorite sourdough bread or speedrunning through a level of your favorite video game, live streaming is the modern show-and-tell. It's a powerful way to tell the world about your hobby through a medium once reserved for exclusive and expensive TV studios. Not only is the medium available to anyone with a relatively good internet connection, but the most popular software to make it happen is open source.
+
+[OBS][2] (Open Broadcaster Software) is a cross-platform application that serves as a control center for your live stream. A _stream_, strictly speaking, means _progressive and coherent data_. The data in a stream can be audio, video, graphics, text, or anything else you can represent as digital data. OBS is programmed to accept data as input, combine streams together (technically referred to as _mixing_) into one product, and then broadcast it.
+
+![OBS flowchart][3]
+
+A _broadcast_ is data that can be received by some target. If you're live streaming, your primary target is a streaming service that can host your stream, so other people can find it in a web browser or media player. A live stream is a live event, so people have to "tune in" to your stream when it's happening, or else they miss it. However, you can also target your own hard drive so you can record a presentation and then post it on the internet later for people to watch at their leisure.
+
+### Installing OBS
+
+To install OBS on Windows or macOS, download an installer package from [OBS's website][2].
+
+To install OBS on Linux, either install it with your package manager (such as **dnf**, **zypper**, or **apt**) or [install it as a Flatpak][4].
+
+### Join a streaming service
+
+In order to live stream, you must have a stream broker. That is, you need a central location on the internet for your stream to be delivered, so your viewers can get to what you're broadcasting. There are a few popular streaming services online, like YouTube and Twitch. You can also [set up your own video streaming server][5] using open source software.
+
+Regardless of which option you choose, before you begin streaming, you must have a destination for your stream. If you do use a streaming service, you must obtain a _streaming key_. A streaming key is a hash value (it usually looks something like **2ae2fad4e33c3a89c21**) that is private and unique to you. You use this key to authenticate yourself through your streaming software. Without it, the streaming service can't know you are who you say you are and won't let you broadcast over your user account.
+
+* * *
+
+* * *
+
+* * *
+
+**![Streaming key][6]**
+
+ * In Twitch, your **Primary Stream Key** is available in the **Channel** panel of your **Creator Dashboard**.
+ * On YouTube, you must enable live streaming by verifying your account. Once you've done that, your **Stream Key** is in the **Other Features** menu option of your **Channel Dashboard**.
+ * If you're using your own server, there's no maze-like GUI to navigate. You just [create your own streaming key][7].
+
+
+
+### Enter your streaming key
+
+Once you have a streaming key, launch OBS and go to the **File** > **Settings** menu.
+
+In the **Settings** window, click on the **Stream** category in the left column. Set the **Service** to your stream service (Custom, Twitch, YouTube, etc.), and enter your stream key. Click the **OK** button in the bottom right to save your changes.
+
+### Create sources
+
+In OBS, _sources_ represent any input signal you want to stream. By default, sources are listed at the bottom of the OBS window.
+
+![OBS sources][8]
+
+This might be a webcam, a microphone, an audio stream (such as the sound of a video game you're playing), a screen capture of your computer (a "screencast"), a slideshow you want to present, an image, and so on. Before you start streaming, you should define all the sources you plan on using for your stream. This means you have to do a little pre-production and consider what you anticipate for your show. Any camera you have set up must be defined as a source in OBS. Any extra media you plan on cutting to during your show must be defined as a source. Any sound effects or background music must be defined as a source.
+
+Not all sources "happen" at once. By adding media to your **Sources** panel in OBS, you're just assembling the raw components for your stream. Once you make devices and data available to OBS, you can create your **Scenes**.
+
+#### Setting up audio
+
+Computers have seemingly dozens of ways to route audio. Here's the workflow to follow when setting up sound for your stream:
+
+ 1. Check your cables: verify that your microphone is plugged in.
+ 2. Go to your computer's sound control panel and set the input to whatever microphone you want OBS to treat as the main microphone. This might be a gaming headset or a boom mic or a desktop podcasting mic or a Bluetooth device or a fancy audio interface with XLR ports. Whatever it is, make sure your computer "hears" your main sound input.
+ 3. In OBS, create a source for your main microphone and name it something obvious (e.g., boom mic, master sound, or mic).
+ 4. Do a test. Make sure OBS "hears" your microphone by referring to the audio-level monitors at the bottom of the OBS window. If it's not responding to the input you believe you've set as input, check your cables, check your computer sound control panel, and check OBS.
+
+
+
+I've seen more people panic over audio sources than any other issue when streaming, and we've _all_ made the same dumb mistakes (several times each, probably!) when attempting to set a microphone for a live stream or videoconference call. Breathe deep, check your cables, check your inputs and outputs, and [get comfortable with audio][9]. It'll pay off in the end.
+
+### Create scenes
+
+A **Scene** in OBS is a screen layout and consists of one or more sources.
+
+![Scenes in OBS][10]
+
+For instance, you might create a scene called **Master shot** that shows you sitting at your desk in front of your computer or at the kitchen counter ready to mix ingredients together. The source could be a webcam mounted on a tripod a meter or two in front of you. Because you want to cut to a detail shot, you might create a second scene called **Close-up**, which uses the computer screen and audio as one input source and your microphone as another source, so you can narrate as you demonstrate what you're doing. If you're doing a baking show, you might want to mount a second webcam above the counter, so you can cut to an overhead shot of ingredients being mixed. Here, your source is a different webcam but probably the same microphone (to avoid making changes in the audio).
+
+A _scene_, in other words, is a lot like a _shot_ in traditional production vernacular, but it can be the combination of many shots. The fun thing about OBS is that you can mix and match a lot of different sources together, so when you're adding a **Scene**, you can resize and position different sources to achieve picture-in-picture, or split-screen, or any other effect you might want. It's common in video game "let's play" streams to have the video game in full-screen, with the player inset in the lower right or left. Or, if you're recording a panel or a multi-player game like D&D you might have several cameras covering several players in a _Brady Bunch_ grid.
+
+The possibilities are endless. During streaming, you can cut from one scene to another as needed. This is intended to be a dynamic system, so you can change scenes depending on what the viewer needs to see at any given moment.
+
+Generally, you want to have some preset scenes before you start to stream. Even if you have a friend willing to do video mixing as you stream, you always want a safe scene to fall back to, so take time beforehand to set up at least a master shot that shows you doing whatever it is you're doing. If all else fails, at least you'll have your main shot you can safely and reliably cut to.
+
+### Transitions
+
+When switching from one scene to another, OBS uses a transition. Once you have more than one scene, you can configure what kind of transition it uses in the **Transitions** panel. Simple transitions are usually best. By default, OBS uses a subtle crossfade, but you can experiment with others as you see fit.
+
+### Go live
+
+To start streaming, do your vocal exercises, find your motivation, and press the **Start Streaming** button.
+
+![Start streaming in OBS][11]
+
+As long as you've set up your streaming service correctly, you're on the air (or on the wires, anyway).
+
+If you're the talent (the person in front of the camera), it might be easiest to have someone control OBS during streaming. But if that's not possible, you can control it yourself as long as you've practiced a little in advance. If you're screencasting, it helps to have a two-monitor setup so you can control OBS without it being on screen.
+
+### Streaming for success
+
+Many of us take streaming for granted now that the internet exists and can broadcast media created by _anyone_. It's a hugely powerful means of communication, and we're all responsible for making the most of it.
+
+If you have something positive to say, a skill to teach, words of encouragement, or just something fun that you want to share, and you feel like you want to broadcast to the world, then take the time to learn OBS. You might not get a million viewers, but independent media is a vital part of [free culture][12]. The world can always use empowering and positive open source voices, and yours may be one of the most important of all.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/open-source-live-stream
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/LIFE_film.png?itok=aElrLLrw (An old-fashioned video camera)
+[2]: http://obsproject.com
+[3]: https://opensource.com/sites/default/files/obs-flowchart.jpg (OBS flowchart)
+[4]: https://flatpak.org/setup
+[5]: https://opensource.com/article/19/1/basic-live-video-streaming-server
+[6]: https://opensource.com/sites/default/files/twitch-key.jpg (Streaming key)
+[7]: https://opensource.com/article/19/1/basic-live-video-streaming-server#obs
+[8]: https://opensource.com/sites/default/files/uploads/obs-sources.jpg (OBS sources)
+[9]: https://opensource.com/article/17/1/linux-plays-sound
+[10]: https://opensource.com/sites/default/files/uploads/obs-scenes.jpg (Scenes in OBS)
+[11]: https://opensource.com/sites/default/files/uploads/obs-stream-start.jpg (Start streaming in OBS)
+[12]: https://opensource.com/article/18/1/creative-commons-real-world
diff --git a/sources/tech/20200430 Edit music recordings with Audacity on Linux.md b/sources/tech/20200430 Edit music recordings with Audacity on Linux.md
new file mode 100644
index 0000000000..be6f68f062
--- /dev/null
+++ b/sources/tech/20200430 Edit music recordings with Audacity on Linux.md
@@ -0,0 +1,161 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Edit music recordings with Audacity on Linux)
+[#]: via: (https://opensource.com/article/20/4/audacity)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Edit music recordings with Audacity on Linux
+======
+How COVID-19 caused me to learn Audacity on the fly and learn to love
+it.
+![Bird singing and music notes][1]
+
+In this strange and difficult time of a global pandemic, we are all called upon to do things differently, to change our routines, and to learn new things.
+
+I have worked from home for many years, so that is nothing new to me. Even though I am allegedly retired, I write articles for Opensource.com and [Enable Sysadmin][2] and books. I also manage my own home network, which is larger than you might think, and my church's network and Linux hosts, and I help a few friends with Linux. All of this keeps me busy doing what I like to do, and all of it is usually well within my comfort zone.
+
+But COVID-19 has changed all of that. And, like many other types of organizations, my church had to move quickly to a new service-delivery paradigm. And that is what churches do—deliver a specific kind of service. As the church sysadmin and with some knowledge of audio recording and editing (back in the '70s, I mixed the sound and was the only roadie for a couple of regional folk-rock groups in Toledo, Ohio), I decided to learn the open source audio recording and editing software [Audacity][3] to help meet this challenge.
+
+This is not a comprehensive how-to article about using Audacity. It is about my experiences getting started with this powerful audio-editing tool, but there should be enough information here to help you get started.
+
+I have learned just what I need to know in order to accomplish my task: combining several separate audio clips into a single MP3 audio file. If you already know Audacity and do things differently or know things that I don't, that is expected. And if you have any suggestions to help me accomplish my task more easily, please share them in the comments.
+
+### The old way
+
+I try not to use the term "normal" now because it is hard to know exactly what that is—if such a state even exists. But our old method of producing recordings for our shut-ins, members who are traveling, and anyone else was to record the sermon portion of our regular, in-person church services and post them on our website.
+
+To do this, I installed a TASCAM SS-R100 solid-state recorder that stores the sermons as MP3 files on a thumb drive. We uploaded the recordings to a special directory of our website so people could download them. The recordings are uploaded using a Bash [program][4] I wrote for the task. _Automate everything!_ I trained a couple of others to perform these tasks using sudo in case I was not available.
+
+This all worked very well. Until it didn't.
+
+### The new way
+
+As soon as the first restrictions on large gatherings occurred, we made some changes. We could still have small gatherings, so four of us met Sunday mornings and recorded an abbreviated service using our in-house recorder and doing the upload the usual way. This worked, but as the crisis deepened and it became more of a risk to meet with even a few people, we had to make more changes.
+
+Like a huge number of other organizations, we realized we each needed to perform our parts of creating services in separate locations from our own homes.
+
+Now, depending upon the structure of the service, I receive several recordings that I need to combine to create the full church service. Our music director records each anthem and interlude using her iPhone and sends me the recordings in the M4A (MPEG-4 audio) format. They each range in length from seconds to five minutes and are up to 3MB in size. Likewise, our rector sends me two to six recordings, also in M4A format, that contains his portion of the service. Sometimes, other musicians in our church send solos or duets recorded with their significant others; these can be in MP3 or M4A formats.
+
+Then, I pull all of this together into a single recording that can be uploaded to our server for people to download. I use Audacity for this because it was available in my repo, and it was easy to get started.
+
+### Getting started with Audacity
+
+I had never used [Audacity][5] before this, so, like many others these days, I needed to learn something new just in time to accomplish what I needed to do. I struggled a bit at first, but it turned out to be fun and very enlightening.
+
+Audacity was easy to install on my Fedora 31 workstation because, as in many distros, it is available from the Fedora repository.
+
+The first time I opened Audacity with the program launcher icon, the application's window was empty with no projects nor tracks present. Audacity projects have an AUP extension, so if you have an existing project, you could click on the file in your favorite file manager and launch Audacity that way.
+
+### Convert M4A to MP3
+
+As installed by Fedora, Audacity does not recognize M4A files. Regardless of how you proceed, you need to install the [LAME][6] MP3 encoder and [FFmpeg][7] import/export library, both of which are available from the Fedora repository and, most likely, any other distro's repository.
+
+There are websites that explain how to configure Audacity to use these tools to import and convert audio files from M4A to other types (such as MP3), but I decided to write a script to do it from the command line. For one reason, using a script is faster than doing a lot of extra clicking in a GUI interface, and for another, the file names need some work, so I already needed a script to rename the files. Many people use non-alphanumeric characters to name files, but I don't like dealing with special keyboard characters from the command line. It's easier to manage files with simple alphanumeric names, so my script removes all non-alphanumeric characters from the file names and then converts the files to MP3 format.
+
+You may choose a different approach, but I like the scripted solution. It is fast, and I only need to run the script once, no matter how many files need to be renamed and converted to MP3.
+
+### Create a new project
+
+You can create a new project whether or not any audio tracks are loaded. I recommend creating the project first, before importing any audio files (aka "clips"). From the Menu bar, select **File > Save Project > Save Project As**. This opens a warning dialog window that says, _"'Save project' is for an Audacity project, not an audio file."_ Click the **OK** button to continue to a standard file-save dialog.
+
+I found that I needed to do this twice. The first time, the warning dialog did not display any buttons, so I had to close the dialog using the window menu or the x icon in the Title bar.
+
+Name the project whatever you like, and Audacity automatically adds the AUP extension. You now have an empty project.
+
+### Add audio files to your project
+
+The first step is to add your audio files to the project. Using the Menu bar, open **File > Import > Audio** and then use the file dialog to select one or more files to import. For my first test project, I loaded all the files at once without sorting the tracks nor aligning the clips in the desired sequence along the timeline. This time, I started by loading the audio files one at a time in the sequence I wanted them from top to bottom. As each file is imported, it is placed into a new track below any existing tracks. The following image shows the files loaded all at one time in the sequence they appear in the working directory.
+
+![Tracks loaded in Audacity][8]
+
+There is a timeline across the top of the window's track area. There is also a scroll bar at the bottom of the window, so you can scroll along the timeline when the tracks extend beyond the width of the Audacity window. There is also a vertical scroll bar if there are more tracks than fit into the window.
+
+Notice the names in the upper-left corner of the waveform section of each track—they are the file names of each track without the extension. These are not there by default, but I find them helpful. To display these names, use the Menu bar to select **Edit > Preferences** and place a check in the **Show Audio Track Name As Overlay** box.
+
+### Order your audio clips
+
+Once you have some files loaded into the Audacity workspace, you can start manipulating them. To order your audio clips, select one and use the **Time-Shift** tool (↔︎) to slide them horizontally along the tracks; continue doing this until all the clips line up end to end in the order you want them. Note that the clip you are moving is book-ended by a pair of vertical alignment lines. When they line up perfectly, the end lines of the two aligned tracks change color to alert you.
+
+You can hover the mouse pointer over the tool icons in the Audacity toolbars to see a pop-up that displays the name of that tool. This helps beginners understand what each tool does.
+
+![Audacity toolbox][9]
+
+Here, the **Selection** tool** **is selected in the Audacity toolbar. The **Time-Shift** tool is second from the left on the bottom row.
+
+The following image shows what happens when you slide the audio clips into place on the project timeline without sorting the tracks into a particular sequence. This may not be optimal for how you like to work. It is not for me.
+
+![Audio clips in Audacity][10]
+
+To remove segments of (or complete) audio clips, select them with the **Selection** tool—you can also select multiple adjacent tracks. Then you can press the **Delete** button on your keyboard to delete the selected segment(s).
+
+In the image above, you can see a vertical black line in track 1 and a vertical green line crossing all the tracks. These are the audio cursors that show the playback positions of a track or the entire project. Choose the **Selection** tool and click the desired position within a track, then click the **Play** button on the transport controls (in the upper-left of the Audacity window) to begin playback. Playback will continue past the end of the selected track and all the way to the end of the project. If tracks overlap on the timeline, they will play simultaneously.
+
+To begin playback immediately, click the desired starting point on the timeline. To play part of a track, hold down the Left mouse button to select a short segment of the track, and then click the **Play** button. The other transport buttons—Pause, Stop, and so—on are identified with universal icons and work as you would expect.
+
+You can also click the **Silence Audio Selection** button—the fifth button from the left on the **Edit** toolbar (shown below)—to completely silence a selected segment while leaving it in place for timing purposes. This is how I silenced a number of background clicks and noises.
+
+![Audacity edit tools][11]
+
+It took me a while to figure out how to sort the tracks vertically, and it turns out there are a few different ways to accomplish the task.
+
+You can use the track menu to reorder arrangement. Each track has its own Control Panel on the left side (shown below). The track drop-down Menu bar at the top of the Control Panel opens a menu that provides several track-sequencing options to move a track up, down, to the top, or to the bottom.
+
+![Moving tracks in Audacity][12]
+
+The items to move a track up or down move the track one position at a time, so you have to select it as many times as necessary to get the track in the desired position.
+
+To drag and drop tracks, you must click on the space occupied by the track details. In this screenshot, that's "Mono, 48000Hz 32 bit float". It can be tricky, because if you click too high, you adjust the panning (the left and right stereo position) and if you click too low, you may collapse or select the track. Target the "Mono" or "Stereo" label (whatever your track happens to be) label, and then click and drag the track up or down to reposition it in your workspace.
+
+### Apply amplification and noise reduction effects
+
+Some tracks need the overall volume to be adjusted. I used the **Selection** tool to double-click and select the entire track (but you could also select a portion of a track). On the Menu bar, select **Effect > Amplify** to display a small dialog window. You can use the slider or enter a value to specify the amount of amplification. Negative numbers decrease the volume. If you try to increase the volume, you need to place a check in the **Allow Clipping** box. Then click OK.
+
+I found that amplification is a bit tricky; it is easy to use too much or too little. Start by using small numbers to see the results. You can always use **Ctrl+Z** to undo your changes if you go too far in either direction.
+
+Another effect I find useful is noise reduction. One of the tracks was recorded with a noticeable 60Hz hum, which is usually due to poor grounding of the microphone or recorder. Fortunately, there were only several seconds of hum and no other sound at the beginning of the recording.
+
+Applying the noise reduction effect was a little confusing at first. First, I selected a few samples of the humming sound to tell Audacity what sound needed to be reduced, and then I navigated to **Effect > Noise Reduction**. This opens the **Noise Reduction** dialog. I clicked on the **Get Noise Profile** button in the Step 1 section of the dialog, which uses the selected sample as the basis for a set of filter presets. After it gathers the selected sample, though, the dialog disappeared (this is by design). I re-opened the dialog, used the slider to select the noise reduction level in decibels (I set it to 15dB and left the other sliders alone), and then clicked **OK**.
+
+This worked well—you can hear the residual hum only if you know it is there. I need to experiment with this some more, but since the result was acceptable, so I did not play with the settings any further.
+
+The reason the dialog box closes after getting a noise profile is actually for the sake of expediency. If you're processing many tracks or segments of audio, each with a different noise profile, you can open the **Noise Reduction** effect, get the current noise profile, and then select the audio you want to clean. You can then run the Noise Reduction filter using **Ctrl+R**, the keyboard shortcut for running the most recent filter. Instead of getting a new noise profile, however, Audacity uses the one you've just stored, and performs the filter instead. This way, you can get a sample with a few clicks but clean lots of audio with just one keyboard shortcut.
+
+### And so much more
+
+I have only worked with a few of the basics and have not even begun to scratch the surface of Audacity. I can already see that it has so many more features and tools that will enable me to create even more professional-sounding projects.
+
+For example, in addition to working with existing audio files, Audacity can make recordings from line inputs, the desktop sound stream, and microphone inputs. It can do special effects like fade in and out and cross-fades. And I have not even tried to figure out what many of the other effects and tools are capable of.
+
+I have a feeling I will need to learn more in the near future. Hopefully, this story of my very limited experience with Audacity will prompt you to check it out. For much more information, you can find the [Audacity manual][13] online.
+
+Using Audacity, you can quickly clean up audio file so that any background noise becomes tolerable.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/4/audacity
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/music-birds-recording-520.png?itok=UoM7brl0 (Bird singing and music notes)
+[2]: https://www.redhat.com/sysadmin/
+[3]: https://www.audacityteam.org/
+[4]: https://opensource.com/article/17/12/using-sudo-delegate
+[5]: https://opensource.com/education/16/9/audacity-classroom
+[6]: https://manual.audacityteam.org/man/installing_and_updating_audacity_on_linux.html#linlame
+[7]: https://manual.audacityteam.org/man/installing_and_updating_audacity_on_linux.html#linff
+[8]: https://opensource.com/sites/default/files/uploads/audacity1_tracksloaded.png (Tracks loaded in Audacity)
+[9]: https://opensource.com/sites/default/files/uploads/audacity2_tools.png (Audacity toolbox)
+[10]: https://opensource.com/sites/default/files/uploads/audacity3_audioclips.png (Audio clips in Audacity)
+[11]: https://opensource.com/sites/default/files/uploads/audacity4_edittoolbar.png (Audacity edit tools)
+[12]: https://opensource.com/sites/default/files/uploads/audacity5_trackmovement.png (Moving tracks in Audacity)
+[13]: https://manual.audacityteam.org/#
diff --git a/sources/tech/20200430 Linux and Kubernetes- Serving The Common Goals of Enterprises.md b/sources/tech/20200430 Linux and Kubernetes- Serving The Common Goals of Enterprises.md
new file mode 100644
index 0000000000..c3c0c36b66
--- /dev/null
+++ b/sources/tech/20200430 Linux and Kubernetes- Serving The Common Goals of Enterprises.md
@@ -0,0 +1,77 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Linux and Kubernetes: Serving The Common Goals of Enterprises)
+[#]: via: (https://www.linux.com/articles/linux-and-kubernetes-serving-the-common-goals-of-enterprises/)
+[#]: author: (Swapnil Bhartiya https://www.linux.com/author/swapnil/)
+
+Linux and Kubernetes: Serving The Common Goals of Enterprises
+======
+
+[![][1]][2]
+
+For [Stefanie Chiras,][3] VP & GM, Red Hat Enterprise Linux (RHEL) Business Unit at [Red Hat][4], aspects such as security and resiliency have always been important for Red Hat. More so, in the current situation when everyone has gone fully remote and it’s much harder to get people in front of the hardware for carrying out updates, patching, etc.
+
+“As we look at our current situation, never has it been more important to have an operating system that is resilient and secure, and we’re focused on that,” she said.
+
+The recently released version of [Red Hat Enterprise Linux (RHEL) 8.2][5] inadvertently address these challenge as it makes it easier for technology leaders to embrace the latest, production-ready innovations swiftly which offering security and resilience that their IT teams need.
+
+RHEL’s embrace of a predictable 6-month minor release cycle also helped customers plan upgrades more efficiently.
+
+“There is value for customers in having predictability of minor releases on a six-month cycle. Without knowing when they were coming was causing disruptions for them. The launch of 8.2 is now the second time we have delivered on our commitment of having minor releases every six months,” said Stefanie Chiras.
+
+In addition to offering security updates, the new version adds insights capabilities and forays into newer areas of innovation.
+
+The upgrade has expanded the earlier capability called ‘Adviser’ dramatically. Additional functionalities such as drift monitoring and CVE coverage allow for a much deeper granularity into how the infrastructure is running.
+
+“It really amplifies the skills that are already present in ops and sysadmin teams, and this provides a Red Hat consultation, if you will, directly into the data center,” claimed Charis.
+
+As containers are increasingly being leveraged for digital transformation, RHEL 8.2 offers an updated application stream of Red Hat’s container tools. It also has new, containerized versions of Buildah and Skopeo.
+
+[Skopeo][6] is an open-source image copying tool, while Buildah is a tool for building Docker- and Kubernetes-compatible images easily and quickly.
+
+RHEL has also ensured in-place upgrades in the new version. Customers can now directly in-place upgrade from version 7 to version 8.2.
+
+Chiras believes Linux has emerged as the go-to-platform for innovations such as Machine Learning, Deep Learning, and Artificial Intelligence.
+
+“Linux has now become the springboard of innovation,” she argued. “AI, machine learning, and deep learning are driving a real change in not just the software but also the hardware. In the context of these emerging technologies, it’s all about making them consumable into an enterprise.”
+
+“We’re very focused on our ecosystem, making sure that we’re working in the right upstream communities with the right ISVs, with the right hardware partners to make all of that magic come together,” Chiras said.
+
+Towards this end, Red Hat has been partnering with multiple architectures for a long time — be it an x86 architecture, ARM, Power, or mainframe with IBM Z. Its partnership with Nvidia pulls in capabilities such as FPGAs, and GPU.
+
+**Synergizing Kubernetes and Linux **
+
+Kubernetes is fast finding favor in enterprises. So how do Linux and Kubernetes serve the common goals of enterprises?
+
+“Kubernetes is a new way to deploy Linux. We’re very focused on providing operational consistency by leveraging our technology in RHEL and then bringing in that incredible capability of Kubernetes within our OpenShift product line,” Chiras said.
+
+The deployment of Linux within a Kubernetes environment is much more complicated than in a traditional deployment. RHEL, therefore, made some key changes. The company created Red Hat Enterprise Linux CoreOS — an optimized version of RHEL for the OpenShift experience.
+
+“It’s deployed as an immutable. It’s tailored, narrow, and gets updated as part of your OpenShift update to provide consistent user experience and comprehensive security.
+
+The launch of the Red Hat Universal Base Image (UBI) offers users greater security, reliability, and performance of official Red Hat container images where OCI-compliant Linux containers run.
+
+“Kubernetes is a new way to deploy Linux. It really is a tight collaboration but what we’re really focused on is the customer experience. We want them to get easy updates with consistency and reliability, resilience and security. We’re pulling all of that together. With such advancements going on, it’s a fascinating space to watch,” added Chiras.
+
+--------------------------------------------------------------------------------
+
+via: https://www.linux.com/articles/linux-and-kubernetes-serving-the-common-goals-of-enterprises/
+
+作者:[Swapnil Bhartiya][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.linux.com/author/swapnil/
+[b]: https://github.com/lujun9972
+[1]: https://www.linux.com/wp-content/uploads/2019/12/computer-2930704_1280-1068x634.jpg (computer-2930704_1280)
+[2]: https://www.linux.com/wp-content/uploads/2019/12/computer-2930704_1280.jpg
+[3]: https://www.linkedin.com/in/stefanie-chiras-9022144/
+[4]: https://www.redhat.com/en
+[5]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html-single/8.2_release_notes/index
+[6]: https://github.com/containers/skopeo
diff --git a/sources/tech/20200501 Transparent, open source alternative to Google Analytics.md b/sources/tech/20200501 Transparent, open source alternative to Google Analytics.md
new file mode 100644
index 0000000000..d4ce222a39
--- /dev/null
+++ b/sources/tech/20200501 Transparent, open source alternative to Google Analytics.md
@@ -0,0 +1,123 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Transparent, open source alternative to Google Analytics)
+[#]: via: (https://opensource.com/article/20/5/plausible-analytics)
+[#]: author: (Marko Saric https://opensource.com/users/markosaric)
+
+Transparent, open source alternative to Google Analytics
+======
+Plausible Analytics is a leaner, more transparent option, with the
+essential data you need but without all the privacy baggage.
+![Digital creative of a browser on the internet][1]
+
+Google Analytics is the most popular website analytics tool. Millions of developers and creators turn to it to collect and analyze their website statistics.
+
+More than 53% of all sites on the web track their visitors using Google Analytics. [84%][2] of sites that do use a known analytics script use Google Analytics.
+
+Google Analytics has, for years, been one of the first tools I installed on a newly launched site. It is a powerful and useful analytics tool. Installing Google Analytics was a habit I didn't think much about until the introduction of the [GDPR][3] (General Data Protection Regulation) and other privacy regulations.
+
+Using Google Analytics these days comes with several pitfalls, including the need for a privacy policy, the need for cookie banners, and the need for a GDPR consent prompt. All these may negatively impact the site loading time and visitor experience.
+
+This has made me try to [de-Google-ify websites][4] that I work on, and it's made me start working on independent solutions that are open source and more privacy-friendly. This is where Plausible Analytics enters the story.
+
+[Plausible Analytics][5] is an open source and lightweight alternative to Google Analytics. It doesn't use cookies and it doesn't collect any personal data, so you don't need to show any cookie banners or get GDPR or CCPA consent. Let's take a closer look.
+
+### Main differences between Google Analytics and Plausible
+
+Plausible Analytics is not designed to be a clone of Google Analytics. It is meant as a simple-to-use replacement and a privacy-friendly alternative. Here are the main differences between the two web analytics tools:
+
+#### Open source vs. closed source
+
+Google Analytics may be powerful and useful, but it is closed source. It is a proprietary tool run by one of the largest companies in the world, a company that is a key player in the ad-tech industry. There's simply no way of knowing what's going on behind the scenes. You have to put your trust in Google.
+
+Plausible is a fully open source tool. You can read our code [on GitHub][6]. We're "open" in other ways, too, such as our [public roadmap][7], which is based around the feedback and features submitted by the members of our community.
+
+#### Privacy of your website visitors
+
+Google Analytics places [several cookies][8] on the devices of your visitors, and it tracks and collects a lot of data. This means that there are several requirements if you want to use Google Analytics and be compliant with the different regulations:
+
+ * You need to have a privacy policy about analytics
+ * You need to show a cookie banner
+ * You need to obtain a GDPR/CCPA consent
+
+
+
+Plausible is made to be fully compliant with the privacy regulations. No cookies are used, and no personal data is collected. This means that you don't need to display the cookie banner, you don't need a privacy policy, and you don't need to ask for the GDPR/CCPA consent when using Plausible.
+
+#### Page weight and loading time
+
+The recommended way of installing Google Analytics is to use the Google Tag Manager. Google Tag Manager script weights 28 KB, and it downloads another JavaScript file called the Google Analytics tag, which adds an additional 17.7 KB to your page size. That's 45.7 KB of page weight combined.
+
+Plausible script weights only 1.4 KB. That's 33 times smaller than the Google Analytics Global Site Tag. Every KB matters when you want to keep your site fast to load.
+
+#### Accuracy of visitor stats
+
+Google Analytics is being blocked by an increasing number of web users. It's blocked by those who use open source browsers such as [Firefox][9] and [Brave][10]. It's also blocked by those who use open source browser add-ons such as the [uBlock Origin][11]. It's not uncommon to see 40% or more of the audience on a tech site blocking Google Analytics.
+
+Plausible is a new player on this market and it's privacy-friendly by default, so it doesn't see the same level of blockage.
+
+#### Simple vs. complex web analytics
+
+[Google Analytics is overkill][12] for many website owners. It's a complex tool that takes time to understand and requires training. Google Analytics presents hundreds of different reports and metrics for you to get insights from. Many users end up creating custom dashboards while ignoring all the rest.
+
+Plausible cuts through all the noise that Google Analytics creates. It presents everything you need to know on one single page—all the most valuable metrics at a glance. You can get an overview of the most actionable insights about your website in one minute.
+
+### A guided tour of Plausible Analytics
+
+Plausible Analytics is not a full-blown replacement and a feature-by-feature reproduction of Google Analytics. It's not designed for all the different use-cases of Google Analytics.
+
+It's built with simplicity and speed in mind. There is no navigational menu. There are no additional sub-menus. There is no need to create custom reports. You get one simple and useful web analytics dashboard out of the box.
+
+Rather than tracking every metric imaginable, many of them that you will never find a use for, Plausible focuses on the essential website stats only. It is easy to use and understand with no training or prior experience:
+
+![Plausible analytics in action][13]
+
+ * Choose the time range that you want to analyze. The visitor numbers are automatically presented on an hourly, daily, or monthly graph. The default time frame is set at the last 30 days.
+ * See the number of unique visitors, total page views, and the bounce rate. These metrics include a percentage comparison to the previous time period, so you understand if the trends are going up or down.
+ * See all the referral sources of traffic and all the most visited pages on your site. Bounce rates of the individual referrals and pages are included too.
+ * See the list of countries your traffic is coming from. You can also see the device, browser, and operating system your visitors are using.
+ * Track events and goals to identify the number of converted visitors, the conversion rate, and the referral sites that send the best quality traffic.
+
+
+
+Take a look at the [live demo][14] where you can follow the traffic to the Plausible website.
+
+### Give Plausible Analytics a chance
+
+With Plausible Analytics, you get all the important web analytics at a glance so you can focus on creating a better site without needing to annoy your visitors with all the different banners and prompts.
+
+You can try Plausible Analytics on your site alongside Google Analytics. [Register today][15] to try it out, and see what you like and what you don't. Share your feedback with the community. This helps us learn and improve. We'd love to hear from you.
+
+Take a look at five great open source alternatives to Google Docs.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/plausible-analytics
+
+作者:[Marko Saric][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/markosaric
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/browser_web_internet_website.png?itok=g5B_Bw62 (Digital creative of a browser on the internet)
+[2]: https://w3techs.com/technologies/details/ta-googleanalytics
+[3]: https://gdpr-info.eu/
+[4]: https://markosaric.com/degoogleify/
+[5]: https://plausible.io/
+[6]: https://github.com/plausible-insights/plausible
+[7]: https://feedback.plausible.io/roadmap
+[8]: https://developers.google.com/analytics/devguides/collection/analyticsjs/cookie-usage
+[9]: https://www.mozilla.org/en-US/firefox/new/
+[10]: https://brave.com/
+[11]: https://github.com/gorhill/uBlock
+[12]: https://plausible.io/vs-google-analytics
+[13]: https://opensource.com/sites/default/files/plausible-analytics.png (Plausible analytics in action)
+[14]: https://plausible.io/plausible.io
+[15]: https://plausible.io/register
diff --git a/sources/tech/20200503 13 tips for getting your talk accepted at a tech conference.md b/sources/tech/20200503 13 tips for getting your talk accepted at a tech conference.md
new file mode 100644
index 0000000000..b260116fb6
--- /dev/null
+++ b/sources/tech/20200503 13 tips for getting your talk accepted at a tech conference.md
@@ -0,0 +1,127 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (13 tips for getting your talk accepted at a tech conference)
+[#]: via: (https://opensource.com/article/20/5/tips-conference-proposals)
+[#]: author: (Todd Lewis https://opensource.com/users/toddlewis)
+
+13 tips for getting your talk accepted at a tech conference
+======
+Before you respond to an event's call for papers, make sure your talk's
+proposal aligns with these best practices.
+![All Things Open check-in at registration booth][1]
+
+As tech conference organizers ramp up for the fall season, you may be seeing calls for papers (CFP) landing in your email box or social media feeds. We at [All Things Open][2] (ATO) have seen a lot of presentation proposals over the years, and we've learned a few things about what makes them successful.
+
+As we prepare for the eighth annual ATO in October 2020, we thought we'd offer a few best practices for writing successful CFP responses. If you're considering submitting a talk to ATO or another tech event, we hope these tips will help improve the chances that your proposal will be accepted.
+
+### 1\. Know the event you're submitting a talk to
+
+This seems like the proverbial _no-brainer_, but some people don't take the time to research an event before they submit a talk. Peruse the conference's website and review the talks, speakers, topics, etc. featured in the last couple of years. You can also find a lot of information simply by googling. The time you invest here will help you avoid a submission that is completely out of context for the event.
+
+### 2\. Understand what the event is looking for
+
+Look for information about what the event is looking for and what types of topics or talks it expects will be a good fit. We try to provide as much information as possible about the [ATO conference][3], [why someone would want to speak][4], and [what we're looking for][5] (both general and special interest topics). We also try to make the submission process as easy as possible (no doubt, there is room for improvement), in part because we believe this improves the quality of submissions and makes our review process go more smoothly.
+
+### 3\. Reach out to the organizer and ask questions
+
+If you're considering submitting a talk, don't hesitate to reach out and ask the event organizers any questions you have and for guidance specific to the event. If there is no or little response, that should be a red flag. If you have any questions about All Things Open, please reach out directly at [info@allthingsopen.org][6].
+
+### 4\. Be clear about what attendees will learn from your talk
+
+This is one of the most common mistakes we see. Only about 25% of the proposals we receive clearly explain the proposed talk's takeaways. One reason you should include this is that nearly every event attendee makes their schedule based on what they will learn if they go to a session. But for organizers and proposal reviewers, having this information clearly stated upfront is pure gold. It simplifies and speeds up the assessment process, which gets you one step closer to being accepted as a speaker. A paragraph titled "Attendee Takeaways" with bullet points is the holy grail for everyone involved.
+
+### 5\. Keep recommended word counts in mind
+
+This is another mistake we see a lot. Many talks are submitted with either a single sentence description in the abstract or an extraordinary long volume of text. Neither is a good idea. The only exception we can think of is when a topic is very popular or topical, and that alone is enough to win the day even if the abstract is extremely short (but this is rare). Most abstracts should be between 75 and 250 words, and perhaps more for an extended workshop with prerequisites (e.g., preexisting knowledge or required downloads). Even then, try to keep your proposal as sharp, concise, and on-point as possible.
+
+Disregard this advice at your own risk; otherwise, there's a high likelihood that your proposal will be met with one of these reactions from reviewers: "They didn't take the time to write any more than this?" or "Sheesh, there's no way I have the time to read all that. I'm going to give it the lowest score and move on."
+
+### 6\. Choose a good title
+
+This is a debate we see all the time: Should a talk's title describe what the talk is about, or should it be written to stand out and get attention (e.g., evoking emotion, anchoring to a popular pop culture topic, or asking a compelling question)? There isn't a single correct answer to this question, but we definitely know when a title "works" and when it doesn't. We've seen some very creative titles work well and generate interest, and we've seen very straightforward titles work well, also.
+
+Here is our rule of thumb: If the talk covers a topic that has been around a while and is not particularly _hot_ right now, try getting creative and spicing it up a bit. If the topic is newer, a more straightforward title describing the talk in plain terms should be good.
+
+Titles on an event schedule may be the only thing attendees use to decide what talks to attend. So, run your potential talk titles by colleagues and friends, and seek their opinions. Ask: "If you were attending an event and saw this title on the schedule, would it pique your interest?"
+
+### 7\. Know the basic criteria that reviewers and organizers use to make decisions
+
+While this isn't a comprehensive list of review criteria, most reviewers and organizers consider one or more of the following when evaluating talk proposals. Therefore, at minimum, consider this list when you're creating a talk and the components that go with it.
+
+ 1. **Timeliness of and estimated interest in the topic:** Is the topic applicable to the session's target audience? Will it deliver value? Is it timely?
+ 2. **Educational value:** Based on the abstract and speaker, is it clear that attendees will learn something from the talk? As mentioned in item 4 above, including an "Attendee Takeaways" section is really helpful to establish educational value.
+ 3. **Technical value:** Is the technology you intend to showcase applicable, unique, or being used in a new and creative way? Is there a live demo or a hands-on component? While some topics don't lend themselves to a demo, most people are visual learners and are better off if a presentation includes one (if it's relevant). For this reason, we place a lot of value on demos and hands-on content.
+ 4. **Diversity:** Yes, there are exceptions, but the majority of events, reviewers, and organizers agree that having a diverse speaker lineup is optimal and results in a better overall event in multiple ways. A topic delivered from a different perspective can often lead to creative breakthroughs for attendees, which is a huge value-add. See item 10 below for more on this.
+ 5. **Talk difficulty level:** We identify All Things Open talks as introductory, intermediate, or advanced. Having a good mix of talk levels ensures everyone in attendance can access applicable content. See item 9 below for more on this, but in general, it's smart to indicate your talk's level, whether or not the CFP requests it.
+
+
+
+### 8\. Stay current on the event's industry or sector
+
+Submitting a proposal on a relevant topic increases the probability your talk will be accepted. But how do you know what topics are of interest, especially if the CFP doesn't spell it out in simple terms? The best way to know what's timely and interesting is to deeply understand the sector the event focuses on.
+
+Yes, this requires time and effort, and it implies you enjoy the sector enough to stay current on it, but it will pay off. This knowledge will result in a higher _sector IQ_, which will be reflected in your topic, title, and abstract. It will be recognized by reviewers and immediately set you apart from others. At All Things Open, we spend the majority of our time reading about and staying current on the "open" space so that we can feature relevant, substantive, and informed content. Submitting a talk that is relevant, substantive, and informed greatly enhances the chance it will be accepted.
+
+### 9\. Describe whether the talk is introductory, intermediate, or advanced
+
+Some CFPs don't ask for this information, but you should offer it anyway. It will make the reviewers and organizer very happy for multiple reasons, including these:
+
+ 1. Unless the event targets attendees with a certain skill or experience level (and most do not), organizers must include content that is appealing to a wide audience, including people of all skill, experience, and expertise levels. Even if an event focuses on a specific type of attendee (perhaps people with higher levels of experience or skills), most want to offer something a little different. Listing the talk level makes this much easier for organizers.
+ 2. News flash: Reviewers and organizers don't know everything and are not experts in every possible topic area. As a result, reviewers will sometimes look for a few keywords or other criteria, and adding the talk level can "seal the deal" and get your talk confirmed.
+
+
+
+### 10\. Tell organizers if you're a member of a historically underrepresented group
+
+A growing number of events are getting better at recognizing the value of diversity and ensuring their speaker lineup reflects it. If you're part of a group that hasn't typically been included in tech events and leadership, look to see if there is a place to indicate that on the submission form. If not, mention it in a conspicuous place somewhere in the abstract. This does not guarantee approval in any way—your proposal must still be well-written and relevant—but it does give reviewers and organizers pertinent information they may value and take into consideration.
+
+### 11\. Don't be ashamed of your credentials or speaking experience if it is light
+
+We talk to a lot of people who would like to deliver a presentation and have a lot to offer, but they never submit a talk because they don't feel they're qualified to speak. _Not true._ Some of the best talks we've seen are from first-time speakers or those very early in their speaking careers. Go ahead and submit the talk, and be honest when discussing your background. Most reviewers and organizers will focus on the substance of the submission over your experience and recognize that new ways of approaching and using technology often come from newbies rather than industry veterans.
+
+One caveat here: It still pays to know yourself. By this, we mean if you absolutely hate public speaking, have no desire to do it, and are only considering submitting a talk due to, for example, pressure from an employer, the talk is not likely to go well. It's better, to be honest, on the frontend than force something you have no desire to do.
+
+### 12\. Consider panel sessions carefully
+
+If you've got an idea for a panel session, please consider it carefully. In more than 10 years of hosting events we've seen some really good panel sessions, but we've seen far more that didn't go so well. Perhaps too many people were on the panel and not everyone had a chance to speak, perhaps a single panel member dominated the entire conversation, or perhaps the moderator didn't keep the dialogue and engagement flowing smoothly. Regardless of the issue, panels have the potential to go very wrong.
+
+That said, panels can still work and deliver a lot of value to attendees. If you do submit a panel session be sure to keep in mind the amount of time allotted for the session and confirm the number of panel members accordingly. Remember, less is always more when it comes to the panel format. Also, be sure the moderator understands the subject matter being discussed and doesn't mind enforcing format parameters and speaking time limits. Finally, let organizers know panel members and the moderator will engage in a pre-conference walk-through/preparation call before the event to ensure a smooth process in front of a live audience. Remember, organizers are well aware panels can be terrific but can also go in the opposite direction and very easily lead to a lot of negative feedback.
+
+### 13\. This is not an opportunity to sell
+
+This is a sensitive topic, but one that absolutely must be mentioned. Over the years we've seen literally hundreds of talks "disqualified" by reviewers because they viewed the talk as a sales pitch. Few things evoke such a visceral response. Yes, there are events, tracks, and session slots where a sales pitch is appropriate (and maybe even required by the company paying your costs). However, make it a priority to know when and where this is appropriate and acceptable. And always, and we mean always, err on the side of making substance the focus of the talk rather than a sales angle.
+
+It might sound like a cliche, but when a talk is delivered effectively with a focus on substance, people will **want** to buy what you're selling. And if you're not selling anything, they'll want to follow you on social media and generally engage with you—because you delivered value to them. Meaning: You gave them something they can apply themselves (education) or because your delivery style was entertaining and engaging. With rare exceptions, always focus any abstract on substance, and the rest will take care of itself.
+
+### Go for it!
+
+We greatly admire and respect anyone who submits a talk for consideration—it takes a lot of time, thought, and courage. Therefore, we go to great lengths to thank everyone who goes through the process; we give free event passes to everyone who applies (regardless of approval or rejection), and we make every effort to host Q&A sessions to provide as much guidance as possible on the front end. Again, the more time and consideration speakers put into the submission process, the easier the lives of reviewers and organizers. We need to make all of this as easy as possible.
+
+While this is not a comprehensive list of best practices, it includes some of the things we think people can benefit from knowing before submitting a talk. There are a lot of people out there with more knowledge and experience, so please share your best tips for submitting conference proposals in the comments, so we can all learn from you.
+
+* * *
+
+_[All Things Open][2] is a universe of platforms and events focusing on open source, open tech, and the open web. It hosts the [All Things Open conference][3], the largest open source/tech/web event on the US East Coast. The conference regularly hosts thousands of attendees and many of the world's most influential companies from a wide variety of industries and sectors. In 2019, nearly 5,000 people attended from 41 US states and 24 countries. Please direct inquiries about ATO to the team at [info@allthingsopen.org][6]._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/tips-conference-proposals
+
+作者:[Todd Lewis][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/toddlewis
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/ato2016_checkin_conference.jpg?itok=DJtoSS6t (All Things Open check-in at registration booth)
+[2]: https://www.allthingsopen.org/
+[3]: https://2020.allthingsopen.org/
+[4]: https://2020.allthingsopen.org/call-for-speakers
+[5]: https://www.allthingsopen.org/what-were-looking-for/
+[6]: mailto:info@allthingsopen.org
diff --git a/sources/tech/20200504 Create interactive learning games for kids with open source.md b/sources/tech/20200504 Create interactive learning games for kids with open source.md
new file mode 100644
index 0000000000..f6ade34857
--- /dev/null
+++ b/sources/tech/20200504 Create interactive learning games for kids with open source.md
@@ -0,0 +1,123 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Create interactive learning games for kids with open source)
+[#]: via: (https://opensource.com/article/20/5/jclic-games-kids)
+[#]: author: (Peter Cheer https://opensource.com/users/petercheer)
+
+Create interactive learning games for kids with open source
+======
+Help your students learn by creating fun puzzles and games in JClic, an
+easy Java-based app.
+![Family learning and reading together at night in a room][1]
+
+Schools are closed in many countries around the world to slow the spread of COVID-19. This has suddenly thrown many parents and teachers into homeschooling. Fortunately, there are plenty of educational resources on the internet to use or adapt, although their licenses vary. You can try searching for Creative Commons Open Educational Resources, but if you want to create your own materials, there are many options for that to.
+
+If you want to create digital educational activities with puzzles or tests, two easy-to-use, open source, cross-platform applications that fit the bill are eXeLearning and JClic. My earlier article on [eXeLearning][2] is a good introduction to that program, so here I'll look at [JClic][3]. It is an open source software project for creating various types of interactive activities such as associations, text-based activities, crosswords, and other puzzles with text, graphics, and multimedia elements.
+
+Although it's been around since the 1990s, JClic never developed a large user base in the English-speaking world. It was created in Catalonia by the [Catalan Educational Telematic Network][4] (XTEC).
+
+### About JClic
+
+JClic is a Java-based application that's available in many Linux repositories and can be downloaded from [GitHub][5]. It runs on Linux, macOS, and Windows, but because it is a Java program, you must have a Java runtime environment [installed][6].
+
+The program's interface has not really changed much over the years, even while features have been added or dropped, such as introducing HTML5 export functionality to replace Java Applet technology for web-based deployment. It hasn't needed to change much, though, because it's very effective at what it does.
+
+### Creating a JClic project
+
+Many teachers from many countries have used JClic to create interactive materials for a wide variety of ability levels, subjects, languages, and curricula. Some of these materials have been collected in an [downloadable activities library][7]. Although few activities are in English, you can get a sense of the possibilities JClic offers.
+
+As JClic has a visual, point-and-click program interface, it is easy enough to learn that a new user can quickly concentrate on content creation. [Documentation][8] is available on GitHub.
+
+The screenshots below are from one of the JClic projects I created to teach basic Excel skills to learners in Papua New Guinea.
+
+A JClic project is created in its authoring tool and consists of the following four elements:
+
+#### 1\. Metadata about the project
+
+![JClic metadata][9]
+
+#### 2\. A library of the graphical and other resources it uses
+
+![JClic media][10]
+
+#### 3\. A series of one or more activities
+
+![JClic activities][11]
+
+JClic can produce seven different activity types:
+
+ * Associations where the user discovers the relationships between two information sets
+ * Memory games where the user discovers pairs of identical elements or relations (which are hidden) between them
+ * Exploration activities involving the identification and information, based on a single Information set
+ * Puzzles where the user reconstructs information that is initially presented in a disordered form; the activity can include graphics, text, sound, or a combination of them
+ * Written-response activities that are solved by writing text, either a single word or a sentence
+ * Text activities that are based on words, phrases, letters, and paragraphs of text that need to be completed, understood, corrected, or ordered; these activities can contain images and windows with active content
+ * Word searches and crosswords
+
+
+
+Because of variants in the activities, there are 16 possible activity types.
+
+#### 4\. A timeline to sequence the activities
+
+![JClic timeline][12]
+
+### Using JClic content
+
+Projects can run in JClic's player (part of the Java application you used to create the project), or they can be exported to HTML5 so they can run in a web browser.
+
+The one thing I don't like about JClic is that its default HTML5 export function assumes you'll be online when running a project. If you want a project to work offline as needed, you must download a compiled and minified HTML5 player from [Github][13], and place it in the same folder as your JClic project.
+
+Next, open the **index.html** file in a text editor and replace this line:
+
+
+```
+``
+```
+
+With:
+
+
+```
+``
+```
+
+Now the HTML5 version of your project runs in a web browser, whether the user is online or not.
+
+JClic also provides a reports function that can store test scores in an ODBC-compliant database. I have not explored this feature, as my tests and puzzles are mostly used for self-assessment and to prompt reflection by the learner, rather than as part of a formal scheme, so the scores are not very important. If you would like to learn about it, there is [documentation][14] on running JClic Reports Server with Tomcat and MySQL (or [mariaDB][15]).
+
+### Conclusion
+
+JClic offers a wide range of activity types that provide plenty of room to be creative in designing content to fit your subject area and type of learner. JClic is a valuable addition for anyone who needs a quick and easy way to develop educational resources.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/jclic-games-kids
+
+作者:[Peter Cheer][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/petercheer
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/family_learning_kids_night_reading.png?itok=6K7sJVb1 (Family learning and reading together at night in a room)
+[2]: https://opensource.com/article/18/5/exelearning
+[3]: https://clic.xtec.cat/legacy/en/jclic/index.html
+[4]: https://clic.xtec.cat/legacy/en/index.html
+[5]: https://github.com/projectestac/jclic
+[6]: https://adoptopenjdk.net/installation.html
+[7]: https://clic.xtec.cat/repo/
+[8]: https://github.com/projectestac/jclic/wiki/JClic_Guide
+[9]: https://opensource.com/sites/default/files/uploads/metadata.png (JClic metadata)
+[10]: https://opensource.com/sites/default/files/uploads/media.png (JClic media)
+[11]: https://opensource.com/sites/default/files/uploads/activities.png (JClic activities)
+[12]: https://opensource.com/sites/default/files/uploads/sequence.png (JClic timeline)
+[13]: http://projectestac.github.io/jclic.js/
+[14]: https://github.com/projectestac/jclic/wiki/Jclic-Reports-Server-with-Tomcat-and-MySQL-on-Ubuntu
+[15]: https://mariadb.org/
diff --git a/sources/tech/20200504 Define and optimize data partitions in Apache Cassandra.md b/sources/tech/20200504 Define and optimize data partitions in Apache Cassandra.md
new file mode 100644
index 0000000000..d28f0daee0
--- /dev/null
+++ b/sources/tech/20200504 Define and optimize data partitions in Apache Cassandra.md
@@ -0,0 +1,150 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Define and optimize data partitions in Apache Cassandra)
+[#]: via: (https://opensource.com/article/20/5/apache-cassandra)
+[#]: author: (Anil Inamdar https://opensource.com/users/anil-inamdar)
+
+Define and optimize data partitions in Apache Cassandra
+======
+Apache Cassandra is built for speed and scalability; here's how to get
+the most out of those benefits.
+![Person standing in front of a giant computer screen with numbers, data][1]
+
+Apache Cassandra is a database. But it's not just any database; it's a replicating database designed and tuned for scalability, high availability, low-latency, and performance. Cassandra can help your data survive regional outages, hardware failure, and what many admins would consider excessive amounts of data.
+
+Having a thorough command of data partitions enables you to achieve superior Cassandra cluster design, performance, and scalability. In this article, I'll examine how to define partitions and how Cassandra uses them, as well as the most critical best practices and known issues you ought to be aware of.
+
+To set the scene: partitions are chunks of data that serve as the atomic unit for key database-related functions like data distribution, replication, and indexing. Distributed data systems commonly distribute incoming data into these partitions, performing the partitioning with simple mathematical functions such as identity or hashing, and using a "partition key" to group data by partition. For example, consider a case where server logs arrive as incoming data. Using the "identity" partitioning function and the timestamps of each log (rounded to the hour value) for the partition key, we can partition this data such that each partition holds one hour of the logs.
+
+### Data partitions in Cassandra
+
+Cassandra operates as a distributed system and adheres to the data partitioning principles described above. With Cassandra, data partitioning relies on an algorithm configured at the cluster level, and a partition key configured at the table level.
+
+![Cassandra data partition][2]
+
+Cassandra Query Language (CQL) uses the familiar SQL table, row, and column terminologies. In the example diagram above, the table configuration includes the partition key within its primary key, with the format: Primary Key = Partition Key + [Clustering Columns].
+
+A primary key in Cassandra represents both a unique data partition and a data arrangement inside a partition. Data arrangement information is provided by optional clustering columns. Each unique partition key represents a set of table rows managed in a server, as well as all servers that manage its replicas.
+
+### Defining primary keys in CQL
+
+The following four examples demonstrate how a primary key can be represented in CQL syntax. The sets of rows produced by these definitions are generally considered a partition.
+
+#### Definition 1 (partition key: log_hour, clustering columns: none)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP PRIMARYKEY,
+ log_level text,
+ message text,
+ server text
+ )
+```
+
+Here, all rows that share a **log_hour** go into the same partition.
+
+#### Definition 2 (partition key: log_hour, clustering columns: log_level)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP,
+ log_level text,
+ message text,
+ server text,
+ PRIMARY KEY (log_hour, log_level)
+ )
+```
+
+This definition uses the same partition key as Definition 1, but here all rows in each partition are arranged in ascending order by **log_level**.
+
+#### Definition 3 (partition key: log_hour, server, clustering columns: none)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP,
+ log_level text,
+ message text,
+ server text,
+ PRIMARY KEY ((log_hour, server))
+ )
+```
+
+In this definition, all rows share a **log_hour** for each distinct **server** as a single partition.
+
+#### Definition 4 (partition key: log_hour, server, clustering columns: log_level)
+
+
+```
+CREATE TABLE server_logs(
+ log_hour TIMESTAMP,
+ log_level text,
+ message text,
+ server text,
+ PRIMARY KEY ((log_hour, server),log_level)
+ )WITH CLUSTERING ORDER BY (column3 DESC);
+```
+
+This definition uses the same partition as Definition 3 but arranges the rows within a partition in descending order by **log_level**.
+
+### How Cassandra uses the partition key
+
+Cassandra relies on the partition key to determine which node to store data on and where to locate data when it's needed. Cassandra performs these read and write operations by looking at a partition key in a table, and using tokens (a long value out of range -2^63 to +2^63-1) for data distribution and indexing. These tokens are mapped to partition keys by using a partitioner, which applies a partitioning function that converts any partition key to a token. Through this token mechanism, every node of a Cassandra cluster owns a set of data partitions. The partition key then enables data indexing on each node.
+
+![Cassandra cluster with 3 nodes and token-based ownership][3]
+
+A Cassandra cluster with three nodes and token-based ownership. This is a simplistic representation: the actual implementation uses [Vnodes][4].
+
+### Data partition impacts on Cassandra clusters
+
+Careful partition key design is crucial to achieving the ideal partition size for the use case. Getting it right allows for even data distribution and strong I/O performance. Partition size has several impacts on Cassandra clusters you need to be aware of:
+
+ * Read performance—In order to find partitions in SSTables files on disk, Cassandra uses data structures that include caches, indexes, and index summaries. Partitions that are too large reduce the efficiency of maintaining these data structures – and will negatively impact performance as a result. Cassandra releases have made strides in this area: in particular, version 3.6 and above of the Cassandra engine introduce storage improvements that deliver better performance for large partitions and resilience against memory issues and crashes.
+ * Memory usage— Large partitions place greater pressure on the JVM heap, increasing its size while also making the garbage collection mechanism less efficient.
+ * Cassandra repairs—Large partitions make it more difficult for Cassandra to perform its repair maintenance operations, which keep data consistent by comparing data across replicas.
+ * Tombstone eviction—Not as mean as it sounds, Cassandra uses unique markers known as "tombstones" to mark data for deletion. Large partitions can make that deletion process more difficult if there isn't an appropriate data deletion pattern and compaction strategy in place.
+
+
+
+While these impacts may make it tempting to simply design partition keys that yield especially small partitions, the data access pattern is also highly influential on ideal partition size (for more information, read this in-depth guide to [Cassandra data modeling][5]). The data access pattern can be defined as how a table is queried, including all of the table's **select** queries. Ideally, CQL select queries should have just one partition key in the **where** clause—that is to say, Cassandra is most efficient when queries can get needed data from a single partition, instead of many smaller ones.
+
+### Best practices for partition key design
+
+Following best practices for partition key design helps you get to an ideal partition size. As a rule of thumb, the maximum partition size in Cassandra should stay under 100MB. Ideally, it should be under 10MB. While Cassandra versions 3.6 and newer make larger partition sizes more viable, careful testing and benchmarking must be performed for each workload to ensure a partition key design supports desired cluster performance.
+
+Specifically, these best practices should be considered as part of any partition key design:
+
+ * The goal for a partition key must be to fit an ideal amount of data into each partition for supporting the needs of its access pattern.
+ * A partition key should disallow unbounded partitions: those that may grow indefinitely in size over time. For instance, in the **server_logs** examples above, using the server column as a partition key would create unbounded partitions as the number of server logs continues to increase. In contrast, using **log_hour** limits each partition to an hour of data.
+ * A partition key should also avoid creating a partition skew, in which partitions grow unevenly, and some are able to grow without limit over time. In the **server_logs** examples, using the server column in a scenario where one server generates considerably more logs than others would produce a partition skew. To avoid this, a useful technique is to introduce another attribute from the table to force an even distribution, even if it's necessary to create a dummy column to do so.
+ * It's helpful to partition time-series data with a partition key that uses a time element as well as other attributes. This protects against unbounded partitions, enables access patterns to use the time attribute in querying specific data, and allows for time-bound data deletion. The examples above each demonstrate this by using the **log_hour** time attribute.
+
+
+
+Several tools are available to help test, analyze, and monitor Cassandra partitions to check that a chosen schema is efficient and effective. By carefully designing partition keys to align well with the data and needs of the solution at hand, and following best practices to optimize partition size, you can utilize data partitions that more fully deliver on the scalability and performance potential of a Cassandra deployment.
+
+Dani and Jon will give a three hour tutorial at OSCON this year called: Becoming friends with...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/apache-cassandra
+
+作者:[Anil Inamdar][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/anil-inamdar
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr (Person standing in front of a giant computer screen with numbers, data)
+[2]: https://opensource.com/sites/default/files/uploads/apache_cassandra_1_0.png (Cassandra data partition)
+[3]: https://opensource.com/sites/default/files/uploads/apache_cassandra_2_0.png (Cassandra cluster with 3 nodes and token-based ownership)
+[4]: https://www.instaclustr.com/cassandra-vnodes-how-many-should-i-use/
+[5]: https://www.instaclustr.com/resource/6-step-guide-to-apache-cassandra-data-modelling-white-paper/
diff --git a/sources/tech/20200504 Understanding systemd at startup on Linux.md b/sources/tech/20200504 Understanding systemd at startup on Linux.md
new file mode 100644
index 0000000000..2d0a5ef7b6
--- /dev/null
+++ b/sources/tech/20200504 Understanding systemd at startup on Linux.md
@@ -0,0 +1,445 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Understanding systemd at startup on Linux)
+[#]: via: (https://opensource.com/article/20/5/systemd-startup)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Understanding systemd at startup on Linux
+======
+systemd's startup provides important clues to help you solve problems
+when they occur.
+![People at the start line of a race][1]
+
+In [_Learning to love systemd_][2], the first article in this series, I looked at systemd's functions and architecture and the controversy around its role as a replacement for the old SystemV init program and startup scripts. In this second article, I'll start exploring the files and tools that manage the Linux startup sequence. I'll explain the systemd startup sequence, how to change the default startup target (runlevel in SystemV terms), and how to manually switch to a different target without going through a reboot.
+
+I'll also look at two important systemd tools. The first is the **systemctl** command, which is the primary means of interacting with and sending commands to systemd. The second is **journalctl**, which provides access to the systemd journals that contain huge amounts of system history data such as kernel and service messages (both informational and error messages).
+
+Be sure to use a non-production system for testing and experimentation in this and future articles. Your test system needs to have a GUI desktop (such as Xfce, LXDE, Gnome, KDE, or another) installed.
+
+I wrote in my previous article that I planned to look at creating a systemd unit and adding it to the startup sequence in this article. Because this article became longer than I anticipated, I will hold that for the next article in this series.
+
+### Exploring Linux startup with systemd
+
+Before you can observe the startup sequence, you need to do a couple of things to make the boot and startup sequences open and visible. Normally, most distributions use a startup animation or splash screen to hide the detailed messages that would otherwise be displayed during a Linux host's startup and shutdown. This is called the Plymouth boot screen on Red Hat-based distros. Those hidden messages can provide a great deal of information about startup and shutdown to a sysadmin looking for information to troubleshoot a bug or to just learn about the startup sequence. You can change this using the GRUB (Grand Unified Boot Loader) configuration.
+
+The main GRUB configuration file is **/boot/grub2/grub.cfg**, but, because this file can be overwritten when the kernel version is updated, you do not want to change it. Instead, modify the **/etc/default/grub** file, which is used to modify the default settings of **grub.cfg**.
+
+Start by looking at the current, unmodified version of the **/etc/default/grub** file:
+
+
+```
+[root@testvm1 ~]# cd /etc/default ; cat grub
+GRUB_TIMEOUT=5
+GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
+GRUB_DEFAULT=saved
+GRUB_DISABLE_SUBMENU=true
+GRUB_TERMINAL_OUTPUT="console"
+GRUB_CMDLINE_LINUX="resume=/dev/mapper/fedora_testvm1-swap rd.lvm.
+lv=fedora_testvm1/root rd.lvm.lv=fedora_testvm1/swap rd.lvm.lv=fedora_
+testvm1/usr rhgb quiet"
+GRUB_DISABLE_RECOVERY="true"
+[root@testvm1 default]#
+```
+
+Chapter 6 of the [GRUB documentation][3] contains a list of all the possible entries in the **/etc/default/grub** file, but I focus on the following:
+
+ * I change **GRUB_TIMEOUT**, the number of seconds for the GRUB menu countdown, from five to 10 to give a bit more time to respond to the GRUB menu before the countdown hits zero.
+ * I delete the last two parameters on **GRUB_CMDLINE_LINUX**, which lists the command-line parameters that are passed to the kernel at boot time. One of these parameters, **rhgb** stands for Red Hat Graphical Boot, and it displays the little Fedora icon animation during the kernel initialization instead of showing boot-time messages. The other, the **quiet** parameter, prevents displaying the startup messages that document the progress of the startup and any errors that occur. I delete both **rhgb** and **quiet** because sysadmins need to see these messages. If something goes wrong during boot, the messages displayed on the screen can point to the cause of the problem.
+
+
+
+After you make these changes, your GRUB file will look like:
+
+
+```
+[root@testvm1 default]# cat grub
+GRUB_TIMEOUT=10
+GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
+GRUB_DEFAULT=saved
+GRUB_DISABLE_SUBMENU=true
+GRUB_TERMINAL_OUTPUT="console"
+GRUB_CMDLINE_LINUX="resume=/dev/mapper/fedora_testvm1-swap rd.lvm.
+lv=fedora_testvm1/root rd.lvm.lv=fedora_testvm1/swap rd.lvm.lv=fedora_
+testvm1/usr"
+GRUB_DISABLE_RECOVERY="false"
+[root@testvm1 default]#
+```
+
+The **grub2-mkconfig** program generates the **grub.cfg** configuration file using the contents of the **/etc/default/grub** file to modify some of the default GRUB settings. The **grub2-mkconfig** program sends its output to **STDOUT**. It has a **-o** option that allows you to specify a file to send the datastream to, but it is just as easy to use redirection. Run the following command to update the **/boot/grub2/grub.cfg** configuration file:
+
+
+```
+[root@testvm1 grub2]# grub2-mkconfig > /boot/grub2/grub.cfg
+Generating grub configuration file ...
+Found linux image: /boot/vmlinuz-4.18.9-200.fc28.x86_64
+Found initrd image: /boot/initramfs-4.18.9-200.fc28.x86_64.img
+Found linux image: /boot/vmlinuz-4.17.14-202.fc28.x86_64
+Found initrd image: /boot/initramfs-4.17.14-202.fc28.x86_64.img
+Found linux image: /boot/vmlinuz-4.16.3-301.fc28.x86_64
+Found initrd image: /boot/initramfs-4.16.3-301.fc28.x86_64.img
+Found linux image: /boot/vmlinuz-0-rescue-7f12524278bd40e9b10a085bc82dc504
+Found initrd image: /boot/initramfs-0-rescue-7f12524278bd40e9b10a085bc82dc504.img
+done
+[root@testvm1 grub2]#
+```
+
+Reboot your test system to view the startup messages that would otherwise be hidden behind the Plymouth boot animation. But what if you need to view the startup messages and have not disabled the Plymouth boot animation? Or you have, but the messages stream by too fast to read? (Which they do.)
+
+There are a couple of options, and both involve log files and systemd journals—which are your friends. You can use the **less** command to view the contents of the **/var/log/messages** file. This file contains boot and startup messages as well as messages generated by the operating system during normal operation. You can also use the **journalctl** command without any options to view the systemd journal, which contains essentially the same information:
+
+
+```
+[root@testvm1 grub2]# journalctl
+\-- Logs begin at Sat 2020-01-11 21:48:08 EST, end at Fri 2020-04-03 08:54:30 EDT. --
+Jan 11 21:48:08 f31vm.both.org kernel: Linux version 5.3.7-301.fc31.x86_64 ([mockbuild@bkernel03.phx2.fedoraproject.org][4]) (gcc version 9.2.1 20190827 (Red Hat 9.2.1-1) (GCC)) #1 SMP Mon Oct >
+Jan 11 21:48:08 f31vm.both.org kernel: Command line: BOOT_IMAGE=(hd0,msdos1)/vmlinuz-5.3.7-301.fc31.x86_64 root=/dev/mapper/VG01-root ro resume=/dev/mapper/VG01-swap rd.lvm.lv=VG01/root rd>
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers'
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256
+Jan 11 21:48:08 f31vm.both.org kernel: x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard' format.
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-provided physical RAM map:
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000000100000-0x00000000dffeffff] usable
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000dfff0000-0x00000000dfffffff] ACPI data
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
+Jan 11 21:48:08 f31vm.both.org kernel: BIOS-e820: [mem 0x0000000100000000-0x000000041fffffff] usable
+Jan 11 21:48:08 f31vm.both.org kernel: NX (Execute Disable) protection: active
+Jan 11 21:48:08 f31vm.both.org kernel: SMBIOS 2.5 present.
+Jan 11 21:48:08 f31vm.both.org kernel: DMI: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
+Jan 11 21:48:08 f31vm.both.org kernel: Hypervisor detected: KVM
+Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: Using msrs 4b564d01 and 4b564d00
+Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: cpu 0, msr 30ae01001, primary cpu clock
+Jan 11 21:48:08 f31vm.both.org kernel: kvm-clock: using sched offset of 8250734066 cycles
+Jan 11 21:48:08 f31vm.both.org kernel: clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
+Jan 11 21:48:08 f31vm.both.org kernel: tsc: Detected 2807.992 MHz processor
+Jan 11 21:48:08 f31vm.both.org kernel: e820: update [mem 0x00000000-0x00000fff] usable ==> reserved
+Jan 11 21:48:08 f31vm.both.org kernel: e820: remove [mem 0x000a0000-0x000fffff] usable
+<snip>
+```
+
+I truncated this datastream because it can be hundreds of thousands or even millions of lines long. (The journal listing on my primary workstation is 1,188,482 lines long.) Be sure to try this on your test system. If it has been running for some time—even if it has been rebooted many times—huge amounts of data will be displayed. Explore this journal data because it contains a lot of information that can be very useful when doing problem determination. Knowing what this data looks like for a normal boot and startup can help you locate problems when they occur.
+
+I will discuss systemd journals, the **journalctl** command, and how to sort through all of that data to find what you want in more detail in a future article in this series.
+
+After GRUB loads the kernel into memory, it must first extract itself from the compressed version of the file before it can perform any useful work. After the kernel has extracted itself and started running, it loads systemd and turns control over to it.
+
+This is the end of the boot process. At this point, the Linux kernel and systemd are running but unable to perform any productive tasks for the end user because nothing else is running, there's no shell to provide a command line, no background processes to manage the network or other communication links, and nothing that enables the computer to perform any productive function.
+
+Systemd can now load the functional units required to bring the system up to a selected target run state.
+
+### Targets
+
+A systemd target represents a Linux system's current or desired run state. Much like SystemV start scripts, targets define the services that must be present for the system to run and be active in that state. Figure 1 shows the possible run-state targets of a Linux system using systemd. As seen in the first article of this series and in the systemd bootup man page (man bootup), there are other intermediate targets that are required to enable various necessary services. These can include **swap.target**, **timers.target**, **local-fs.target**, and more. Some targets (like **basic.target**) are used as checkpoints to ensure that all the required services are up and running before moving on to the next-higher level target.
+
+Unless otherwise changed at boot time in the GRUB menu, systemd always starts the **default.target**. The **default.target** file is a symbolic link to the true target file. For a desktop workstation, this is typically going to be the **graphical.target**, which is equivalent to runlevel 5 in SystemV. For a server, the default is more likely to be the **multi-user.target**, which is like runlevel 3 in SystemV. The **emergency.target** file is similar to single-user mode. Targets and services are systemd units.
+
+The following table, which I included in the previous article in this series, compares the systemd targets with the old SystemV startup runlevels. The systemd target aliases are provided by systemd for backward compatibility. The target aliases allow scripts—and sysadmins—to use SystemV commands like **init 3** to change runlevels. Of course, the SystemV commands are forwarded to systemd for interpretation and execution.
+
+**systemd targets** | **SystemV runlevel** | **target aliases** | **Description**
+---|---|---|---
+default.target | | | This target is always aliased with a symbolic link to either **multi-user.target** or **graphical.target**. systemd always uses the **default.target** to start the system. The **default.target** should never be aliased to **halt.target**, **poweroff.target**, or **reboot.target**.
+graphical.target | 5 | runlevel5.target | **Multi-user.target** with a GUI
+| 4 | runlevel4.target | Unused. Runlevel 4 was identical to runlevel 3 in the SystemV world. This target could be created and customized to start local services without changing the default **multi-user.target**.
+multi-user.target | 3 | runlevel3.target | All services running, but command-line interface (CLI) only
+| 2 | runlevel2.target | Multi-user, without NFS, but all other non-GUI services running
+rescue.target | 1 | runlevel1.target | A basic system, including mounting the filesystems with only the most basic services running and a rescue shell on the main console
+emergency.target | S | | Single-user mode—no services are running; filesystems are not mounted. This is the most basic level of operation with only an emergency shell running on the main console for the user to interact with the system.
+halt.target | | | Halts the system without powering it down
+reboot.target | 6 | runlevel6.target | Reboot
+poweroff.target | 0 | runlevel0.target | Halts the system and turns the power off
+
+Each target has a set of dependencies described in its configuration file. systemd starts the required dependencies, which are the services required to run the Linux host at a specific level of functionality. When all of the dependencies listed in the target configuration files are loaded and running, the system is running at that target level. If you want, you can review the systemd startup sequence and runtime targets in the first article in this series, [_Learning to love systemd_][2].
+
+### Exploring the current target
+
+Many Linux distributions default to installing a GUI desktop interface so that the installed systems can be used as workstations. I always install from a Fedora Live boot USB drive with an Xfce or LXDE desktop. Even when I'm installing a server or other infrastructure type of host (such as the ones I use for routers and firewalls), I use one of these installations that installs a GUI desktop.
+
+I could install a server without a desktop (and that would be typical for data centers), but that does not meet my needs. It is not that I need the GUI desktop itself, but the LXDE installation includes many of the other tools I use that are not in a default server installation. This means less work for me after the initial installation.
+
+But just because I have a GUI desktop does not mean it makes sense to use it. I have a 16-port KVM that I can use to access the KVM interfaces of most of my Linux systems, but the vast majority of my interaction with them is via a remote SSH connection from my primary workstation. This way is more secure and uses fewer system resources to run **multi-user.target** compared to **graphical.target.**
+
+To begin, check the default target to verify that it is the **graphical.target**:
+
+
+```
+[root@testvm1 ~]# systemctl get-default
+graphical.target
+[root@testvm1 ~]#
+```
+
+Now verify the currently running target. It should be the same as the default target. You can still use the old method, which displays the old SystemV runlevels. Note that the previous runlevel is on the left; it is **N** (which means None), indicating that the runlevel has not changed since the host was booted. The number 5 indicates the current target, as defined in the old SystemV terminology:
+
+
+```
+[root@testvm1 ~]# runlevel
+N 5
+[root@testvm1 ~]#
+```
+
+Note that the runlevel man page indicates that runlevels are obsolete and provides a conversion table.
+
+You can also use the systemd method. There is no one-line answer here, but it does provide the answer in systemd terms:
+
+
+```
+[root@testvm1 ~]# systemctl list-units --type target
+UNIT LOAD ACTIVE SUB DESCRIPTION
+basic.target loaded active active Basic System
+cryptsetup.target loaded active active Local Encrypted Volumes
+getty.target loaded active active Login Prompts
+graphical.target loaded active active Graphical Interface
+local-fs-pre.target loaded active active Local File Systems (Pre)
+local-fs.target loaded active active Local File Systems
+multi-user.target loaded active active Multi-User System
+network-online.target loaded active active Network is Online
+network.target loaded active active Network
+nfs-client.target loaded active active NFS client services
+nss-user-lookup.target loaded active active User and Group Name Lookups
+paths.target loaded active active Paths
+remote-fs-pre.target loaded active active Remote File Systems (Pre)
+remote-fs.target loaded active active Remote File Systems
+rpc_pipefs.target loaded active active rpc_pipefs.target
+slices.target loaded active active Slices
+sockets.target loaded active active Sockets
+sshd-keygen.target loaded active active sshd-keygen.target
+swap.target loaded active active Swap
+sysinit.target loaded active active System Initialization
+timers.target loaded active active Timers
+
+LOAD = Reflects whether the unit definition was properly loaded.
+ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
+SUB = The low-level unit activation state, values depend on unit type.
+
+21 loaded units listed. Pass --all to see loaded but inactive units, too.
+To show all installed unit files use 'systemctl list-unit-files'.
+```
+
+This shows all of the currently loaded and active targets. You can also see the **graphical.target** and the **multi-user.target**. The **multi-user.target** is required before the **graphical.target** can be loaded. In this example, the **graphical.target** is active.
+
+### Switching to a different target
+
+Making the switch to the **multi-user.target** is easy:
+
+
+```
+`[root@testvm1 ~]# systemctl isolate multi-user.target`
+```
+
+The display should now change from the GUI desktop or login screen to a virtual console. Log in and list the currently active systemd units to verify that **graphical.target** is no longer running:
+
+
+```
+`[root@testvm1 ~]# systemctl list-units --type target`
+```
+
+Be sure to use the **runlevel** command to verify that it shows both previous and current "runlevels":
+
+
+```
+[root@testvm1 ~]# runlevel
+5 3
+```
+
+### Changing the default target
+
+Now, change the default target to the **multi-user.target** so that it will always boot into the **multi-user.target** for a console command-line interface rather than a GUI desktop interface. As the root user on your test host, change to the directory where the systemd configuration is maintained and do a quick listing:
+
+
+```
+[root@testvm1 ~]# cd /etc/systemd/system/ ; ll
+drwxr-xr-x. 2 root root 4096 Apr 25 2018 basic.target.wants
+<snip>
+lrwxrwxrwx. 1 root root 36 Aug 13 16:23 default.target -> /lib/systemd/system/graphical.target
+lrwxrwxrwx. 1 root root 39 Apr 25 2018 display-manager.service -> /usr/lib/systemd/system/lightdm.service
+drwxr-xr-x. 2 root root 4096 Apr 25 2018 getty.target.wants
+drwxr-xr-x. 2 root root 4096 Aug 18 10:16 graphical.target.wants
+drwxr-xr-x. 2 root root 4096 Apr 25 2018 local-fs.target.wants
+drwxr-xr-x. 2 root root 4096 Oct 30 16:54 multi-user.target.wants
+<snip>
+[root@testvm1 system]#
+```
+
+I shortened this listing to highlight a few important things that will help explain how systemd manages the boot process. You should be able to see the entire list of directories and links on your virtual machine.
+
+The **default.target** entry is a symbolic link (symlink, soft link) to the directory **/lib/systemd/system/graphical.target**. List that directory to see what else is there:
+
+
+```
+`[root@testvm1 system]# ll /lib/systemd/system/ | less`
+```
+
+You should see files, directories, and more links in this listing, but look specifically for **multi-user.target** and **graphical.target**. Now display the contents of **default.target**, which is a link to **/lib/systemd/system/graphical.target**:
+
+
+```
+[root@testvm1 system]# cat default.target
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Graphical Interface
+Documentation=man:systemd.special(7)
+Requires=multi-user.target
+Wants=display-manager.service
+Conflicts=rescue.service rescue.target
+After=multi-user.target rescue.service rescue.target display-manager.service
+AllowIsolate=yes
+[root@testvm1 system]#
+```
+
+This link to the **graphical.target** file describes all of the prerequisites and requirements that the graphical user interface requires. I will explore at least some of these options in the next article in this series.
+
+To enable the host to boot to multi-user mode, you need to delete the existing link and create a new one that points to the correct target. Make the [PWD][5] **/etc/systemd/system**, if it is not already:
+
+
+```
+[root@testvm1 system]# rm -f default.target
+[root@testvm1 system]# ln -s /lib/systemd/system/multi-user.target default.target
+```
+
+List the **default.target** link to verify that it links to the correct file:
+
+
+```
+[root@testvm1 system]# ll default.target
+lrwxrwxrwx 1 root root 37 Nov 28 16:08 default.target -> /lib/systemd/system/multi-user.target
+[root@testvm1 system]#
+```
+
+If your link does not look exactly like this, delete it and try again. List the content of the **default.target** link:
+
+
+```
+[root@testvm1 system]# cat default.target
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Multi-User System
+Documentation=man:systemd.special(7)
+Requires=basic.target
+Conflicts=rescue.service rescue.target
+After=basic.target rescue.service rescue.target
+AllowIsolate=yes
+[root@testvm1 system]#
+```
+
+The **default.target**—which is really a link to the **multi-user.target** at this point—now has different requirements in the **[Unit]** section. It does not require the graphical display manager.
+
+Reboot. Your virtual machine should boot to the console login for virtual console 1, which is identified on the display as tty1. Now that you know how to change the default target, change it back to the **graphical.target** using a command designed for the purpose.
+
+First, check the current default target:
+
+
+```
+[root@testvm1 ~]# systemctl get-default
+multi-user.target
+[root@testvm1 ~]# systemctl set-default graphical.target
+Removed /etc/systemd/system/default.target.
+Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/graphical.target.
+[root@testvm1 ~]#
+```
+
+Enter the following command to go directly to the **graphical.target** and the display manager login page without having to reboot:
+
+
+```
+`[root@testvm1 system]# systemctl isolate default.target`
+```
+
+I do not know why the term "isolate" was chosen for this sub-command by systemd's developers. My research indicates that it may refer to running the specified target but "isolating" and terminating all other targets that are not required to support the target. However, the effect is to switch targets from one run target to another—in this case, from the multi-user target to the graphical target. The command above is equivalent to the old init 5 command in SystemV start scripts and the init program.
+
+Log into the GUI desktop, and verify that it is working as it should.
+
+### Summing up
+
+This article explored the Linux systemd startup sequence and started to explore two important systemd tools, **systemctl** and **journalctl**. It also explained how to switch from one target to another and to change the default target.
+
+The next article in this series will create a new systemd unit and configure it to run during startup. It will also look at some of the configuration options that help determine where in the sequence a particular unit will start, for example, after networking is up and running.
+
+### Resources
+
+There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.
+
+ * The Fedora Project has a good, practical [guide][6] [to systemd][6]. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
+ * The Fedora Project also has a good [cheat sheet][7] that cross-references the old SystemV commands to comparable systemd ones.
+ * For detailed technical information about systemd and the reasons for creating it, check out [Freedesktop.org][8]'s [description of systemd][9].
+ * [Linux.com][10]'s "More systemd fun" offers more advanced systemd [information and tips][11].
+
+
+
+There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
+
+ * [Rethinking PID 1][12]
+ * [systemd for Administrators, Part I][13]
+ * [systemd for Administrators, Part II][14]
+ * [systemd for Administrators, Part III][15]
+ * [systemd for Administrators, Part IV][16]
+ * [systemd for Administrators, Part V][17]
+ * [systemd for Administrators, Part VI][18]
+ * [systemd for Administrators, Part VII][19]
+ * [systemd for Administrators, Part VIII][20]
+ * [systemd for Administrators, Part IX][21]
+ * [systemd for Administrators, Part X][22]
+ * [systemd for Administrators, Part XI][23]
+
+
+
+Alison Chiaken, a Linux kernel and systems programmer at Mentor Graphics, offers a preview of her...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/systemd-startup
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/start_line.jpg?itok=9reaaW6m (People at the start line of a race)
+[2]: https://opensource.com/article/20/4/systemd
+[3]: http://www.gnu.org/software/grub/manual/grub
+[4]: mailto:mockbuild@bkernel03.phx2.fedoraproject.org
+[5]: https://en.wikipedia.org/wiki/Pwd
+[6]: https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html
+[7]: https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
+[8]: http://Freedesktop.org
+[9]: http://www.freedesktop.org/wiki/Software/systemd
+[10]: http://Linux.com
+[11]: https://www.linux.com/training-tutorials/more-systemd-fun-blame-game-and-stopping-services-prejudice/
+[12]: http://0pointer.de/blog/projects/systemd.html
+[13]: http://0pointer.de/blog/projects/systemd-for-admins-1.html
+[14]: http://0pointer.de/blog/projects/systemd-for-admins-2.html
+[15]: http://0pointer.de/blog/projects/systemd-for-admins-3.html
+[16]: http://0pointer.de/blog/projects/systemd-for-admins-4.html
+[17]: http://0pointer.de/blog/projects/three-levels-of-off.html
+[18]: http://0pointer.de/blog/projects/changing-roots
+[19]: http://0pointer.de/blog/projects/blame-game.html
+[20]: http://0pointer.de/blog/projects/the-new-configuration-files.html
+[21]: http://0pointer.de/blog/projects/on-etc-sysinit.html
+[22]: http://0pointer.de/blog/projects/instances.html
+[23]: http://0pointer.de/blog/projects/inetd.html
diff --git a/sources/tech/20200505 8 open source video games to play.md b/sources/tech/20200505 8 open source video games to play.md
new file mode 100644
index 0000000000..ac0577d96b
--- /dev/null
+++ b/sources/tech/20200505 8 open source video games to play.md
@@ -0,0 +1,116 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (8 open source video games to play)
+[#]: via: (https://opensource.com/article/20/5/open-source-fps-games)
+[#]: author: (Aman Gaur https://opensource.com/users/amangaur)
+
+8 open source video games to play
+======
+These games are fun and free to play, a way to connect with friends, and
+an opportunity to make an old favorite even better.
+![Gaming on a grid with penguin pawns][1]
+
+Video games are a big business. That's great for the industry's longevity—not to mention for all the people working in programming and graphics. But it can take a lot of work, time, and money to keep up with all the latest gaming crazes. If you feel like playing a few quick rounds of a video game without investing in a new console or game franchise, then you'll be happy to know that there are plenty of open source combat games you can download, play, share, and even modify (if you're inclined to programming) for free.
+
+First-person shooters (FPS) are one of the most popular categories of video games. They are centered around the perspective of the protagonist (the player), and they often offer weapon-based advancement. As you get better at the game, you survive longer, you get better weapons, and you increase your power. FPS games have a distinct look and feel, which is reflected in the category's name: players see everything—their weapons and the game world—in first person, as if they're looking through their player character's eyes.
+
+If you want to give one a try, check out the following eight great open source FPS games.
+
+### Xonotic
+
+![Xonotic][2]
+
+[Xonotic][3] is a fast-paced, arena-based FPS game. It is a popular game in the open source world. One reason could be the fact that it has never been a mainstream game. It offers a variety of weapons and enemies that are thrown right at you mercilessly from the start. Demanding quick action and response, it is an experience that will keep you on the edge of your seats. The game is available under the GPLv3+ license.
+
+### Wolfenstein Enemy Territory
+
+![Wolfenstein Enemy Territory][4]
+
+Wolfenstein has been a major franchise in gaming for many years. If you are a fan of gore and glory, then you've probably already heard of this game (if not, you'll love it once you try it). [Wolfenstein Enemy Territory][5] is an early iteration of the popular World War II game. It became free to play in 2003, and its [source code][6] is provided under the GPLv3. To play, however, you must own the game data (or recreate it yourself) separately (which remains under its original EULA).
+
+### Doom
+
+![Doom][7]
+
+[Doom][8] is a wildly popular game that was also an early example of games on Linux—way back in 2004. There are many iterations of the game, many of which have been released as open source. The game is about acquiring a teleportation device that's been captured by demons, so the violence, while gory, is low on realism. The source code for the game was provided under the GPL, but many versions require that you own the game for the game assets. There are dozens of ports and adaptations, including [Freedoom][9] (with free assets), [Dhewm3][10], [RBDoom-3-BFG][11], and many more. Try a few and pick your favorite!
+
+### Smokin' Guns
+
+![Smokin' Guns][12]
+
+If you're a fan of the Old West and six-shooters, this FPS is for you. From cowboys to gunslingers and with a captivating background score, [Smokin' Guns][13] has it all. It's a semi-realistic simulation of the old spaghetti western. On your way through the game, you face multiple enemies and get multiple weapons, so there's always the promise of excitement and danger around the corner. The game is free and open source under the terms of the GPLv2.
+
+### Nexuiz
+
+![Nexuiz][14]
+
+[Nexuiz][15] (classic) is another great FPS that's free to play on multiple platforms. The game is based on the Quake engine and has been made open source under the GNU GPLv2. The game offers multiple modes, including online, LAN party, and bot training. The game features sophisticated weapons and fast action. It's brutal and exciting, with an objective: kill as many opponents as possible before they get you.
+
+Note that the open source version of Nexuiz is not the same as the version built on CryEngine3 that is sold on Steam.
+
+### .kkrieger
+
+![kkrieger][16]
+
+[.Kkrieger][17] was developed in 2004 by .theprodukkt, a German demogroup. The game was developed using an unreleased (at the time) engine known as Werkkzeug. This game might feel a little slow to many, but it still offers an intense experience. The approaching enemies are slow, but their sheer number makes it confusing to know which one to take down first. It's an onslaught, and you have to shoot through layers of enemies before you reach the final boss. It was released in a rather raw form on [GitHub][18] by its creators under a BSD license with some public domain components.
+
+### Warsow
+
+![Warsow][19]
+
+If you've ever played Borderlands 2, then imagine [Warsow][20] as an arena-style Borderlands. The game is built on a modernized Quake II engine, and its plot takes a simple approach: Kill as many opponents as possible. The team with the most number of kills wins. Despite its simplicity, it features amazing weaponry and lots of great trick moves, like circle jumping, bunny hopping, double jumping, ramp sliding, and so on. It makes for an engaging multiplayer session, and it's been recognized by multiple online leagues as a worthy game for their competitions. Get the source code from [GitHub][21] or install the game from your software repository.
+
+### World of Padman
+
+![World of Padman][22]
+
+[The World of Padman][23] may be the last game on this list, but it's one of the most unique. Designed by PadWorld Entertainment, World of Padman takes a different twist graphically and introduces you to quirky and whimsical characters in a colorful (albeit cartoonishly violent) world. It's based on the ioquake3 engine, and its unique style and uproarious gameplay have earned it a featured place in multiple gaming magazines. You can download the source code from [GitHub][24].
+
+### Give one a shot
+
+A game that becomes open source can act as a template for something great, whether it's a wholly open source version of an old classic, a remix of a beloved game, or an entirely new platform built on an old reliable engine.
+
+Open source gaming is important for many reasons: it provides users with a fun diversion, a way to connect with friends, and an opportunity for programmers and designers to hack within an existing framework. If titles like Doom weren't made open source, a little bit of video game history would be lost. Instead, it endures and has the opportunity to grow even more.
+
+Try an open source game, and watch your six.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/open-source-fps-games
+
+作者:[Aman Gaur][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/amangaur
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/game_pawn_grid_linux.png?itok=4gERzRkg (Gaming on a grid with penguin pawns)
+[2]: https://opensource.com/sites/default/files/uploads/xonotic.jpg (Xonotic)
+[3]: https://www.xonotic.org/download/
+[4]: https://opensource.com/sites/default/files/uploads/wolfensteinenemyterritory.jpg (Wolfenstein Enemy Territory)
+[5]: https://www.splashdamage.com/games/wolfenstein-enemy-territory/
+[6]: https://github.com/id-Software/Enemy-Territory
+[7]: https://opensource.com/sites/default/files/uploads/doom.jpg (Doom)
+[8]: https://github.com/id-Software/DOOM
+[9]: https://freedoom.github.io/
+[10]: https://dhewm3.org/
+[11]: https://github.com/RobertBeckebans/RBDOOM-3-BFG/
+[12]: https://opensource.com/sites/default/files/uploads/smokinguns.jpg (Smokin' Guns)
+[13]: https://www.smokin-guns.org/downloads
+[14]: https://opensource.com/sites/default/files/uploads/nexuiz.jpg (Nexuiz)
+[15]: https://sourceforge.net/projects/nexuiz/
+[16]: https://opensource.com/sites/default/files/uploads/kkrieger.jpg (kkrieger)
+[17]: https://web.archive.org/web/20120204065621/http://www.theprodukkt.com/kkrieger
+[18]: https://github.com/farbrausch/fr_public
+[19]: https://opensource.com/sites/default/files/uploads/warsow.jpg (Warsow)
+[20]: https://www.warsow.net/download
+[21]: https://github.com/Warsow
+[22]: https://opensource.com/sites/default/files/uploads/padman.jpg (World of Padman)
+[23]: https://worldofpadman.net/en/
+[24]: https://github.com/PadWorld-Entertainment
diff --git a/sources/tech/20200505 Analyzing data science code with R and Emacs.md b/sources/tech/20200505 Analyzing data science code with R and Emacs.md
new file mode 100644
index 0000000000..ebcfadbe92
--- /dev/null
+++ b/sources/tech/20200505 Analyzing data science code with R and Emacs.md
@@ -0,0 +1,133 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Analyzing data science code with R and Emacs)
+[#]: via: (https://opensource.com/article/20/5/r-emacs-data-science)
+[#]: author: (Peter Prevos https://opensource.com/users/danderzei)
+
+Analyzing data science code with R and Emacs
+======
+Emacs' versatility and extensibility bring the editor's full power into
+play for writing data science code.
+![metrics and data shown on a computer screen][1]
+
+Way back in 2012, _Harvard Business Review_ published an article that proclaimed "data scientist" to be the [sexiest job][2] of the 21st century. Interest in data science has exploded since then. Many great open source projects, such as [Python][3] and the [R language][4] for statistical computing, have facilitated the rapid developments in how we analyze data.
+
+I started my career using pencil and paper and moved to spreadsheets. Now the R language is my weapon of choice when I need to create value from data. Emacs is another one of my favorite tools. This article briefly explains how to use the [Emacs Speaks Statistics][5] (ESS) package to get started with developing R projects in this venerable editor.
+
+The vast majority of R developers use the [RStudio][6] IDE to manage their projects. RStudio is a powerful open source editor with specialized functionality to develop data science projects. RStudio is a great integrated development environment (IDE), but its editing functions are limited.
+
+Using Emacs to write data science code means that you have access to the full power of this extensible editor. I prefer using Emacs for my data science projects because I can do many other tasks within the same application, leveraging the multifunctionality of this venerable editor. If you are just getting started with Emacs, then please first read Seth Kenlon's [Emacs getting started][7] article.
+
+### Setting up Emacs for R
+
+Emacs is an almost infinitely extensible text editor, which unfortunately means that many things don't work the way you want them to out of the box. Before you can write and execute R scripts, you need to install some packages and configure them. The ESS package provides an interface between Emacs and R. Other packages, such as [Company][8] and [highlight-parentheses][9] help with completion and balancing parentheses.
+
+Emacs uses a version of Lisp for configuration. The lines of [Emacs Lisp][10] code below install the required extensions and define a minimal configuration to get you started. These lines were tested for GNU Emacs version 26.3.
+
+Copy these lines and save them in a file named **init.el** in your **.emacs.d** folder. This is the folder that Emacs uses to store configurations, including the [init file][11]. If you already have an init file, then you can append these lines to your config. This minimal configuration is enough to get you started.
+
+
+```
+;; Elisp file for R coding with Emacs
+
+;; Add MELPA repository and initialise the package manager
+(require 'package)
+(add-to-list 'package-archives
+ '("melpa" . ""))
+(package-initialize)
+
+;; Install use-package,in case it does not exist yet
+;; The use-package software will install all other packages as required
+(unless (package-installed-p 'use-package)
+ (package-refresh-contents)
+ (package-install 'use-package))
+
+;; ESS configurationEmacs Speaks Statistics
+(use-package ess
+ :ensure t
+)
+
+;; Auto completion
+(use-package company
+ :ensure t
+ :config
+ (setq company-idle-delay 0)
+ (setq company-minimum-prefix-length 2)
+ (global-company-mode t)
+)
+
+; Parentheses
+(use-package highlight-parentheses
+ :ensure t
+ :config
+ (progn
+ (highlight-parentheses-mode)
+ (global-highlight-parentheses-mode))
+ )
+```
+
+### Using the R console
+
+To start an R console session, press **M-x R** and hit **Enter** (**M** is the Emacs way to denote the **Alt** or **Command** key). ESS will ask you to nominate a working directory, which defaults to the folder of the current buffer. You can use more than one console in the same Emacs session by repeating the R command.
+
+Emacs opens a new buffer for your new R console. You can also use the **Up** and **Down** arrow keys to go to previous lines and re-run them. Use the **Ctrl** and **Up/Down** arrow keys to recycle old commands.
+
+The Company ("complete anything") package manages autocompletion in both the console and R scripts. When entering a function, the mini-buffer at the bottom of the screen shows the relevant parameters. When the autocompletion dropdown menu appears, you can press **F1** to view the chosen option's Help file before you select it.
+
+The [highlight-parentheses][9] package does what its name suggests. Several other Emacs packages are available to help you balance parentheses and other structural elements in your code.
+
+### Writing R scripts
+
+Emacs recognizes R mode for any buffer with a **.R** extension (the file extension is case-sensitive). Open or create a new file with the **C-x C-f** shortcut and type the path and file name. You can start writing your code and use all of the powerful editing techniques that Emacs provides.
+
+Several functions are available to evaluate the code. You can evaluate each line separately with **C-<return>**, while **C-c C-c** will evaluate a contiguous region. Keying **C-c C-b** will evaluate the whole buffer.
+
+When you evaluate some code, Emacs will use any running console or ask you to open a new console to run the code.
+
+The output of any plotting functions appears in a window outside of Emacs. If you prefer to view the output within Emacs, then you need to save the output to disk and open the resulting file in a separate buffer.
+
+![Literate programming in Org mode, the ESS buffer, and graphics output.][12]
+
+Literate programming in Org mode, the ESS buffer, and graphics output.
+
+### Advanced use
+
+This article provides a brief introduction to using R in Emacs. Many parameters can be fine-tuned to make Emacs behave according to your preferences, but it would take too much space to cover them here. The [ESS manual][13] describes these in detail. You can also extend functionality with additional packages.
+
+Org mode can integrate R code, providing a productive platform for literate programming. If you prefer to use RMarkdown, the [Polymode][14] package has you covered.
+
+Emacs has various packages to make your editing experience more efficient. The best part of using Emacs to write R code is that the program is more than just an IDE; it is a malleable computer system that you can configure to match your favorite workflow.
+
+Learning how to configure Emacs can be daunting. The best way to learn quickly is to copy ideas from people who share their configurations. Miles McBain manages a [list of Emacs configurations][15] that could be useful if you want to explore using the R language in Emacs further.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/r-emacs-data-science
+
+作者:[Peter Prevos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/danderzei
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/metrics_data_dashboard_system_computer_analytics.png?itok=oxAeIEI- (metrics and data shown on a computer screen)
+[2]: https://hbr.org/2012/10/data-scientist-the-sexiest-job-of-the-21st-century
+[3]: https://www.python.org/
+[4]: https://www.r-project.org/
+[5]: https://ess.r-project.org/
+[6]: https://opensource.com/article/18/2/getting-started-RStudio-IDE
+[7]: https://opensource.com/article/20/3/getting-started-emacs
+[8]: https://company-mode.github.io/
+[9]: https://github.com/tsdh/highlight-parentheses.el
+[10]: https://en.wikipedia.org/wiki/Emacs_Lisp
+[11]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html
+[12]: https://opensource.com/sites/default/files/uploads/r-ess-screenshot.jpg (Literate programming in Org mode, the ESS buffer, and graphics output.)
+[13]: https://ess.r-project.org/index.php?Section=documentation&subSection=manuals
+[14]: https://github.com/polymode/polymode
+[15]: https://github.com/MilesMcBain/esscss
diff --git a/sources/tech/20200507 Using the systemctl command to manage systemd units.md b/sources/tech/20200507 Using the systemctl command to manage systemd units.md
new file mode 100644
index 0000000000..e305cee36c
--- /dev/null
+++ b/sources/tech/20200507 Using the systemctl command to manage systemd units.md
@@ -0,0 +1,618 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Using the systemctl command to manage systemd units)
+[#]: via: (https://opensource.com/article/20/5/systemd-units)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Using the systemctl command to manage systemd units
+======
+Units are the basis of everything in systemd.
+![woman on laptop sitting at the window][1]
+
+In the first two articles in this series, I explored the Linux systemd startup sequence. In the [first article][2], I looked at systemd's functions and architecture and the controversy around its role as a replacement for the old SystemV init program and startup scripts. And in the [second article][3], I examined two important systemd tools, systemctl and journalctl, and explained how to switch from one target to another and to change the default target.
+
+In this third article, I'll look at systemd units in more detail and how to use the systemctl command to explore and manage units. I'll also explain how to stop and disable units and how to create a new systemd mount unit to mount a new filesystem and enable it to initiate during startup.
+
+### Preparation
+
+All of the experiments in this article should be done as the root user (unless otherwise specified). Some of the commands that simply list various systemd units can be performed by non-root users, but the commands that make changes cannot. Make sure to do all of these experiments only on non-production hosts or virtual machines (VMs).
+
+One of these experiments requires the sysstat package, so install it before you move on. For Fedora and other Red Hat-based distributions you can install sysstat with:
+
+
+```
+`dnf -y install sysstat`
+```
+
+The sysstat RPM installs several statistical tools that can be used for problem determination. One is [System Activity Report][4] (SAR), which records many system performance data points at regular intervals (every 10 minutes by default). Rather than run as a daemon in the background, the sysstat package installs two systemd timers. One timer runs every 10 minutes to collect data, and the other runs once a day to aggregate the daily data. In this article, I will look briefly at these timers but wait to explain how to create a timer in a future article.
+
+### systemd suite
+
+The fact is, systemd is more than just one program. It is a large suite of programs all designed to work together to manage nearly every aspect of a running Linux system. A full exposition of systemd would take a book on its own. Most of us do not need to understand all of the details about how all of systemd's components fit together, so I will focus on the programs and components that enable you to manage various Linux services and deal with log files and journals.
+
+### Practical structure
+
+The structure of systemd—outside of its executable files—is contained in its many configuration files. Although these files have different names and identifier extensions, they are all called "unit" files. Units are the basis of everything systemd.
+
+Unit files are ASCII plain-text files that are accessible to and can be created or modified by a sysadmin. There are a number of unit file types, and each has its own man page. Figure 1 lists some of these unit file types by their filename extensions and a short description of each.
+
+systemd unit | Description
+---|---
+.automount | The **.automount** units are used to implement on-demand (i.e., plug and play) and mounting of filesystem units in parallel during startup.
+.device | The **.device** unit files define hardware and virtual devices that are exposed to the sysadmin in the **/dev/directory**. Not all devices have unit files; typically, block devices such as hard drives, network devices, and some others have unit files.
+.mount | The **.mount** unit defines a mount point on the Linux filesystem directory structure.
+.scope | The **.scope** unit defines and manages a set of system processes. This unit is not configured using unit files, rather it is created programmatically. Per the **systemd.scope** man page, “The main purpose of scope units is grouping worker processes of a system service for organization and for managing resources.”
+.service | The **.service** unit files define processes that are managed by systemd. These include services such as crond cups (Common Unix Printing System), iptables, multiple logical volume management (LVM) services, NetworkManager, and more.
+.slice | The **.slice** unit defines a “slice,” which is a conceptual division of system resources that are related to a group of processes. You can think of all system resources as a pie and this subset of resources as a “slice” out of that pie.
+.socket | The **.socket** units define interprocess communication sockets, such as network sockets.
+.swap | The **.swap** units define swap devices or files.
+.target | The **.target** units define groups of unit files that define startup synchronization points, runlevels, and services. Target units define the services and other units that must be active in order to start successfully.
+.timer | The **.timer** unit defines timers that can initiate program execution at specified times.
+
+### systemctl
+
+I looked at systemd's startup functions in the [second article][3], and here I'll explore its service management functions a bit further. systemd provides the **systemctl** command that is used to start and stop services, configure them to launch (or not) at system startup, and monitor the current status of running services.
+
+In a terminal session as the root user, ensure that root's home directory ( **~** ) is the [PWD][5]. To begin looking at units in various ways, list all of the loaded and active systemd units. systemctl automatically pipes its [stdout][6] data stream through the **less** pager, so you don't have to:
+
+
+```
+[root@testvm1 ~]# systemctl
+UNIT LOAD ACTIVE SUB DESCRIPTION
+proc-sys-fs-binfmt_misc.automount loaded active running Arbitrary Executable File>
+sys-devices-pci0000:00-0000:00:01.1-ata7-host6-target6:0:0-6:0:0:0-block-sr0.device loaded a>
+sys-devices-pci0000:00-0000:00:03.0-net-enp0s3.device loaded active plugged 82540EM Gigabi>
+sys-devices-pci0000:00-0000:00:05.0-sound-card0.device loaded active plugged 82801AA AC'97>
+sys-devices-pci0000:00-0000:00:08.0-net-enp0s8.device loaded active plugged 82540EM Gigabi>
+sys-devices-pci0000:00-0000:00:0d.0-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda1.device loa>
+sys-devices-pci0000:00-0000:00:0d.0-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda2.device loa>
+<snip – removed lots of lines of data from here>
+
+LOAD = Reflects whether the unit definition was properly loaded.
+ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
+SUB = The low-level unit activation state, values depend on unit type.
+
+206 loaded units listed. Pass --all to see loaded but inactive units, too.
+To show all installed unit files use 'systemctl list-unit-files'.
+```
+
+As you scroll through the data in your terminal session, look for some specific things. The first section lists devices such as hard drives, sound cards, network interface cards, and TTY devices. Another section shows the filesystem mount points. Other sections include various services and a list of all loaded and active targets.
+
+The sysstat timers at the bottom of the output are used to collect and generate daily system activity summaries for SAR. SAR is a very useful problem-solving tool. (You can learn more about it in Chapter 13 of my book [_Using and Administering Linux: Volume 1, Zero to SysAdmin: Getting Started_][7].)
+
+Near the very bottom, three lines describe the meanings of the statuses (loaded, active, and sub). Press **q** to exit the pager.
+
+Use the following command (as suggested in the last line of the output above) to see all the units that are installed, whether or not they are loaded. I won't reproduce the output here, because you can scroll through it on your own. The systemctl program has an excellent tab-completion facility that makes it easy to enter complex commands without needing to memorize all the options:
+
+
+```
+`[root@testvm1 ~]# systemctl list-unit-files`
+```
+
+You can see that some units are disabled. Table 1 in the man page for systemctl lists and provides short descriptions of the entries you might see in this listing. Use the **-t** (type) option to view just the timer units:
+
+
+```
+[root@testvm1 ~]# systemctl list-unit-files -t timer
+UNIT FILE STATE
+[chrony-dnssrv@.timer][8] disabled
+dnf-makecache.timer enabled
+fstrim.timer disabled
+logrotate.timer disabled
+logwatch.timer disabled
+[mdadm-last-resort@.timer][9] static
+mlocate-updatedb.timer enabled
+sysstat-collect.timer enabled
+sysstat-summary.timer enabled
+systemd-tmpfiles-clean.timer static
+unbound-anchor.timer enabled
+```
+
+You could do the same thing with this alternative, which provides considerably more detail:
+
+
+```
+[root@testvm1 ~]# systemctl list-timers
+Thu 2020-04-16 09:06:20 EDT 3min 59s left n/a n/a systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
+Thu 2020-04-16 10:02:01 EDT 59min left Thu 2020-04-16 09:01:32 EDT 49s ago dnf-makecache.timer dnf-makecache.service
+Thu 2020-04-16 13:00:00 EDT 3h 57min left n/a n/a sysstat-collect.timer sysstat-collect.service
+Fri 2020-04-17 00:00:00 EDT 14h left Thu 2020-04-16 12:51:37 EDT 3h 49min left mlocate-updatedb.timer mlocate-updatedb.service
+Fri 2020-04-17 00:00:00 EDT 14h left Thu 2020-04-16 12:51:37 EDT 3h 49min left unbound-anchor.timer unbound-anchor.service
+Fri 2020-04-17 00:07:00 EDT 15h left n/a n/a sysstat-summary.timer sysstat-summary.service
+
+6 timers listed.
+Pass --all to see loaded but inactive timers, too.
+[root@testvm1 ~]#
+```
+
+Although there is no option to do systemctl list-mounts, you can list the mount point unit files:
+
+
+```
+[root@testvm1 ~]# systemctl list-unit-files -t mount
+UNIT FILE STATE
+-.mount generated
+boot.mount generated
+dev-hugepages.mount static
+dev-mqueue.mount static
+home.mount generated
+proc-fs-nfsd.mount static
+proc-sys-fs-binfmt_misc.mount disabled
+run-vmblock\x2dfuse.mount disabled
+sys-fs-fuse-connections.mount static
+sys-kernel-config.mount static
+sys-kernel-debug.mount static
+tmp.mount generated
+usr.mount generated
+var-lib-nfs-rpc_pipefs.mount static
+var.mount generated
+
+15 unit files listed.
+[root@testvm1 ~]#
+```
+
+The STATE column in this data stream is interesting and requires a bit of explanation. The "generated" states indicate that the mount unit was generated on the fly during startup using the information in **/etc/fstab**. The program that generates these mount units is **/lib/systemd/system-generators/systemd-fstab-generator,** along with other tools that generate a number of other unit types. The "static" mount units are for filesystems like **/proc** and **/sys**, and the files for these are located in the **/usr/lib/systemd/system** directory.
+
+Now, look at the service units. This command will show all services installed on the host, whether or not they are active:
+
+
+```
+`[root@testvm1 ~]# systemctl --all -t service`
+```
+
+The bottom of this listing of service units displays 166 as the total number of loaded units on my host. Your number will probably differ.
+
+Unit files do not have a filename extension (such as **.unit**) to help identify them, so you can generalize that most configuration files that belong to systemd are unit files of one type or another. The few remaining files are mostly **.conf** files located in **/etc/systemd**.
+
+Unit files are stored in the **/usr/lib/systemd** directory and its subdirectories, while the **/etc/systemd/** directory and its subdirectories contain symbolic links to the unit files necessary to the local configuration of this host.
+
+To explore this, make **/etc/systemd** the PWD and list its contents. Then make **/etc/systemd/system** the PWD and list its contents, and list the contents of at least a couple of the current PWD's subdirectories.
+
+Take a look at the **default.target** file, which determines which runlevel target the system will boot to. In the second article in this series, I explained how to change the default target from the GUI (**graphical.target**) to the command-line only (**multi-user.target**) target. The **default.target** file on my test VM is simply a symlink to **/usr/lib/systemd/system/graphical.target**.
+
+Take a few minutes to examine the contents of the **/etc/systemd/system/default.target** file:
+
+
+```
+[root@testvm1 system]# cat default.target
+# SPDX-License-Identifier: LGPL-2.1+
+#
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+
+[Unit]
+Description=Graphical Interface
+Documentation=man:systemd.special(7)
+Requires=multi-user.target
+Wants=display-manager.service
+Conflicts=rescue.service rescue.target
+After=multi-user.target rescue.service rescue.target display-manager.service
+AllowIsolate=yes
+```
+
+Note that this requires the **multi-user.target**; the **graphical.target** cannot start if the **multi-user.target** is not already up and running. It also says it "wants" the **display-manager.service** unit. A "want" does not need to be fulfilled in order for the unit to start successfully. If the "want" cannot be fulfilled, it will be ignored by systemd, and the rest of the target will start regardless.
+
+The subdirectories in **/etc/systemd/system** are lists of wants for various targets. Take a few minutes to explore the files and their contents in the **/etc/systemd/system/graphical.target.wants** directory.
+
+The **systemd.unit** man page contains a lot of good information about unit files, their structure, the sections they can be divided into, and the options that can be used. It also lists many of the unit types, all of which have their own man pages. If you want to interpret a unit file, this would be a good place to start.
+
+### Service units
+
+A Fedora installation usually installs and enables services that particular hosts do not need for normal operation. Conversely, sometimes it doesn't include services that need to be installed, enabled, and started. Services that are not needed for the Linux host to function as desired, but which are installed and possibly running, represent a security risk and should—at minimum—be stopped and disabled and—at best—should be uninstalled.
+
+The systemctl command is used to manage systemd units, including services, targets, mounts, and more. Take a closer look at the list of services to identify services that will never be used:
+
+
+```
+[root@testvm1 ~]# systemctl --all -t service
+UNIT LOAD ACTIVE SUB DESCRIPTION
+<snip>
+chronyd.service loaded active running NTP client/server
+crond.service loaded active running Command Scheduler
+cups.service loaded active running CUPS Scheduler
+dbus-daemon.service loaded active running D-Bus System Message Bus
+<snip>
+● ip6tables.service not-found inactive dead ip6tables.service
+● ipset.service not-found inactive dead ipset.service
+● iptables.service not-found inactive dead iptables.service
+<snip>
+firewalld.service loaded active running firewalld - dynamic firewall daemon
+<snip>
+● ntpd.service not-found inactive dead ntpd.service
+● ntpdate.service not-found inactive dead ntpdate.service
+pcscd.service loaded active running PC/SC Smart Card Daemon
+```
+
+I have pruned out most of the output from the command to save space. The services that show "loaded active running" are obvious. The "not-found" services are ones that systemd is aware of but are not installed on the Linux host. If you want to run those services, you must install the packages that contain them.
+
+Note the **pcscd.service** unit. This is the PC/SC smart-card daemon. Its function is to communicate with smart-card readers. Many Linux hosts—including VMs—have no need for this reader nor the service that is loaded and taking up memory and CPU resources. You can stop this service and disable it, so it will not restart on the next boot. First, check its status:
+
+
+```
+[root@testvm1 ~]# systemctl status pcscd.service
+● pcscd.service - PC/SC Smart Card Daemon
+ Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled)
+ Active: active (running) since Fri 2019-05-10 11:28:42 EDT; 3 days ago
+ Docs: man:pcscd(8)
+ Main PID: 24706 (pcscd)
+ Tasks: 6 (limit: 4694)
+ Memory: 1.6M
+ CGroup: /system.slice/pcscd.service
+ └─24706 /usr/sbin/pcscd --foreground --auto-exit
+
+May 10 11:28:42 testvm1 systemd[1]: Started PC/SC Smart Card Daemon.
+```
+
+This data illustrates the additional information systemd provides versus SystemV, which only reports whether or not the service is running. Note that specifying the **.service** unit type is optional. Now stop and disable the service, then re-check its status:
+
+
+```
+[root@testvm1 ~]# systemctl stop pcscd ; systemctl disable pcscd
+Warning: Stopping pcscd.service, but it can still be activated by:
+ pcscd.socket
+Removed /etc/systemd/system/sockets.target.wants/pcscd.socket.
+[root@testvm1 ~]# systemctl status pcscd
+● pcscd.service - PC/SC Smart Card Daemon
+ Loaded: loaded (/usr/lib/systemd/system/pcscd.service; indirect; vendor preset: disabled)
+ Active: failed (Result: exit-code) since Mon 2019-05-13 15:23:15 EDT; 48s ago
+ Docs: man:pcscd(8)
+ Main PID: 24706 (code=exited, status=1/FAILURE)
+
+May 10 11:28:42 testvm1 systemd[1]: Started PC/SC Smart Card Daemon.
+May 13 15:23:15 testvm1 systemd[1]: Stopping PC/SC Smart Card Daemon...
+May 13 15:23:15 testvm1 systemd[1]: pcscd.service: Main process exited, code=exited, status=1/FAIL>
+May 13 15:23:15 testvm1 systemd[1]: pcscd.service: Failed with result 'exit-code'.
+May 13 15:23:15 testvm1 systemd[1]: Stopped PC/SC Smart Card Daemon.
+```
+
+The short log entry display for most services prevents having to search through various log files to locate this type of information. Check the status of the system runlevel targets—specifying the "target" unit type is required:
+
+
+```
+[root@testvm1 ~]# systemctl status multi-user.target
+● multi-user.target - Multi-User System
+ Loaded: loaded (/usr/lib/systemd/system/multi-user.target; static; vendor preset: disabled)
+ Active: active since Thu 2019-05-09 13:27:22 EDT; 4 days ago
+ Docs: man:systemd.special(7)
+
+May 09 13:27:22 testvm1 systemd[1]: Reached target Multi-User System.
+[root@testvm1 ~]# systemctl status graphical.target
+● graphical.target - Graphical Interface
+ Loaded: loaded (/usr/lib/systemd/system/graphical.target; indirect; vendor preset: disabled)
+ Active: active since Thu 2019-05-09 13:27:22 EDT; 4 days ago
+ Docs: man:systemd.special(7)
+
+May 09 13:27:22 testvm1 systemd[1]: Reached target Graphical Interface.
+[root@testvm1 ~]# systemctl status default.target
+● graphical.target - Graphical Interface
+ Loaded: loaded (/usr/lib/systemd/system/graphical.target; indirect; vendor preset: disabled)
+ Active: active since Thu 2019-05-09 13:27:22 EDT; 4 days ago
+ Docs: man:systemd.special(7)
+
+May 09 13:27:22 testvm1 systemd[1]: Reached target Graphical Interface.
+```
+
+The default target is the graphical target. The status of any unit can be checked in this way.
+
+### Mounts the old way
+
+A mount unit defines all of the parameters required to mount a filesystem on a designated mount point. systemd can manage mount units with more flexibility than those using the **/etc/fstab** filesystem configuration file. Despite this, systemd still uses the **/etc/fstab** file for filesystem configuration and mounting purposes. systemd uses the **systemd-fstab-generator** tool to create transient mount units from the data in the **fstab** file.
+
+I will create a new filesystem and a systemd mount unit to mount it. If you have some available disk space on your test system, you can do it along with me.
+
+_Note that the volume group and logical volume names may be different on your test system. Be sure to use the names that are pertinent to your system._
+
+You will need to create a partition or logical volume, then make an EXT4 filesystem on it. Add a label to the filesystem, **TestFS**, and create a directory for a mount point **/TestFS**.
+
+To try this on your own, first, verify that you have free space on the volume group. Here is what that looks like on my VM where I have some space available on the volume group to create a new logical volume:
+
+
+```
+[root@testvm1 ~]# lsblk
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
+sda 8:0 0 120G 0 disk
+├─sda1 8:1 0 4G 0 part /boot
+└─sda2 8:2 0 116G 0 part
+ ├─VG01-root 253:0 0 5G 0 lvm /
+ ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]
+ ├─VG01-usr 253:2 0 30G 0 lvm /usr
+ ├─VG01-home 253:3 0 20G 0 lvm /home
+ ├─VG01-var 253:4 0 20G 0 lvm /var
+ └─VG01-tmp 253:5 0 10G 0 lvm /tmp
+sr0 11:0 1 1024M 0 rom
+[root@testvm1 ~]# vgs
+ VG #PV #LV #SN Attr VSize VFree
+ VG01 1 6 0 wz--n- <116.00g <23.00g
+```
+
+Then create a new volume on **VG01** named **TestFS**. It does not need to be large; 1GB is fine. Then create a filesystem, add the filesystem label, and create the mount point:
+
+
+```
+[root@testvm1 ~]# lvcreate -L 1G -n TestFS VG01
+ Logical volume "TestFS" created.
+[root@testvm1 ~]# mkfs -t ext4 /dev/mapper/VG01-TestFS
+mke2fs 1.45.3 (14-Jul-2019)
+Creating filesystem with 262144 4k blocks and 65536 inodes
+Filesystem UUID: 8718fba9-419f-4915-ab2d-8edf811b5d23
+Superblock backups stored on blocks:
+ 32768, 98304, 163840, 229376
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (8192 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+[root@testvm1 ~]# e2label /dev/mapper/VG01-TestFS TestFS
+[root@testvm1 ~]# mkdir /TestFS
+```
+
+Now, mount the new filesystem:
+
+
+```
+[root@testvm1 ~]# mount /TestFS/
+mount: /TestFS/: can't find in /etc/fstab.
+```
+
+This will not work because you do not have an entry in **/etc/fstab**. You can mount the new filesystem even without the entry in **/etc/fstab** using both the device name (as it appears in **/dev**) and the mount point. Mounting in this manner is simpler than it used to be—it used to require the filesystem type as an argument. The mount command is now smart enough to detect the filesystem type and mount it accordingly.
+
+Try it again:
+
+
+```
+[root@testvm1 ~]# mount /dev/mapper/VG01-TestFS /TestFS/
+[root@testvm1 ~]# lsblk
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
+sda 8:0 0 120G 0 disk
+├─sda1 8:1 0 4G 0 part /boot
+└─sda2 8:2 0 116G 0 part
+ ├─VG01-root 253:0 0 5G 0 lvm /
+ ├─VG01-swap 253:1 0 8G 0 lvm [SWAP]
+ ├─VG01-usr 253:2 0 30G 0 lvm /usr
+ ├─VG01-home 253:3 0 20G 0 lvm /home
+ ├─VG01-var 253:4 0 20G 0 lvm /var
+ ├─VG01-tmp 253:5 0 10G 0 lvm /tmp
+ └─VG01-TestFS 253:6 0 1G 0 lvm /TestFS
+sr0 11:0 1 1024M 0 rom
+[root@testvm1 ~]#
+```
+
+Now the new filesystem is mounted in the proper location. List the mount unit files:
+
+
+```
+`[root@testvm1 ~]# systemctl list-unit-files -t mount`
+```
+
+This command does not show a file for the **/TestFS** filesystem because no file exists for it. The command **systemctl status TestFS.mount** does not display any information about the new filesystem either. You can try it using wildcards with the **systemctl status** command:
+
+
+```
+[root@testvm1 ~]# systemctl status *mount
+● usr.mount - /usr
+ Loaded: loaded (/etc/fstab; generated)
+ Active: active (mounted)
+ Where: /usr
+ What: /dev/mapper/VG01-usr
+ Docs: man:fstab(5)
+ man:systemd-fstab-generator(8)
+
+<SNIP>
+● TestFS.mount - /TestFS
+ Loaded: loaded (/proc/self/mountinfo)
+ Active: active (mounted) since Fri 2020-04-17 16:02:26 EDT; 1min 18s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+
+● run-user-0.mount - /run/user/0
+ Loaded: loaded (/proc/self/mountinfo)
+ Active: active (mounted) since Thu 2020-04-16 08:52:29 EDT; 1 day 5h ago
+ Where: /run/user/0
+ What: tmpfs
+
+● var.mount - /var
+ Loaded: loaded (/etc/fstab; generated)
+ Active: active (mounted) since Thu 2020-04-16 12:51:34 EDT; 1 day 1h ago
+ Where: /var
+ What: /dev/mapper/VG01-var
+ Docs: man:fstab(5)
+ man:systemd-fstab-generator(8)
+ Tasks: 0 (limit: 19166)
+ Memory: 212.0K
+ CPU: 5ms
+ CGroup: /system.slice/var.mount
+```
+
+This command provides some very interesting information about your system's mounts, and your new filesystem shows up. The **/var** and **/usr** filesystems are identified as being generated from **/etc/fstab**, while your new filesystem simply shows that it is loaded and provides the location of the info file in the **/proc/self/mountinfo** file.
+
+Next, automate this mount. First, do it the old-fashioned way by adding an entry in **/etc/fstab**. Later, I'll show you how to do it the new way, which will teach you about creating units and integrating them into the startup sequence.
+
+Unmount **/TestFS** and add the following line to the **/etc/fstab** file:
+
+
+```
+`/dev/mapper/VG01-TestFS /TestFS ext4 defaults 1 2`
+```
+
+Now, mount the filesystem with the simpler **mount** command and list the mount units again:
+
+
+```
+[root@testvm1 ~]# mount /TestFS
+[root@testvm1 ~]# systemctl status *mount
+<SNIP>
+● TestFS.mount - /TestFS
+ Loaded: loaded (/proc/self/mountinfo)
+ Active: active (mounted) since Fri 2020-04-17 16:26:44 EDT; 1min 14s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+<SNIP>
+```
+
+This did not change the information for this mount because the filesystem was manually mounted. Reboot and run the command again, and this time specify **TestFS.mount** rather than using the wildcard. The results for this mount are now consistent with it being mounted at startup:
+
+
+```
+[root@testvm1 ~]# systemctl status TestFS.mount
+● TestFS.mount - /TestFS
+ Loaded: loaded (/etc/fstab; generated)
+ Active: active (mounted) since Fri 2020-04-17 16:30:21 EDT; 1min 38s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+ Docs: man:fstab(5)
+ man:systemd-fstab-generator(8)
+ Tasks: 0 (limit: 19166)
+ Memory: 72.0K
+ CPU: 6ms
+ CGroup: /system.slice/TestFS.mount
+
+Apr 17 16:30:21 testvm1 systemd[1]: Mounting /TestFS...
+Apr 17 16:30:21 testvm1 systemd[1]: Mounted /TestFS.
+```
+
+### Creating a mount unit
+
+Mount units may be configured either with the traditional **/etc/fstab** file or with systemd units. Fedora uses the **fstab** file as it is created during the installation. However, systemd uses the **systemd-fstab-generator** program to translate the **fstab** file into systemd units for each entry in the **fstab** file. Now that you know you can use systemd **.mount** unit files for filesystem mounting, try it out by creating a mount unit for this filesystem.
+
+First, unmount **/TestFS**. Edit the **/etc/fstab** file and delete or comment out the **TestFS** line. Now, create a new file with the name **TestFS.mount** in the **/etc/systemd/system** directory. Edit it to contain the configuration data below. The unit file name and the name of the mount point _must_ be identical, or the mount will fail:
+
+
+```
+# This mount unit is for the TestFS filesystem
+# By David Both
+# Licensed under GPL V2
+# This file should be located in the /etc/systemd/system directory
+
+[Unit]
+Description=TestFS Mount
+
+[Mount]
+What=/dev/mapper/VG01-TestFS
+Where=/TestFS
+Type=ext4
+Options=defaults
+
+[Install]
+WantedBy=multi-user.target
+```
+
+The **Description** line in the **[Unit]** section is for us humans, and it provides the name that's shown when you list mount units with **systemctl -t mount**. The data in the **[Mount]** section of this file contains essentially the same data that would be found in the **fstab** file.
+
+Now enable the mount unit:
+
+
+```
+[root@testvm1 etc]# systemctl enable TestFS.mount
+Created symlink /etc/systemd/system/multi-user.target.wants/TestFS.mount → /etc/systemd/system/TestFS.mount.
+```
+
+This creates the symlink in the **/etc/systemd/system** directory, which will cause this mount unit to be mounted on all subsequent boots. The filesystem has not yet been mounted, so you must "start" it:
+
+
+```
+`[root@testvm1 ~]# systemctl start TestFS.mount`
+```
+
+Verify that the filesystem has been mounted:
+
+
+```
+[root@testvm1 ~]# systemctl status TestFS.mount
+● TestFS.mount - TestFS Mount
+ Loaded: loaded (/etc/systemd/system/TestFS.mount; enabled; vendor preset: disabled)
+ Active: active (mounted) since Sat 2020-04-18 09:59:53 EDT; 14s ago
+ Where: /TestFS
+ What: /dev/mapper/VG01-TestFS
+ Tasks: 0 (limit: 19166)
+ Memory: 76.0K
+ CPU: 3ms
+ CGroup: /system.slice/TestFS.mount
+
+Apr 18 09:59:53 testvm1 systemd[1]: Mounting TestFS Mount...
+Apr 18 09:59:53 testvm1 systemd[1]: Mounted TestFS Mount.
+```
+
+This experiment has been specifically about creating a unit file for a mount, but it can be applied to other types of unit files as well. The details will be different, but the concepts are the same. Yes, I know it is still easier to add a line to the **/etc/fstab** file than it is to create a mount unit. But this is a good example of how to create a unit file because systemd does not have generators for every type of unit.
+
+### In summary
+
+This article looked at systemd units in more detail and how to use the systemctl command to explore and manage units. It also showed how to stop and disable units and create a new systemd mount unit to mount a new filesystem and enable it to initiate during startup.
+
+In the next article in this series, I will take you through a recent problem I had during startup and show you how I circumvented it using systemd.
+
+### Resources
+
+There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.
+
+ * The Fedora Project has a good, practical [guide][10] [to systemd][10]. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
+ * The Fedora Project also has a good [cheat sheet][11] that cross-references the old SystemV commands to comparable systemd ones.
+ * For detailed technical information about systemd and the reasons for creating it, check out [Freedesktop.org][12]'s [description of systemd][13].
+ * [Linux.com][14]'s "More systemd fun" offers more advanced systemd [information and tips][15].
+
+
+
+There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
+
+ * [Rethinking PID 1][16]
+ * [systemd for Administrators, Part I][17]
+ * [systemd for Administrators, Part II][18]
+ * [systemd for Administrators, Part III][19]
+ * [systemd for Administrators, Part IV][20]
+ * [systemd for Administrators, Part V][21]
+ * [systemd for Administrators, Part VI][22]
+ * [systemd for Administrators, Part VII][23]
+ * [systemd for Administrators, Part VIII][24]
+ * [systemd for Administrators, Part IX][25]
+ * [systemd for Administrators, Part X][26]
+ * [systemd for Administrators, Part XI][27]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/systemd-units
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lenovo-thinkpad-laptop-window-focus.png?itok=g0xPm2kD (young woman working on a laptop)
+[2]: https://opensource.com/article/20/4/systemd
+[3]: https://opensource.com/article/20/4/systemd-startup
+[4]: https://en.wikipedia.org/wiki/Sar_%28Unix%29
+[5]: https://en.wikipedia.org/wiki/Pwd
+[6]: https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout)
+[7]: http://www.both.org/?page_id=1183
+[8]: mailto:chrony-dnssrv@.timer
+[9]: mailto:mdadm-last-resort@.timer
+[10]: https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html
+[11]: https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
+[12]: http://Freedesktop.org
+[13]: http://www.freedesktop.org/wiki/Software/systemd
+[14]: http://Linux.com
+[15]: https://www.linux.com/training-tutorials/more-systemd-fun-blame-game-and-stopping-services-prejudice/
+[16]: http://0pointer.de/blog/projects/systemd.html
+[17]: http://0pointer.de/blog/projects/systemd-for-admins-1.html
+[18]: http://0pointer.de/blog/projects/systemd-for-admins-2.html
+[19]: http://0pointer.de/blog/projects/systemd-for-admins-3.html
+[20]: http://0pointer.de/blog/projects/systemd-for-admins-4.html
+[21]: http://0pointer.de/blog/projects/three-levels-of-off.html
+[22]: http://0pointer.de/blog/projects/changing-roots
+[23]: http://0pointer.de/blog/projects/blame-game.html
+[24]: http://0pointer.de/blog/projects/the-new-configuration-files.html
+[25]: http://0pointer.de/blog/projects/on-etc-sysinit.html
+[26]: http://0pointer.de/blog/projects/instances.html
+[27]: http://0pointer.de/blog/projects/inetd.html
diff --git a/sources/tech/20200508 A guide to setting up your Open Source Program Office (OSPO) for success.md b/sources/tech/20200508 A guide to setting up your Open Source Program Office (OSPO) for success.md
new file mode 100644
index 0000000000..ea3aa01866
--- /dev/null
+++ b/sources/tech/20200508 A guide to setting up your Open Source Program Office (OSPO) for success.md
@@ -0,0 +1,193 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (A guide to setting up your Open Source Program Office (OSPO) for success)
+[#]: via: (https://opensource.com/article/20/5/open-source-program-office)
+[#]: author: (J. Manrique Lopez de la Fuente https://opensource.com/users/jsmanrique)
+
+A guide to setting up your Open Source Program Office (OSPO) for success
+======
+Learn how to best grow and maintain your open source communities and
+allies.
+![community team brainstorming ideas][1]
+
+Companies create Open Source Program Offices (OSPO) to manage their relationship with the open source ecosystems they depend on. By understanding the company's open source ecosystem, an OSPO is able to maximize the company's return on investment and reduce the risks of consuming, contributing to, and releasing open source software. Additionally, since the company depends on its open source ecosystem, ensuring its health and sustainability shall ensure the company's health, sustainable growth, and evolution.
+
+### How has OSPO become vital to companies and their open source ecosystem?
+
+Marc Andreessen has said that "software is eating the world," and more recently, it could be said that open source is eating the software world. But how is that process happening?
+
+Companies get involved with open source projects in several ways. These projects comprise the company's open source ecosystem, and their relationships and interactions can be seen through Open Source Software's (OSS) inbound and outbound processes.
+
+From the OSS inbound point of view, companies use it to build their own solutions and their own infrastructure. OSS gets introduced because it's part of the code their technology providers use, or because their own developers add open source components to the company's information technology (IT) infrastructure.
+
+From the OSS outbound point of view, some companies contribute to OSS projects. That contribution could be part of the company's requirements for their solutions that need certain fixes in upstream projects. For example, Samsung contributes to certain graphics-related projects to ensure its hardware has software support once it gets into the market. In some other cases, contributing to OSS is a mechanism to retain talent by allowing the people to contribute to projects different from their daily work.
+
+Some companies release their own open source projects as an outbound OSS process. For companies like Red Hat or GitLab, it would be expected. But, there are increasingly more non-software companies releasing a lot of OSS, like Lyft.
+
+![OSS inbound and outbound processes][2]
+
+OSS inbound and outbound processes
+
+Ultimately, all of these projects involved in the inbound and outbound OSS flow are the company's OSS ecosystem. And like any living being, the company's health and sustainability depend on the ecosystem that surrounds it.
+
+### OSPO responsibilities
+
+Following the species and their ecosystem, people working in the OSPO team could be seen as the rangers in the organization's OSS ecosystem. They take care of the ecosystem and its relationship with the company, to keep everything healthy and sustainable.
+
+When the company consumes open source software projects, they need to be aware of licenses and compliance, to check the project's health, to ensure there are no security flaws, and, in some cases, to identify talented community members for potential hiring processes.
+
+When the company contributes to open source software projects, they need to be sure there are no Intellectual Property (IP) issues, to ensure the company contributions' footprint and its leadership in the projects, and sometimes, also to help talented people stay engaged with the company through their contributions.
+
+And when the company releases and maintains open source projects, they are responsible for ensuring community engagement and growth, for checking there are no IP issues, that the company maintains its footprint and leadership, and perhaps, to attract new talent to the company.
+
+Have you realized the whole set of skills required in an OSPO team? When I've asked people working in OSPO about the size of their teams, the number is around 1 to 5 people per 1,000 developers in the company. That's a small team to monitor a lot of people and their potential OSS related activity.
+
+### How to manage an OSPO
+
+With all these activities in OSPO people's minds and all the resources they need to worry about, how are they able to manage all of this?
+
+There are at least a couple of open source communities with valuable knowledge and resources available for them:
+
+ * The [TODO Group][3] is "an open group of companies who want to collaborate on practices, tools, and other ways to run successful and effective open source projects and programs." For example, they have a complete set of [guides][4] with best practices for and from companies running OSPOS.
+ * The [CHAOSS (Community Health Analytics for Open Source Software)][5] community develops metrics, methodologies, and software for managing open source project health and sustainability. (See more on CHAOSS' active communities and working groups below).
+
+
+
+OSPO managers need to report a lot of information to the rest of the company to answer many questions related to their OSS inbound and outbound processes, i.e., Which projects are we using in our organization? What's the health of those projects? Who are the key people in those projects? Which projects are we contributing to? Which projects are we releasing? How are we dealing with community contributions? Who are the key contributors?
+
+### Data-driven OSPO
+
+As William Edwards Deming said, "Without data, you are just a person with an opinion."
+
+Having opinions is not a bad thing, but having opinions based on data certainly makes it easier to understand, discuss, and determine the processes best suited to your company and its goals. CHAOSS is the recommended community to look to for guidance about metrics strategies and tools.
+
+Recently, the CHAOSS community has released [a new set of metric definitions][6]. These metrics are only subsets of all the ones being discussed in the focus areas of each working group (WG):
+
+ * [Common WG][7]: Defines the metrics that are used by both working groups or are important for community health, but that do not cleanly fit into one of the other existing working groups. Areas of interest include organizational affiliation, responsiveness, and geographic coverage.
+ * [Diversity and Inclusion WG][8]: Gathers experiences regarding diversity and inclusion in open source projects with the goal of understanding, from a qualitative and quantitative point of view, how diversity and inclusion can be measured.
+ * [Evolution WG][9]: Refines the metrics that inform evolution and works with software implementations.
+ * [Risk WG][10]: Refines the metrics that inform risk and works with software implementations.
+ * [Value WG][11]: Focuses on industry-standard metrics for economic value in open source. Their main goal is to publish trusted industry-standard value metrics—a kind of S&P for software development and an authoritative source for metrics significance and industry norms.
+
+
+
+On the tooling side, projects like [Augur][12], [Cregit][13], and [GrimoireLab][14] are the reference tools that report these metrics, but also many others related to OSPO activities. They are also the seed for new tools and solutions provided by the OSS community like [Cauldron.io][15], a SaaS open source solution to ease OSS ecosystem analysis.
+
+![CHAOSS Metrics for 15 years of Unity OSS activity. Source: cauldron.io][16]
+
+CHAOSS Metrics for 15 years of Unity OSS activity. Source: cauldron.io
+
+All these metrics and data are useless without a metrics strategy. Usually, the first approach is to try to measure as much as possible, producing overwhelming reports and dashboards full of charts and data. What is the value of that?
+
+Experience has shown that a very valid approach is the [Goal, Questions, Metrics (GQM)][17] strategy. But how do we put that in practice in an OSPO?
+
+First of all, we need to understand the company's goals when using, consuming, contributing to, or releasing and maintaining OSS projects. The usual goals are related to market positioning, required upstream features development, and talent attraction or retention. Based on these goals, we should write down related questions that can be answered with numbers, like the following:
+
+#### Who/how many are the core maintainers of my OSS ecosystem projects?
+
+![Uber OSS code core, regular, and casual contributors evolution. Source: uber.biterg.io][18]
+
+Uber OSS code core, regular, and casual contributors evolution. Source: uber.biterg.io
+
+People contribute through different mechanisms or tools (code, issues, comments, tests, etc.). Measuring the core contributors (those that have done 80% of the contributions), the regular ones (those that have done 15% of the contributions), and the casual ones (those have made 5% of the contributions) can answer questions related to participation over time, but also how people move between the different buckets. Adding affiliation information helps to identify external core contributors.
+
+#### Where are the contributions happening?
+
+![Uber OSS activity based on location. Source: uber.biterg.io][19]
+
+Uber OSS activity based on location. Source: uber.biterg.io
+
+The growth of OSS ecosystems is also related to OSS projects spread across the world. Understanding that spread helps OSPO, and the company, to manage actions that improve support for people from different countries and regions.
+
+#### What is the company's OSS network?
+
+![Uber OSS network. Source: uber.biterg.io][20]
+
+Uber OSS network. Source: uber.biterg.io
+
+The company's OSS ecosystem includes those projects that the company's people contribute to. Understanding which projects they contribute to offers insight into which technologies or OSS components are interesting to people, and which companies or organizations the company collaborates with.
+
+#### How is the company dealing with contributions?
+
+![Github Pull Requests backlog management index and time to close analysis. Source: uber.biterg.io][21]
+
+Github Pull Requests backlog management index and time to close analysis. Source: uber.biterg.io
+
+One of the goals when releasing OSS projects is to grow the community around them. Measuring how the company handles contributions to its projects from outside its boundaries helps to understand how "welcoming" it is and identifies mentors (or bottlenecks) and opportunities to lower the barrier to contribute.
+
+#### Consumers vs. maintainers
+
+Over the last months, we have been hearing that corporations are taking OSS for free without contributing back. The typical arguments are that these corporations are making millions of dollars thanks to free work, plus the issue of OSS project maintainer burnout due to users' complaints and requests for free support.
+
+The system is unbalanced; usually, the number of users exceeds the number of maintainers. Is that good or bad? Having users for our software is (or should be) good. But we need to manage expectations on both sides.
+
+From the corporation's point of view, consuming OSS without care is very, very risky.
+
+OSPO can play an important role in educating the company about the risks they are facing, and how to reduce them by contributing back to their OSS ecosystem. Remember, a company's overall sustainability could rely heavily on its ecosystem sustainability.
+
+A good strategy is to start shifting your company from being pure OSS consumers to becoming contributors to their OSS inbound projects. From just submitting issues and asking questions to help solve issues, answering questions, and even sending patches, contributing helps grow and maintain the project while giving back to the community. It doesn't happen immediately, but over time, the company will be perceived as an OSS ecosystem citizen. Eventually, some people from the company could end up helping to maintain those projects too.
+
+And what about money? There are plenty of ways to support the OSS ecosystem financially. Some examples:
+
+ * Business initiatives like [Tidelift][22], or [OpenCollective][23]
+ * Foundations and their supporting mechanisms, like [Software Freedom Conservancy][24], or [CommunityBridge][25] from the Linux Foundation
+ * Self-funding programs (like [Indeed][26] and [Salesforce][27] have done)
+ * Emerging gig development approaches like [Github Sponsors][28] or [Patreon][29]
+
+
+
+Last but not least, companies need to avoid the "not invented here" syndrome. For some OSS projects, there might be companies providing consulting, customization, maintenance, and/or support services. Instead of taking OSS and spending time and people to self-host, self-customize, or try to bring those kinds of services in-house, it might be smarter and more efficient to hire some of those companies to do the thought work.
+
+As a final remark, I would like to emphasize the importance of an OSPO for a company to succeed and grow in the current market. As shepherds of the company's OSS ecosystem, they are the best people in the organization to understand how the ecosystem works and flows, and they should be empowered to manage, monitor, and make recommendations and decisions to ensure sustainability and growth.
+
+Does your organization have an OSPO yet?
+
+Six common traits of successful open source programs, and a look back at how the open source...
+
+Why would a company not in the business of software development create an open source program...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/open-source-program-office
+
+作者:[J. Manrique Lopez de la Fuente][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/jsmanrique
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/meeting_discussion_brainstorm.png?itok=7_m4CC8S (community team brainstorming ideas)
+[2]: https://opensource.com/sites/default/files/uploads/ospo_1.png (OSS inbound and outbound processes)
+[3]: https://todogroup.org/
+[4]: https://todogroup.org/guides/
+[5]: https://chaoss.community/
+[6]: https://chaoss.community/metrics/
+[7]: https://github.com/chaoss/wg-common
+[8]: https://github.com/chaoss/wg-diversity-inclusion
+[9]: https://github.com/chaoss/wg-evolution
+[10]: https://github.com/chaoss/wg-risk
+[11]: https://github.com/chaoss/wg-value
+[12]: https://github.com/chaoss/augur
+[13]: https://github.com/cregit
+[14]: https://chaoss.github.io/grimoirelab/
+[15]: https://cauldron.io/
+[16]: https://opensource.com/sites/default/files/uploads/ospo_2.png (CHAOSS Metrics for 15 years of Unity OSS activity. Source: cauldron.io)
+[17]: https://en.wikipedia.org/wiki/GQM
+[18]: https://opensource.com/sites/default/files/uploads/ospo_3.png (Uber OSS code core, regular, and casual contributors evolution. Source: uber.biterg.io)
+[19]: https://opensource.com/sites/default/files/uploads/ospo_4.png (Uber OSS activity based on location. Source: uber.biterg.io)
+[20]: https://opensource.com/sites/default/files/uploads/ospo_5_0.png (Uber OSS network. Source: uber.biterg.io)
+[21]: https://opensource.com/sites/default/files/uploads/ospo_6.png (Github Pull Requests backlog management index and time to close analysis. Source: uber.biterg.io)
+[22]: https://tidelift.com/
+[23]: https://opencollective.com/
+[24]: https://sfconservancy.org/
+[25]: https://funding.communitybridge.org/
+[26]: https://engineering.indeedblog.com/blog/2019/02/sponsoring-osi/
+[27]: https://sustain.codefund.fm/23
+[28]: https://help.github.com/en/github/supporting-the-open-source-community-with-github-sponsors
+[29]: https://www.patreon.com/
diff --git a/sources/tech/20200510 Open source underpins coronavirus IoT and robotics solutions.md b/sources/tech/20200510 Open source underpins coronavirus IoT and robotics solutions.md
new file mode 100644
index 0000000000..5ce9ce0a1f
--- /dev/null
+++ b/sources/tech/20200510 Open source underpins coronavirus IoT and robotics solutions.md
@@ -0,0 +1,86 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Open source underpins coronavirus IoT and robotics solutions)
+[#]: via: (https://opensource.com/article/20/5/robotics-covid19)
+[#]: author: (Sam Bocetta https://opensource.com/users/sambocetta)
+
+Open source underpins coronavirus IoT and robotics solutions
+======
+From sanitization of equipment and facilities to plotting the spread of
+the virus, robots are playing an active role in combating COVID-19.
+![Three giant robots and a person][1]
+
+The tech sector is quietly having a boom during the COVID-19 pandemic. Open source developers are getting involved with many aspects of the fight against the coronavirus, [using Python to visualize its spread][2] and helping to repurpose data acquisition systems to perform contact tracing.
+
+However, one of the most exciting areas of current research is the use of robotics to contain the spread of the coronavirus. In the last few weeks, robots have been deployed in critical environments—particularly in hospitals and on airplanes—to help staff sterilize surfaces and objects.
+
+Most of these robots are produced by tech startups, who have seen an opportunity to prove the worth of their proprietary systems. Many of them, however, rely on [open source cloud and IoT tools][3] that have been developed by the open source community.
+
+In this article, we'll take a look at how robotics are being used to fight the disease, the IoT infrastructure that underpins these systems, and finally, the security and privacy concerns that their increased use is highlighting.
+
+### Robots and COVID-19
+
+Around the world, robots are being deployed to help the fight against COVID-19. The most direct use of robots has been in healthcare facilities, and China has taken the lead when it comes to deploying robots in hospitals.
+
+For example, a field hospital that recently opened in Wuhan—where the virus originated—is [making extensive use of robots][4] to help healthcare workers care for patients. Some of these robots provide food, drink, and medicine to patients, and others are used to clean parts of the hospital.
+
+Other companies, such as the Texas startup Xenex Disinfection Services, are using robots and UV light to deactivate viruses, bacteria, and spores on surfaces in airports. Still others, like Dimer UVC Innovations, are focusing on making robots that can [improve aircraft hygiene][5].
+
+Not all of the "robots" deployed against the disease are anthropomorphic, though. The same field hospital in Wuhan that is using human-like robots is also making extensive use of less obviously "robotic" IoT devices.
+
+Patients entering the hospital are screened by networked 5G thermometers to alert staff for anyone showing a high fever, and patients wear smart bracelets and rings equipped with sensors. These are synced with CloudMinds' AI platform, and patients' vital signs, including temperature, heart rate, and blood oxygen levels, can be monitored.
+
+### Robots and the IoT
+
+Even when these robots appear to be independent entities, they make [extensive use of the IoT][6]. In other words, although patients may feel that they are being cared for by a robot that can make its own decisions, in reality, these robots are controlled by large, distributed sensing and data processing systems.
+
+Although many of the robots being deployed are the proprietary property of the tech firms who produce their hardware, their functioning is based on an ecosystem of software that is largely open source.
+
+This observation is an important one because it overturns one of the primary misconceptions about the [way that AI is used today][7][,][7] whether in a healthcare setting or elsewhere. Most research into robotics today does not seek to embed fully intelligent AI systems into robots themselves but, instead, uses centralized AI systems to control a wide variety of far less "smart" IoT devices.
+
+This observation, in turn, highlights two key points about the robots currently being developed and used to fight COVID-19. One is that they rely on a software ecosystem—much of it open source—that has been developed in a truly collaborative process involving thousands of engineers. The second is that the networked nature of these robots makes them vulnerable to exploitation.
+
+### Security and privacy
+
+This vulnerability to cybersecurity threats has led some analysts to raise questions about the wisdom of widespread deployment of IoT-driven robotics, whether in the healthcare system or anywhere else. Spyware in the IoT [remains a huge problem][8], and some fear that by integrating IoT systems into healthcare, we may be exposing more data—and more sensitive data—to intruders.
+
+Even where developers are careful to build security into these devices, the sheer number of components they rely on makes DevSecOps processes difficult to implement. Especially in this current time of crisis, many software engineers have been forced to accelerate the release of new components, and this could lead to them being vulnerable. If a company is rushing to bring a healthcare robot onto the market in response to COVID-19, it's unlikely that the open source code that these devices run on will be [properly audited][9].
+
+And even if companies are able to maintain the integrity of their DevSecOps processes while still accelerating development, it's far from certain that patients themselves understand the privacy implications of delegating their care to IoT devices. Many lack the open source privacy tools [necessary to keep their data private][10] when browsing the internet, let alone those that should be deployed to protect sensitive healthcare data.
+
+### The future
+
+In short, the deployment of robots in the fight against COVID-19 is highlighting long-standing concerns about the integrity, security, and privacy of IoT systems more generally. Professionals in this field have long argued that [IoT audits][11] and [embedded Linux systems][12] should be the standard for IoT development, but in the current crisis, their warnings are likely to be ignored.
+
+This is worrying because it's likely that IoT systems will be increasingly used in healthcare in the coming decade. So whilst the COVID-19 pandemic will provide a proof of their utility in this sector, it should also not be used as an excuse to roll out poorly secured, poorly audited IoT software in highly sensitive environments.
+
+Open source isn’t just changing the way we interact with the world, it’s changing the way the world...
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/robotics-covid19
+
+作者:[Sam Bocetta][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/sambocetta
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/BUSINESS_robots.png?itok=TOZgajrd (Three giant robots and a person)
+[2]: https://opensource.com/article/20/4/python-data-covid-19
+[3]: https://opensource.com/article/18/7/digital-transformation-strategy-think-cloud
+[4]: https://www.cnbc.com/2020/03/18/how-china-is-using-robots-and-telemedicine-to-combat-the-coronavirus.html
+[5]: https://www.therobotreport.com/company-offers-germ-killing-robot-to-airports-to-address-coronavirus-outbreak/
+[6]: https://www.cloudwards.net/what-is-the-internet-of-things/
+[7]: https://opensource.com/article/17/3/5-big-ways-ai-rapidly-invading-our-lives
+[8]: https://blog.eccouncil.org/spyware-in-the-iot-what-does-it-mean-for-your-online-privacy/
+[9]: https://opensource.com/article/17/10/doc-audits
+[10]: https://privacyaustralia.net/privacy-tools/
+[11]: https://opensource.com/article/19/11/how-many-iot-devices
+[12]: https://opensource.com/article/17/3/embedded-linux-iot-ecosystem
diff --git a/sources/tech/20200511 How I track my home-s energy consumption with open source.md b/sources/tech/20200511 How I track my home-s energy consumption with open source.md
new file mode 100644
index 0000000000..10dfaa5f8e
--- /dev/null
+++ b/sources/tech/20200511 How I track my home-s energy consumption with open source.md
@@ -0,0 +1,144 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How I track my home's energy consumption with open source)
+[#]: via: (https://opensource.com/article/20/5/energy-monitoring)
+[#]: author: (Stephan Avenwedde https://opensource.com/users/hansic99)
+
+How I track my home's energy consumption with open source
+======
+These open source components help you find ways to save money and
+conserve resources.
+![lightbulb drawing outline][1]
+
+An important step towards optimizing energy consumption is knowing your actual consumption. My house was built during the oil crisis in the 1970s, and due to the lack of a natural gas connection, the builders decided to use electricity to do all of the heating (water and home heating). This is not unusual for this area of Germany, and it remains an appropriate solution in countries that depend highly on nuclear power.
+
+Electricity prices here are quite high (around € 0.28/kWh), so I decided to monitor my home's energy consumption to get a feel for areas where I could save some energy.
+
+I used to work for a company that sold energy-monitoring systems for industrial customers. While this company mostly used proprietary software, you can set up a similar smart monitoring and logging solution for your home based on open source components. This article will show you how.
+
+In Germany, the grid operator owns the electricity meter. The grid operator is obliged to provide an interface on its metering device to enable the customer to access the meter reading. Here is the metering device on my home:
+
+![Actaris ACE3000 electricity meter][2]
+
+Actaris ACE3000 Type 110 (dry contact located behind the marked cover)
+
+Generally, almost every metering device has at least a [dry contact][3]—as my electricity meter does—that you can use to log metering. As you can see, my electricity meter has two counters: The upper one is for the day tariff (6am to 10pm), and the lower one is for the night tariff (10pm to 6am). The night tariff is a bit cheaper. Two-tariff meters are usually found only in houses with electric heating.
+
+### Design
+
+A reliable energy-monitoring solution for private use should meet the following requirements:
+
+ * Logging of metering impulses (dry contact)
+ * 24/7 operation
+ * Energy-saving operation
+ * Visualization of consumption data
+ * Long-term recording of consumption data
+ * Connectivity (e.g., Ethernet, USB, WiFi, etc.)
+ * Affordability
+
+
+
+I choose the Siemens SIMATIC IOT2020 as my hardware platform. This industrial-proven device is based on an Intel Quark x86 CPU, has programmable interrupts, and is compatible with many Arduino shields.
+
+![Siemens SIMATIC IOT2020][4]
+
+Siemens SIMATIC IOT2020
+
+The Siemens device comes without an SD card and, therefore, without an operating system. Luckily, you can find a current Yocto-based Linux OS image and instructions on how to flash the SD card in the [Siemens forum][5].
+
+In addition to the hardware platform, you also need some accessories. The following materials list shows the minimum components you need. Each item includes links to the parts I purchased, so you can get a sense of the project's costs.
+
+#### Materials list
+
+ * [Siemens SIMATIC IoT2020 unit][6]
+ * [Siemens I/O Shield for SIMATIC IoT2000 series][7]
+ * [microSD card][8] (2GB or more)
+ * [CSL 300Mbit USB-WLAN adapter][9]
+ * 24V power supply (I used a 2.1A [TDK-Lambda DRB50-24-1][10], which I already owned). You could use a less expensive power supply with less power: the SIMATIC IOT2020 has a maximum current of 1.4A, and the dry contact needs an additional 0.1A (24V / 220Ω).
+ * 5 terminal blocks ([Weidmueller WDU 2.5mm][11])
+ * 2 terminal cross-connecting bridges ([Weidmueller WQV][12])
+ * [DIN rail][13] (~300 mm)
+ * [220Ω / 3W resistor][14]
+ * Wire
+
+
+
+Here is the assembled result:
+
+![Mounted and hooked up energy logger][15]
+
+Energy logger mounted and hooked up
+
+Unfortunately, I didn't have enough space at the rear wall of the cabinet; therefore, the DIN rail with the mounted parts lies on the ground.
+
+The connections between the meter and the Siemens device look like this:
+
+![Wiring between meter and energy logger][16]
+
+### How it works
+
+A dry contact is a current interface. When the electricity meter triggers, a current of 0.1A starts flowing between **s0+** and **s0-**. On **DI0**, the voltage rises to 24V and triggers an interrupt. When the electricity meter disconnects **s0+** and **s0-**, **DI0** is grounded over the resistor.
+
+On my device, the contact closes 1,000 times per kWh (this value varies between metering devices).
+
+To count these peaks reliably, I created [a C program][17] that registers an interrupt service routine on the DI0 input and counts upwards in memory. Once a minute, the values from memory are written to an [SQLite][18] database.
+
+The overall meter reading is also written to a text file and can be preset with a starting value. This acts as a copy of the overall metering value of the meter in the cabinet.
+
+![Energy logger architecture][19]
+
+Energy logger architecture
+
+The data is visualized using [Node-RED][20], and I can access overviews, like the daily consumption dashboard below, over a web-based GUI.
+
+![Node-RED based GUI][21]
+
+Daily overview in the Node-RED GUI
+
+For the daily overview, I calculate the hourly costs based on the consumption data (the large bar chart). On the top-left of the dashboard you can see the actual power; below that is the daily consumption (energy and costs). The water heater for the shower causes the large peak in the bar chart.
+
+### A reliable system
+
+Aside from a lost timestamp during a power failure (the real-time clock in the Siemens device is not backed by a battery by default), everything has been working fine for more than one-and-a-half years.
+
+If you can set up the whole Linux system completely from the command line, you'll get a reliable and flexible system with the ability to link interrupt service routines to the I/O level.
+
+Because the I/O Shield runs on standard control voltage (24V), you can extend its functionality with the whole range of standardized industrial components (e.g., relays, sensors, actors, etc.). And, due to its open architecture, this system can be extended easily and applied to other applications, like for monitoring gas or water consumption or as a weather station, a simple controller for tasks, and more.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/energy-monitoring
+
+作者:[Stephan Avenwedde][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/hansic99
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/Collaboration%20for%20health%20innovation.png?itok=s4O5EX2w (lightbulb drawing outline)
+[2]: https://opensource.com/sites/default/files/uploads/openenergylogger_1_electricity_meter.jpg (Actaris ACE3000 electricity meter)
+[3]: https://en.wikipedia.org/wiki/Dry_contact
+[4]: https://opensource.com/sites/default/files/uploads/openenergylogger_2_siemens_device.jpg (Siemens SIMATIC IOT2020)
+[5]: https://support.industry.siemens.com/tf/ww/en/posts/new-example-image-version-online/189090/?page=0&pageSize=10
+[6]: https://de.rs-online.com/web/p/products/1244037
+[7]: https://de.rs-online.com/web/p/products/1354133
+[8]: https://de.rs-online.com/web/p/micro-sd-karten/7582584/
+[9]: https://www.amazon.de/300Mbit-WLAN-Adapter-Hochleistungs-Antennen-Dual-Band/dp/B00LLIOT34
+[10]: https://de.rs-online.com/web/p/products/8153133
+[11]: https://de.rs-online.com/web/p/din-schienenklemmen-ohne-sicherung/0425190/
+[12]: https://de.rs-online.com/web/p/din-schienenklemmen-zubehor/0202574/
+[13]: https://de.rs-online.com/web/p/din-schienen/2835729/
+[14]: https://de.rs-online.com/web/p/widerstande-durchsteckmontage/2142673/
+[15]: https://opensource.com/sites/default/files/uploads/openenergylogger_3_assembled_device.jpg (Mounted and hooked up energy logger)
+[16]: https://opensource.com/sites/default/files/uploads/openenergylogger_4_wiring.png (Wiring between meter and energy logger)
+[17]: https://github.com/hANSIc99/OpenEnergyLogger
+[18]: https://www.sqlite.org/index.html
+[19]: https://opensource.com/sites/default/files/uploads/openenergylogger_5_architecure.png (Energy logger architecture)
+[20]: https://nodered.org/
+[21]: https://opensource.com/sites/default/files/uploads/openenergylogger_6_dashboard.png (Node-RED based GUI)
diff --git a/sources/tech/20200511 Start using systemd as a troubleshooting tool.md b/sources/tech/20200511 Start using systemd as a troubleshooting tool.md
new file mode 100644
index 0000000000..372be7660e
--- /dev/null
+++ b/sources/tech/20200511 Start using systemd as a troubleshooting tool.md
@@ -0,0 +1,269 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Start using systemd as a troubleshooting tool)
+[#]: via: (https://opensource.com/article/20/5/systemd-troubleshooting-tool)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Start using systemd as a troubleshooting tool
+======
+While systemd is not really a troubleshooting tool, the information in
+its output points the way toward solving problems.
+![Magnifying glass on code][1]
+
+No one would really consider systemd to be a troubleshooting tool, but when I encountered a problem on my webserver, my growing knowledge of systemd and some of its features helped me locate and circumvent the problem.
+
+The problem was that my server, yorktown, which provides name services, DHCP, NTP, HTTPD, and SendMail email services for my home office network, failed to start the Apache HTTPD daemon during normal startup. I had to start it manually after I realized that it was not running. The problem had been going on for some time, and I recently got around to trying to fix it.
+
+Some of you will say that systemd itself is the cause of this problem, and, based on what I know now, I agree with you. However, I had similar types of problems with SystemV. (In the [first article][2] in this series, I looked at the controversy around systemd as a replacement for the old SystemV init program and startup scripts. If you're interested in learning more about systemd, read the [second][3] and [third][4] articles, too.) No software is perfect, and neither systemd nor SystemV is an exception, but systemd provides far more information for problem-solving than SystemV ever offered.
+
+### Determining the problem
+
+The first step to finding the source of this problem is to determine the httpd service's status:
+
+
+```
+[root@yorktown ~]# systemctl status httpd
+● httpd.service - The Apache HTTP Server
+ Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
+ Active: failed (Result: exit-code) since Thu 2020-04-16 11:54:37 EDT; 15min ago
+ Docs: man:httpd.service(8)
+ Process: 1101 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
+ Main PID: 1101 (code=exited, status=1/FAILURE)
+ Status: "Reading configuration..."
+ CPU: 60ms
+
+Apr 16 11:54:35 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
+Apr 16 11:54:37 yorktown.both.org httpd[1101]: (99)Cannot assign requested address: AH00072: make_sock: could not bind to address 192.168.0.52:80
+Apr 16 11:54:37 yorktown.both.org httpd[1101]: no listening sockets available, shutting down
+Apr 16 11:54:37 yorktown.both.org httpd[1101]: AH00015: Unable to open logs
+Apr 16 11:54:37 yorktown.both.org systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE
+Apr 16 11:54:37 yorktown.both.org systemd[1]: httpd.service: Failed with result 'exit-code'.
+Apr 16 11:54:37 yorktown.both.org systemd[1]: Failed to start The Apache HTTP Server.
+[root@yorktown ~]#
+```
+
+This status information is one of the systemd features that I find much more useful than anything SystemV offers. The amount of helpful information here leads me easily to a logical conclusion that takes me in the right direction. All I ever got from the old **chkconfig** command is whether or not the service is running and the process ID (PID) if it is. That is not very helpful.
+
+The key entry in this status report shows that HTTPD cannot bind to the IP address, which means it cannot accept incoming requests. This indicates that the network is not starting fast enough to be ready for the HTTPD service to bind to the IP address because the IP address has not yet been set. This is not supposed to happen, so I explored my network service systemd startup configuration files; all appeared to be correct with the right "after" and "requires" statements. Here is the **/lib/systemd/system/httpd.service** file from my server:
+
+
+```
+# Modifying this file in-place is not recommended, because changes
+# will be overwritten during package upgrades. To customize the
+# behaviour, run "systemctl edit httpd" to create an override unit.
+
+# For example, to pass additional options (such as -D definitions) to
+# the httpd binary at startup, create an override unit (as is done by
+# systemctl edit) and enter the following:
+
+# [Service]
+# Environment=OPTIONS=-DMY_DEFINE
+
+[Unit]
+Description=The Apache HTTP Server
+Wants=httpd-init.service
+After=network.target remote-fs.target nss-lookup.target httpd-init.service
+Documentation=man:httpd.service(8)
+
+[Service]
+Type=notify
+Environment=LANG=C
+
+ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
+ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
+# Send SIGWINCH for graceful stop
+KillSignal=SIGWINCH
+KillMode=mixed
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
+```
+
+The **httpd.service** unit file explicitly specifies that it should load after the **network.target** and the **httpd-init.service** (among others). I tried to find all of these services using the **systemctl list-units** command and searching for them in the resulting data stream. All were present and should have ensured that the httpd service did not load before the network IP address was set.
+
+### First solution
+
+A bit of searching on the internet confirmed that others had encountered similar problems with httpd and other services. This appears to happen because one of the required services indicates to systemd that it has finished its startup—but it actually spins off a child process that has not finished. After a bit more searching, I came up with a circumvention.
+
+I could not figure out why the IP address was taking so long to be assigned to the network interface card. So, I thought that if I could delay the start of the HTTPD service by a reasonable amount of time, the IP address would be assigned by that time.
+
+Fortunately, the **/lib/systemd/system/httpd.service** file above provides some direction. Although it says not to alter it, it does indicate how to proceed: Use the command **systemctl edit httpd**, which automatically creates a new file (**/etc/systemd/system/httpd.service.d/override.conf**) and opens the [GNU Nano][5] editor. (If you are not familiar with Nano, be sure to look at the hints at the bottom of the Nano interface.)
+
+Add the following text to the new file and save it:
+
+
+```
+[root@yorktown ~]# cd /etc/systemd/system/httpd.service.d/
+[root@yorktown httpd.service.d]# ll
+total 4
+-rw-r--r-- 1 root root 243 Apr 16 11:43 override.conf
+[root@yorktown httpd.service.d]# cat override.conf
+# Trying to delay the startup of httpd so that the network is
+# fully up and running so that httpd can bind to the correct
+# IP address
+#
+# By David Both, 2020-04-16
+
+[Service]
+ExecStartPre=/bin/sleep 30
+```
+
+The **[Service]** section of this override file contains a single line that delays the start of the HTTPD service by 30 seconds. The following status command shows the service status during the wait time:
+
+
+```
+[root@yorktown ~]# systemctl status httpd
+● httpd.service - The Apache HTTP Server
+ Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
+ Drop-In: /etc/systemd/system/httpd.service.d
+ └─override.conf
+ /usr/lib/systemd/system/httpd.service.d
+ └─php-fpm.conf
+ Active: activating (start-pre) since Thu 2020-04-16 12:14:29 EDT; 28s ago
+ Docs: man:httpd.service(8)
+Cntrl PID: 1102 (sleep)
+ Tasks: 1 (limit: 38363)
+ Memory: 260.0K
+ CPU: 2ms
+ CGroup: /system.slice/httpd.service
+ └─1102 /bin/sleep 30
+
+Apr 16 12:14:29 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
+Apr 16 12:15:01 yorktown.both.org systemd[1]: Started The Apache HTTP Server.
+[root@yorktown ~]#
+```
+
+And this command shows the status of the HTTPD service after the 30-second delay expires. The service is up and running correctly:
+
+
+```
+[root@yorktown ~]# systemctl status httpd
+● httpd.service - The Apache HTTP Server
+ Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
+ Drop-In: /etc/systemd/system/httpd.service.d
+ └─override.conf
+ /usr/lib/systemd/system/httpd.service.d
+ └─php-fpm.conf
+ Active: active (running) since Thu 2020-04-16 12:15:01 EDT; 1min 18s ago
+ Docs: man:httpd.service(8)
+ Process: 1102 ExecStartPre=/bin/sleep 30 (code=exited, status=0/SUCCESS)
+ Main PID: 1567 (httpd)
+ Status: "Total requests: 0; Idle/Busy workers 100/0;Requests/sec: 0; Bytes served/sec: 0 B/sec"
+ Tasks: 213 (limit: 38363)
+ Memory: 21.8M
+ CPU: 82ms
+ CGroup: /system.slice/httpd.service
+ ├─1567 /usr/sbin/httpd -DFOREGROUND
+ ├─1569 /usr/sbin/httpd -DFOREGROUND
+ ├─1570 /usr/sbin/httpd -DFOREGROUND
+ ├─1571 /usr/sbin/httpd -DFOREGROUND
+ └─1572 /usr/sbin/httpd -DFOREGROUND
+
+Apr 16 12:14:29 yorktown.both.org systemd[1]: Starting The Apache HTTP Server...
+Apr 16 12:15:01 yorktown.both.org systemd[1]: Started The Apache HTTP Server.
+```
+
+I could have experimented to see if a shorter delay would work as well, but my system is not that critical, so I decided not to. It works reliably as it is, so I am happy.
+
+Because I gathered all this information, I reported it to Red Hat Bugzilla as Bug [1825554][6]. I believe that it is much more productive to report bugs than it is to complain about them.
+
+### The better solution
+
+A couple of days after reporting this as a bug, I received a response indicating that systemd is just the manager, and if httpd needs to be ordered after some requirements are met, it needs to be expressed in the unit file. The response pointed me to the **httpd.service** man page. I wish I had found this earlier because it is a better solution than the one I came up with. This solution is explicitly targeted to the prerequisite target unit rather than a somewhat random delay.
+
+From the [**httpd.service** man page][7]:
+
+> **Starting the service at boot time**
+>
+> The httpd.service and httpd.socket units are _disabled_ by default. To start the httpd service at boot time, run: **systemctl enable httpd.service**. In the default configuration, the httpd daemon will accept connections on port 80 (and, if mod_ssl is installed, TLS connections on port 443) for any configured IPv4 or IPv6 address.
+>
+> If httpd is configured to depend on any specific IP address (for example, with a "Listen" directive) which may only become available during start-up, or if httpd depends on other services (such as a database daemon), the service _must_ be configured to ensure correct start-up ordering.
+>
+> For example, to ensure httpd is only running after all configured network interfaces are configured, create a drop-in file (as described above) with the following section:
+>
+> [Unit]
+> After=network-online.target
+> Wants=network-online.target
+
+I still think this is a bug because it is quite common—at least in my experience—to use a **Listen** directive in the **httpd.conf** configuration file. I have always used **Listen** directives, even on hosts with only a single IP address, and it is clearly necessary on hosts with multiple network interface cards (NICs) and internet protocol (IP) addresses. Adding the lines above to the **/usr/lib/systemd/system/httpd.service** default file would not cause problems for configurations that do not use a **Listen** directive and would prevent this problem for those that do.
+
+In the meantime, I will use the suggested solution.
+
+### Next steps
+
+This article describes a problem I had with starting the Apache HTTPD service on my server. It leads you through the problem determination steps I took and shows how I used systemd to assist. I also covered the circumvention I implemented using systemd and the better solution that followed from my bug report.
+
+As I mentioned at the start, it is very likely that this is the result of a problem with systemd, specifically the configuration for httpd startup. Nevertheless, systemd provided me with the tools to locate the likely source of the problem and to formulate and implement a circumvention. Neither solution really resolves the problem to my satisfaction. For now, the root cause of the problem still exists and must be fixed. If that is simply adding the recommended lines to the **/usr/lib/systemd/system/httpd.service** file, that would work for me.
+
+One of the things I discovered during this is process is that I need to learn more about defining the sequences in which things start. I will explore that in my next article, the fifth in this series.
+
+### Resources
+
+There is a great deal of information about systemd available on the internet, but much is terse, obtuse, or even misleading. In addition to the resources mentioned in this article, the following webpages offer more detailed and reliable information about systemd startup.
+
+ * The Fedora Project has a good, practical [guide][8] [to systemd][8]. It has pretty much everything you need to know in order to configure, manage, and maintain a Fedora computer using systemd.
+ * The Fedora Project also has a good [cheat sheet][9] that cross-references the old SystemV commands to comparable systemd ones.
+ * For detailed technical information about systemd and the reasons for creating it, check out [Freedesktop.org][10]'s [description of systemd][11].
+ * [Linux.com][12]'s "More systemd fun" offers more advanced systemd [information and tips][13].
+
+
+
+There is also a series of deeply technical articles for Linux sysadmins by Lennart Poettering, the designer and primary developer of systemd. These articles were written between April 2010 and September 2011, but they are just as relevant now as they were then. Much of everything else good that has been written about systemd and its ecosystem is based on these papers.
+
+ * [Rethinking PID 1][14]
+ * [systemd for Administrators, Part I][15]
+ * [systemd for Administrators, Part II][16]
+ * [systemd for Administrators, Part III][17]
+ * [systemd for Administrators, Part IV][18]
+ * [systemd for Administrators, Part V][19]
+ * [systemd for Administrators, Part VI][20]
+ * [systemd for Administrators, Part VII][21]
+ * [systemd for Administrators, Part VIII][22]
+ * [systemd for Administrators, Part IX][23]
+ * [systemd for Administrators, Part X][24]
+ * [systemd for Administrators, Part XI][25]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/systemd-troubleshooting-tool
+
+作者:[David Both][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/dboth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/find-file-linux-code_magnifying_glass_zero.png?itok=E2HoPDg0 (Magnifying glass on code)
+[2]: https://opensource.com/article/20/4/systemd
+[3]: https://opensource.com/article/20/4/systemd-startup
+[4]: https://opensource.com/article/20/4/understanding-and-using-systemd-units
+[5]: https://www.nano-editor.org/
+[6]: https://bugzilla.redhat.com/show_bug.cgi?id=1825554
+[7]: https://www.mankier.com/8/httpd.service#Description-Starting_the_service_at_boot_time
+[8]: https://docs.fedoraproject.org/en-US/quick-docs/understanding-and-administering-systemd/index.html
+[9]: https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet
+[10]: http://Freedesktop.org
+[11]: http://www.freedesktop.org/wiki/Software/systemd
+[12]: http://Linux.com
+[13]: https://www.linux.com/training-tutorials/more-systemd-fun-blame-game-and-stopping-services-prejudice/
+[14]: http://0pointer.de/blog/projects/systemd.html
+[15]: http://0pointer.de/blog/projects/systemd-for-admins-1.html
+[16]: http://0pointer.de/blog/projects/systemd-for-admins-2.html
+[17]: http://0pointer.de/blog/projects/systemd-for-admins-3.html
+[18]: http://0pointer.de/blog/projects/systemd-for-admins-4.html
+[19]: http://0pointer.de/blog/projects/three-levels-of-off.html
+[20]: http://0pointer.de/blog/projects/changing-roots
+[21]: http://0pointer.de/blog/projects/blame-game.html
+[22]: http://0pointer.de/blog/projects/the-new-configuration-files.html
+[23]: http://0pointer.de/blog/projects/on-etc-sysinit.html
+[24]: http://0pointer.de/blog/projects/instances.html
+[25]: http://0pointer.de/blog/projects/inetd.html
diff --git a/sources/tech/20200511 Tips and tricks for optimizing container builds.md b/sources/tech/20200511 Tips and tricks for optimizing container builds.md
new file mode 100644
index 0000000000..0a4fbed8cb
--- /dev/null
+++ b/sources/tech/20200511 Tips and tricks for optimizing container builds.md
@@ -0,0 +1,201 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Tips and tricks for optimizing container builds)
+[#]: via: (https://opensource.com/article/20/5/optimize-container-builds)
+[#]: author: (Ravi Chandran https://opensource.com/users/ravichandran)
+
+Tips and tricks for optimizing container builds
+======
+Try these techniques to minimize the number and length of your container
+build iterations.
+![Toolbox drawing of a container][1]
+
+How many iterations does it take to get a container configuration just right? And how long does each iteration take? Well, if you answered "too many times and too long," then my experiences are similar to yours. On the surface, creating a configuration file seems like a straightforward exercise: implement the same steps in a configuration file that you would perform if you were installing the system by hand. Unfortunately, I've found that it usually doesn't quite work that way, and a few "tricks" are handy for such DevOps exercises.
+
+In this article, I'll share some techniques I've found that help minimize the number and length of iterations. In addition, I'll outline a few good practices beyond the [standard ones][2].
+
+In the [tutorial repository][3] from my previous article about [containerizing build systems][4], I've added a folder called **/tutorial2_docker_tricks** with an example covering some of the tricks that I'll walk through in this post. If you want to follow along and you have Git installed, you can pull it locally with:
+
+
+```
+`$ git clone https://github.com/ravi-chandran/dockerize-tutorial`
+```
+
+The tutorial has been tested with Docker Desktop Edition, although it should work with any compatible Linux container system (like [Podman][5]).
+
+### Save time on container image build iterations
+
+If the Dockerfile involves downloading and installing a 5GB file, each iteration of **docker image build** could take a lot of time even with good network speeds. And forgetting to include one item to be installed can mean rebuilding all the layers after that point.
+
+One way around that challenge is to use a local HTTP server to avoid downloading large files from the internet multiple times during **docker image build** iterations. To illustrate this by example, say you need to create a container image with Anaconda 3 under Ubuntu 18.04. The Anaconda 3 installer is a ~0.5GB file, so this will be the "large" file for this example.
+
+Note that you don't want to use the **COPY** instruction, as it creates a new layer. You should also delete the large installer after using it to minimize the container image size. You could use [multi-stage builds][6], but I've found the following approach sufficient and quite effective.
+
+The basic idea is to use a Python-based HTTP server locally to serve the large file(s) and have the Dockerfile **wget** the large file(s) from this local server. Let's explore the details of how to set this up effectively. As a reminder, you can access the [full example][7].
+
+The necessary contents of the folder **tutorial2_docker_tricks/** in this example repository are:
+
+
+```
+tutorial2_docker_tricks/
+├── build_docker_image.sh # builds the docker image
+├── run_container.sh # instantiates a container from the image
+├── install_anaconda.dockerfile # Dockerfile for creating our target docker image
+├── .dockerignore # used to ignore contents of the installer/ folder from the docker context
+├── installer # folder with all our large files required for creating the docker image
+│ └── Anaconda3-2019.10-Linux-x86_64.sh # from
+└── workdir # example folder used as a volume in the running container
+```
+
+The key steps of the approach are:
+
+ * Place the large file(s) in the **installer/** folder. In this example, I have the large Anaconda installer file **Anaconda3-2019.10-Linux-x86_64.sh**. You won't find this file if you clone my [Git repository][8] because only you, as the container image creator, need this source file. The end users of the image don't. [Download the installer][9] to follow along with the example.
+ * Create the **.dockerignore** file and have it ignore the **installer/** folder to avoid Docker copying all the large files into the build context.
+ * In a terminal, **cd** into the **tutorial2_docker_tricks/** folder and execute the build script as **./build_docker_image.sh**.
+ * In **build_docker_image.sh**, start the Python HTTP server to serve any files from the **installer/** folder: [code] cd installer
+python3 -m http.server --bind 10.0.2.15 8888 &
+cd ..
+```
+* If you're wondering about the strange internet protocol (IP) address, I'm working with a VirtualBox Linux VM, and **10.0.2.15** shows up as the address of the Ethernet adapter when I run **ifconfig**. This IP seems to be the convention used by VirtualBox. If your setup is different, you'll need to update this IP address to match your environment and then update **build_docker_image.sh** and **install_anaconda.dockerfile**. The server's port number is set to **8888** for this example. Note that the IP and port numbers could be passed in as build arguments, but I've hard-coded them for brevity.
+* Since the HTTP server is set to run in the background, stop the server near the end of the script with the **kill -9** command using an [elegant approach][10] I found: [code]`kill -9 `ps -ef | grep http.server | grep 8888 | awk '{print $2}'`
+```
+ * Note that this same **kill -9** is also used earlier in the script (before starting the HTTP server). In general, when I iterate on any build script that I might deliberately interrupt, this ensures a clean start of the HTTP server each time.
+ * In the [Dockerfile][11], there is a **RUN wget** instruction that downloads the Anaconda installer from the local HTTP server. It also deletes the installer file and cleans up after the installation. Most importantly, all these actions are performed within the same layer to keep the image size to a minimum: [code] # install Anaconda by downloading the installer via the local http server
+ARG ANACONDA
+RUN wget --no-proxy -O ~/anaconda.sh \
+ && /bin/bash ~/anaconda.sh -b -p /opt/conda \
+ && rm ~/anaconda.sh \
+ && rm -fr /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*
+```
+ * This file runs the wrapper script, **anaconda.sh**, and cleans up large files by removing them with **rm**.
+ * After the build is complete, you should see an image **anaconda_ubuntu1804:v1**. (You can list the images with **docker image ls**.)
+ * You can instantiate a container from this image using **./run_container.sh** at the terminal while in the folder **tutorial2_docker_tricks/**. You can verify that Anaconda is installed with: [code] $ ./run_container.sh
+$ python --version
+Python 3.7.5
+$ conda --version
+conda 4.8.0
+$ anaconda --version
+anaconda Command line client (version 1.7.2)
+```
+ * You'll note that **run_container.sh** sets up a volume **workdir**. In this example repository, the folder **workdir/** is empty. This is a convention I use to set up a volume where I can have my Python and other scripts that are independent of the container image.
+
+
+
+### Minimize container image size
+
+Each **RUN** command is equivalent to executing a new shell, and each **RUN** command creates a layer. The naive approach of mimicking installation instructions with separate **RUN** commands may eventually break at one or more interdependent steps. If it happens to work, it will typically result in a larger image. Chaining multiple installation steps in one **RUN** command and including the **autoremove**, **autoclean**, and **rm** commands (as in the example below) is useful to minimize the size of each layer. Some of these steps may not be needed, depending on what's being installed. However, since these steps take an insignificant amount of time, I always throw them in for good measure at the end of **RUN** commands invoking **apt-get**:
+
+
+```
+RUN apt-get update \
+ && DEBIAN_FRONTEND=noninteractive \
+ apt-get -y --quiet --no-install-recommends install \
+ # list of packages being installed go here \
+ && apt-get -y autoremove \
+ && apt-get clean autoclean \
+ && rm -fr /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*
+```
+
+Also, ensure that you have a **.dockerignore** file in place to ignore items that don't need to be sent to the Docker build context (such as the Anaconda installer file in the earlier example).
+
+### Organize the build tool I/O
+
+For software build systems, the build inputs and outputs—all the scripts that configure and invoke the tools—should be outside the image and the eventually running container. The container itself should remain stateless so that different users will have identical results with it. I covered this extensively in my [previous article][4] but wanted to emphasize it because it's been a useful convention for my work. These inputs and outputs are best accessed by setting up container volumes.
+
+I've had to use a container image that provides data in the form of source code and large pre-built binaries. As a software developer, I was expected to edit the code in the container. This was problematic, because containers are by default stateless: they don't save data within the container, because they're designed to be disposable. But I worked on it, and at the end of each day, I stopped the container and had to be careful not to remove it, because the state had to be maintained so I could continue work the next day. The disadvantage of this approach was that there would be a divergence of development state had there been more than one person working on the project. The value of having identical build systems across developers is somewhat lost with this approach.
+
+### Generate output as non-root user
+
+An important aspect of I/O concerns the ownership of the output files generated when running the tools in the container. By default, since Docker runs as **root**, the output files would be owned by **root**, which is unpleasant. You typically want to work as a non-root user. Changing the ownership after the build output is generated can be done with scripts, but it is an additional and unnecessary step. It's best to set the [**USER**][12] argument in the Dockerfile at the earliest point possible:
+
+
+```
+ARG USERNAME
+# other commands...
+USER ${USERNAME}
+```
+
+The **USERNAME** can be passed in as a build argument (**\--build-arg**) when executing the **docker image build**. You can see an example of this in the example [Dockerfile][11] and corresponding [build script][13].
+
+Some portions of the tools may also need to be installed as a non-root user. So the sequence of installations in the Dockerfile may need to be different from the way it's done if you are installing manually and directly under Linux.
+
+### Non-interactive installation
+
+Interactivity is the opposite of container automation. I've found the
+
+
+```
+`DEBIAN_FRONTEND=noninteractive apt-get -y --quiet --no-install-recommends`
+```
+
+options for the **apt-get install** instruction (as in the example above) necessary to prevent the installer from opening dialog boxes. Note that these options should be used as part of the **RUN** instruction. The **DEBIAN_FRONTEND=noninteractive** should not be set as an environment variable (**ENV**) in the Dockerfile, as this [FAQ explains][14], as it will be inherited by the containers.
+
+### Log your build and run output
+
+Debugging why a build failed is a common task, and logs are a great way to do this. Save a TypeScript of everything that happened during the container image build or container run session using the **tee** utility in a Bash script. In other words, add **|& tee $BASH_SOURCE.log** to the end of the **docker image build** and the **docker image run** commands in your scripts. See the examples in the [image build][13] and [container run][15] scripts.
+
+What this **tee**-ing technique does is generate a file with the same name as the Bash script but with a **.log** extension appended to it so that you know which script it originated from. Everything you see printed to the terminal when running the script will get logged to this file with a similar name.
+
+This is especially valuable for users of your container images to report issues to you when something doesn't work. You can ask them to send you the log file to help diagnose the issue. Many tools generate so much output that it easily overwhelms the default size of the terminal's buffer. Relying only on the terminal's buffer capacity to copy-paste error messages may not be sufficient for diagnosing issues because earlier errors may have been lost.
+
+I've found this to be useful, even in the container image-building scripts, especially when using the Python-based HTTP server discussed above. The server generates so many lines during a download that it typically overwhelms the terminal's buffer.
+
+### Deal with proxies elegantly
+
+In my work environment, proxies are required to reach the internet for downloading the resources in **RUN apt-get** and **RUN wget** commands. The proxies are typically inferred from the environment variables **http_proxy** or **https_proxy**. While **ENV** commands can be used to hard-code such proxy settings in the Dockerfile, there are multiple issues with using **ENV** for proxies directly.
+
+If you are the only one who will ever build the container, then perhaps this will work. But the Dockerfile couldn't be used by someone else at a different location with a different proxy setting. Another issue is that the IT department could change the proxy at some point, resulting in a Dockerfile that won't work any longer. Furthermore, the Dockerfile is a precise document specifying a configuration-controlled system, and every change will be scrutinized by quality assurance.
+
+One simple approach to avoid hard-coding the proxy is to pass your local proxy setting as a build argument in the **docker image build** command:
+
+
+```
+docker image build \
+ --build-arg MY_PROXY=
+```
+
+And then, in the Dockerfile, set the environment variables based on the build argument. In the example shown here, you can still set a default proxy value that can be overridden by the build argument above:
+
+
+```
+# set a default proxy
+ARG MY_PROXY=MY_PROXY=
+ENV http_proxy=$MY_PROXY
+ENV https_proxy=$MY_PROXY
+```
+
+### Summary
+
+These techniques have helped me significantly reduce the time it takes to create container images and debug them when they go wrong. I continue to be on the lookout for additional best practices to add to my list. I hope you find the above techniques useful.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/optimize-container-builds
+
+作者:[Ravi Chandran][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/ravichandran
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/toolbox-learn-draw-container-yearbook.png?itok=xDbwz1pP (Toolbox drawing of a container)
+[2]: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
+[3]: https://github.com/ravi-chandran/dockerize-tutorial
+[4]: https://opensource.com/article/20/4/how-containerize-build-system
+[5]: https://podman.io/getting-started/installation
+[6]: https://docs.docker.com/develop/develop-images/multistage-build/
+[7]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/
+[8]: https://github.com/ravi-chandran/dockerize-tutorial/
+[9]: https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh
+[10]: https://stackoverflow.com/a/37214138
+[11]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/install_anaconda.dockerfile
+[12]: https://docs.docker.com/engine/reference/builder/#user
+[13]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/build_docker_image.sh
+[14]: https://docs.docker.com/engine/faq/
+[15]: https://github.com/ravi-chandran/dockerize-tutorial/blob/master/tutorial2_docker_tricks/run_container.sh
diff --git a/sources/tech/20200515 How to examine processes running on Linux.md b/sources/tech/20200515 How to examine processes running on Linux.md
new file mode 100644
index 0000000000..0659ab04f9
--- /dev/null
+++ b/sources/tech/20200515 How to examine processes running on Linux.md
@@ -0,0 +1,232 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to examine processes running on Linux)
+[#]: via: (https://www.networkworld.com/article/3543232/how-to-examine-processes-running-on-linux.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+How to examine processes running on Linux
+======
+
+Thinkstock
+
+There are quite a number of ways to look at running processes on Linux systems – to see what’s running, the resources that processes are using, how the system is affected by the load and how memory is being used. Each command gives you a different view, and the range of details is considerable. In this post, we’ll run through a series of commands that can help you view process details in a number of different ways.
+
+### ps
+
+While the **ps** command is the most obvious command for examining processes, the arguments that you use when running **ps** will make a big difference in how much information will be provided. With no arguments, **ps** will only show processes associated with your current login session. Add a **-u** and you'll see extended details.
+
+Here is a comparison:
+
+```
+nemo$ ps
+ PID TTY TIME CMD
+ 45867 pts/1 00:00:00 bash
+ 46140 pts/1 00:00:00 ps
+nemo$ ps -u
+USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
+nemo 45867 0.0 0.0 11232 5636 pts/1 Ss 19:04 0:00 -bash
+nemo 46141 0.0 0.0 11700 3648 pts/1 R+ 19:16 0:00 ps -u
+```
+
+Using **ps -ef** will display details on all of the processes running on the system but **ps -eF** will add some additional details.
+
+```
+$ ps -ef | head -2
+UID PID PPID C STIME TTY TIME CMD
+root 1 0 0 May10 ? 00:00:06 /sbin/init splash
+$ ps -eF | head -2
+UID PID PPID C SZ RSS PSR STIME TTY TIME CMD
+root 1 0 0 42108 12524 0 May10 ? 00:00:06 /sbin/init splash
+```
+
+Both commands show who is running the process, the process and parent process IDs, process start time, accumulated run time and the task being run. The additional fields shown when you use **F** instead of **f** include:
+
+ * SZ: the process **size** in physical pages for the core image of the process
+ * RSS: the **resident set size** which shows how much memory is allocated to those parts of the process in RAM. It does not include memory that is swapped out, but does include memory from shared libraries as long as the pages from those libraries are currently in memory. It also includes stack and heap memory.
+ * PSR: the **processor** the process is using
+
+
+
+##### ps -fU
+
+You can list processes for some particular user with a command like "ps -ef | grep USERNAME", but with **ps -fU** command, you’re going to see considerably more data. This is because details of processes that are being run on the user's behalf are also included. In fact, nearly all these processes shown have been kicked off by system simply to support this user’s online session. Nemo has only just logged in and is not yet running any commands or scripts.
+
+```
+$ ps -fU nemo
+UID PID PPID C STIME TTY TIME CMD
+nemo 45726 1 0 19:04 ? 00:00:00 /lib/systemd/systemd --user
+nemo 45732 45726 0 19:04 ? 00:00:00 (sd-pam)
+nemo 45738 45726 0 19:04 ? 00:00:00 /usr/bin/pulseaudio --daemon
+nemo 45740 45726 0 19:04 ? 00:00:00 /usr/libexec/tracker-miner-f
+nemo 45754 45726 0 19:04 ? 00:00:00 /usr/bin/dbus-daemon --sessi
+nemo 45829 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfsd
+nemo 45856 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfsd-fuse /run
+nemo 45862 45706 0 19:04 ? 00:00:00 sshd: nemo@pts/1
+nemo 45864 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-udisks2-vo
+nemo 45867 45862 0 19:04 pts/1 00:00:00 -bash
+nemo 45878 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-afc-volume
+nemo 45883 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-goa-volume
+nemo 45887 45726 0 19:04 ? 00:00:00 /usr/libexec/goa-daemon
+nemo 45895 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-mtp-volume
+nemo 45896 45726 0 19:04 ? 00:00:00 /usr/libexec/goa-identity-se
+nemo 45903 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfs-gphoto2-vo
+nemo 45946 45726 0 19:04 ? 00:00:00 /usr/libexec/gvfsd-metadata
+```
+
+Note that the only process with an assigned TTY is Nemo's shell and that the parent of all of the other processes is **systemd**.
+
+You can supply a comma-separated list of usernames instead of a single name. Just be prepared to be looking at quite a bit more data.
+
+#### top and ntop
+
+The **top** and **ntop** commands will help when you want to get an idea which processes are using the most resources and allow you to reorder your view depending on what criteria you want to use to rank the processes (e.g., highest CPU or memory use).
+
+```
+top - 11:51:27 up 1 day, 21:40, 1 user, load average: 0.08, 0.02, 0.01
+Tasks: 211 total, 1 running, 210 sleeping, 0 stopped, 0 zombie
+%Cpu(s): 5.0 us, 0.5 sy, 0.0 ni, 94.3 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
+MiB Mem : 5944.4 total, 3527.4 free, 565.1 used, 1851.9 buff/cache
+MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 5084.3 avail Mem
+
+ PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
+ 999 root 20 0 394660 14380 10912 S 8.0 0.2 0:46.54 udisksd
+ 65224 shs 20 0 314268 9824 8084 S 1.7 0.2 0:00.34 gvfs-ud+
+ 2034 gdm 20 0 314264 9820 7992 S 1.3 0.2 0:06.25 gvfs-ud+
+ 67909 root 20 0 0 0 0 I 0.3 0.0 0:00.09 kworker+
+ 1 root 20 0 168432 12532 8564 S 0.0 0.2 0:09.93 systemd
+ 2 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kthreadd
+```
+
+Use **shift+m** to sort by memory use and **shift+p** to go back to sorting by CPU usage (the default).
+
+#### /proc
+
+A tremendous amount of information is available on running processes in the **/proc** directory. In fact, if you haven't visited **/proc** quite a few times, you might be astounded by the amount of details available. Just keep in mind that **/proc** is a very different kind of file system. As an interface to kernel data, it provides a view of process details that are currently being used by the system.
+
+Some of the more useful **/proc** files for viewing include **cmdline**, **environ**, **fd**, **limits** and **status**. The following views provide some samples of what you might see.
+
+The **status** file shows the process that is running (bash), its status, the user and group ID for the person running bash, a full list of the groups the user is a member of and the process ID and parent process ID.
+
+```
+$ head -11 /proc/65333/status
+Name: bash
+Umask: 0002
+State: S (sleeping)
+Tgid: 65333
+Ngid: 0
+Pid: 65333
+PPid: 65320
+TracerPid: 0
+Uid: 1000 1000 1000 1000
+Gid: 1000 1000 1000 1000
+FDSize: 256
+Groups: 4 11 24 27 30 46 118 128 500 1000
+...
+```
+
+The **cmdline** file shows the command line used to start the process.
+
+```
+$ cat /proc/65333/cmdline
+-bash
+```
+
+The **environ** file shows the environment variables that are in effect.
+
+```
+$ cat environ
+USER=shsLOGNAME=shsHOME=/home/shsPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/gamesSHELL=/bin/bashTERM=xtermXDG_SESSION_ID=626XDG_RUNTIME_DIR=/run/user/1000DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/busXDG_SESSION_TYPE=ttyXDG_SESSION_CLASS=userMOTD_SHOWN=pamLANG=en_US.UTF-8SSH_CLIENT=192.168.0.19 9385 22SSH_CONNECTION=192.168.0.19 9385 192.168.0.11 22SSH_TTY=/dev/pts/0$
+```
+
+The **fd** file shows the file descriptors. Note how they reflect the pseudo-tty that is being used (pts/0).
+
+```
+$ ls -l /proc/65333/fd
+total 0
+lrwx------ 1 shs shs 64 May 12 09:45 0 -> /dev/pts/0
+lrwx------ 1 shs shs 64 May 12 09:45 1 -> /dev/pts/0
+lrwx------ 1 shs shs 64 May 12 09:45 2 -> /dev/pts/0
+lrwx------ 1 shs shs 64 May 12 09:56 255 -> /dev/pts/0
+$ who
+shs pts/0 2020-05-12 09:45 (192.168.0.19)
+```
+
+The **limits** file contains information about the limits imposed on the process.
+
+```
+$ cat limits
+Limit Soft Limit Hard Limit Units
+Max cpu time unlimited unlimited seconds
+Max file size unlimited unlimited bytes
+Max data size unlimited unlimited bytes
+Max stack size 8388608 unlimited bytes
+Max core file size 0 unlimited bytes
+Max resident set unlimited unlimited bytes
+Max processes 23554 23554 processes
+Max open files 1024 1048576 files
+Max locked memory 67108864 67108864 bytes
+Max address space unlimited unlimited bytes
+Max file locks unlimited unlimited locks
+Max pending signals 23554 23554 signals
+Max msgqueue size 819200 819200 bytes
+Max nice priority 0 0
+Max realtime priority 0 0
+Max realtime timeout unlimited unlimited us
+```
+
+#### pmap
+
+The **pmap** command takes you in an entirely different direction when it comes to memory use. It provides a detailed map of a process’s memory usage. To make sense of this, you need to keep in mind that processes do not run entirely on their own. Instead, they make use of a wide range of system resources. The truncated **pmap** output below shows a portion of the memory map for a single user’s bash login along with some memory usage totals at the bottom.
+
+```
+$ pmap -x 43120
+43120: -bash
+Address Kbytes RSS Dirty Mode Mapping
+000055887655b000 180 180 0 r---- bash
+0000558876588000 708 708 0 r-x-- bash
+0000558876639000 220 148 0 r---- bash
+0000558876670000 16 16 16 r---- bash
+0000558876674000 36 36 36 rw--- bash
+000055887667d000 40 28 28 rw--- [ anon ]
+0000558876b96000 1328 1312 1312 rw--- [ anon ]
+00007f0bd9a7e000 28 28 0 r---- libpthread-2.31.so
+00007f0bd9a85000 68 68 0 r-x-- libpthread-2.31.so
+00007f0bd9a96000 20 0 0 r---- libpthread-2.31.so
+00007f0bd9a9b000 4 4 4 r---- libpthread-2.31.so
+00007f0bd9a9c000 4 4 4 rw--- libpthread-2.31.so
+00007f0bd9a9d000 16 4 4 rw--- [ anon ]
+00007f0bd9aa1000 20 20 0 r---- libnss_systemd.so.2
+00007f0bd9aa6000 148 148 0 r-x-- libnss_systemd.so.2
+...
+ffffffffff600000 4 0 0 --x-- [ anon ]
+---------------- ------- ------- -------
+total kB 11368 5664 1656
+
+Kbytes: size of map in kilobytes
+RSS: resident set size in kilobytes
+Dirty: dirty pages (both shared and private) in kilobytes
+```
+```
+
+```
+
+Join the Network World communities on [Facebook][1] and [LinkedIn][2] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3543232/how-to-examine-processes-running-on-linux.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://www.facebook.com/NetworkWorld/
+[2]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200515 The pieces of Fedora Silverblue.md b/sources/tech/20200515 The pieces of Fedora Silverblue.md
new file mode 100644
index 0000000000..04bd4e1643
--- /dev/null
+++ b/sources/tech/20200515 The pieces of Fedora Silverblue.md
@@ -0,0 +1,172 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (The pieces of Fedora Silverblue)
+[#]: via: (https://fedoramagazine.org/pieces-of-fedora-silverblue/)
+[#]: author: (Nick Hardiman https://fedoramagazine.org/author/nickhardiman/)
+
+The pieces of Fedora Silverblue
+======
+
+![][1]
+
+Fedora Silverblue provides a useful workstation build on an immutable operating system. In “[What is Silverblue?][2]“, you learned about the benefits that an immutable OS provides. But what pieces go into making it? This article examines some of the technology that powers Silverblue.
+
+### The filesystem
+
+Fedora Workstation users may find the idea of an immutable OS to be the most brain-melting part of Silverblue. What does that mean? Find some answers by taking a look at the filesystem.
+
+At first glance, the layout looks pretty much the same as a regular Fedora file system. It has some differences, like making _/home_ a symbolic link to _/var/home_. And you can get more answers by looking at how libostree works. libostree treats the whole tree like it’s an object, checks it into a code repository, and checks out a copy for your machine to use.
+
+#### libostree
+
+The [libostree project][3] supplies the goods for managing Silverblue’s file system. It is an upgrade system that the user can control using [rpm-ostree commands][4].
+
+libostree knows nothing about packages—an upgrade means replacing one complete file system with another complete file system. libostree treats the file system tree as one atomic object (an unbreakable unit). In fact, the forerunner to Silverblue was named [Project Atomic][5].
+
+The libostree project provides a library and set of tools. It’s an upgrade system that carries out these tasks.
+
+ 1. Pull in a new file system
+ 2. Store the new file system
+ 3. Deploy the new file system
+
+
+
+##### Pull in a new file system
+
+Pulling in a new file system means copying an object (the entire file system) from a remote source to its own store. If you’ve worked with virtual machine image files, you already understand the concept of a file system object that you can copy.
+
+##### Store the new file system
+
+The libostree store has some source code control qualities—it stores many file system objects, and checks one out to be used as the root file system. libostree’s store has two parts:
+
+ * a repository database at _/sysroot/ostree/repo/_
+ * file systems in _/sysroot/ostree/deploy/fedora/deploy/_
+
+
+
+libostree keeps track of what’s been checked in using commit IDs. Each commit ID can be found in a directory name, nested deep inside _/sysroot_ .A libostree commit ID is a long checksum, and looks similar to a git commit ID.
+
+```
+$ ls -d /sysroot/ostree/deploy/fedora/deploy/*/
+/sysroot/ostree/deploy/fedora/deploy/c4bf7a6339e6be97d0ca48a117a1a35c9c5e3256ae2db9e706b0147c5845fac4.0/
+```
+
+_rpm-ostree status_ gives a little more information about that commit ID. The output is a little confusing; it can take a while to see this file system is Fedora 31.
+
+```
+$ rpm-ostree status
+State: idle
+AutomaticUpdates: disabled
+Deployments:
+● ostree://fedora:fedora/31/x86_64/silverblue
+ Version: 31.1.9 (2019-10-23T21:44:48Z)
+ Commit: c4bf7a6339e6be97d0ca48a117a1a35c9c5e3256ae2db9e706b0147c5845fac4
+ GPGSignature: Valid signature by 7D22D5867F2A4236474BF7B850CB390B3C3359C4
+```
+
+##### Deploy the new filesystem
+
+libostree deploys a new file system by checking out the new object from its store. libostree doesn’t check out a file system by copying all the files—it uses hard links instead. If you look inside the commit ID directory, you see something that looks suspiciously like the root directory. That’s because it _is_ the root directory. You can see these two directories are pointing to the same place by checking their inodes.
+
+```
+$ ls -di1 / /sysroot/ostree/deploy/fedora/deploy/*/
+260102 /
+260102 /sysroot/ostree/deploy/fedora/deploy/c4bf7a6339e6be97d0ca48a117a1a35c9c5e3256ae2db9e706b0147c5845fac4.0/
+```
+
+This is a fresh install, so there’s only one commit ID. After a system update, there will be two. If more copies of the file system are checked into libostree’s repo, more commit IDs appear here.
+
+##### Upgrade process
+
+Putting the pieces together, the update process looks like this:
+
+ 1. libostree checks out a copy of the file system object from the repository
+ 2. DNF installs packages into the copy
+ 3. libostree checks in the copy as a new object
+ 4. libostree checks out the copy to become the new file system
+ 5. You reboot to pick up the new system files
+
+
+
+In addition to more safety, there is more flexibility. You can do new things with libostree’s repo, like store a few different file systems and check out whichever one you feel like using.
+
+#### Silverblue’s root file system
+
+Fedora keeps its system files in all the usual Linux places, such as _/boot_ for boot files, _/etc_ for configuration files, and _/home_ for user home directories. The root directory in Silverblue looks much like the root directory in traditional Fedora, but there are some differences.
+
+ * The filesystem has been checked out by libostree
+ * Some directories are now symbolic links to new locations. For example, _/home_ is a symbolic link to _/var/home_
+ * _/usr_ is a read-only directory
+ * There’s a new directory named _/sysroot_. This is libostree’s new home
+
+
+
+#### Juggling file systems
+
+You can store many file systems and switch between them. This is called _rebasing_, and it’s similar to git rebasing. In fact, upgrading Silverblue to the next Fedora version is not a big package install—it’s a pull from a remote repository and a rebase.
+
+You could store three copies with three different desktops: one KDE, one GNOME, and one XFCE. Or three different OS versions: how about keeping the current version, the nightly build, and an old classic? Switching between them is a matter of rebasing to the appropriate file system object.
+
+Rebasing is also how you upgrade from one Fedora release to the next. See “[How to rebase to Fedora 32 on Silverblue][6]” for more information.
+
+### Flatpak
+
+The [Flatpak project][7] provides a way of installing applications like LibreOffice. Applications are pulled from remote repositories like [Flathub][8]. It’s a kind of package manager, although you won’t find the word _package_ in the [docs][9]. Traditional Fedora variants like Fedora Workstation can also use Flatpak, but the sandboxed nature of flatpaks make it particularly good for Silverblue. This way you do not have to do the entire ostree update process every time you wish to install an application.
+
+Flatpak is well-suited to desktop applications, but also works for command line applications. You can install the [vim][10] editor with the command _flatpak install flathub org.vim.Vim_ and run it with _flatpak run org.vim.Vim_.
+
+### toolbox
+
+The [toolbox project][11] provides a traditional operating system inside a container. The idea is that you can mess with the mutable OS inside your toolbox (the Fedora container) as much as you like, and leave the immutable OS outside your toolbox untouched. You pack as many toolboxes as you want on your system, so you can keep work separated. Behind the scenes, the executable _/usr/bin/toolbox_ is a shell script that uses [podman][12].
+
+A fresh install does not include a default toolbox. The _toolbox create_ command checks the OS version (by reading _/usr/lib/os-release_), looks for a matching version at the Fedora container registry, and downloads the container.
+
+```
+$ toolbox create
+Image required to create toolbox container.
+Download registry.fedoraproject.org/f31/fedora-toolbox:31 (500MB)? [y/N]: y
+Created container: fedora-toolbox-31
+Enter with: toolbox enter
+```
+
+Hundreds of packages are installed inside the toolbox. The _dnf_ command and the usual Fedora repos are set up, ready to install more. The _ostree_ and _rpm-ostree_ commands are not included – no immutable OS here.
+
+Each user’s home directory is mounted on their toolbox, for storing content files outside the container.
+
+### Put the pieces together
+
+Spend some time exploring Fedora Silverblue and it will become clear how these components fit together. Like other Fedora variants, all these of tools come from open source projects. You can get as up close and personal as you want, from reading their docs to contributing code. Or you can [contribute to Silverblue][13] itself.
+
+Join the Fedora Silverblue conversations on [discussion.fedoraproject.org][14] or in [#silverblue on Freenode IRC][15].
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/pieces-of-fedora-silverblue/
+
+作者:[Nick Hardiman][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://fedoramagazine.org/author/nickhardiman/
+[b]: https://github.com/lujun9972
+[1]: https://fedoramagazine.org/wp-content/uploads/2020/04/silverblue-pieces-816x345.png
+[2]: https://fedoramagazine.org/what-is-silverblue/
+[3]: https://ostree.readthedocs.io/en/latest/
+[4]: https://rpm-ostree.readthedocs.io/en/latest/manual/administrator-handbook/#administering-an-rpm-ostree-based-system
+[5]: https://www.projectatomic.io/
+[6]: https://fedoramagazine.org/how-to-rebase-to-fedora-32-on-silverblue/
+[7]: https://github.com/flatpak/flatpak
+[8]: https://flathub.org/
+[9]: http://docs.flatpak.org/en/latest/index.html
+[10]: https://www.vim.org/
+[11]: https://github.com/containers/toolbox
+[12]: https://github.com/containers/libpod
+[13]: https://silverblue.fedoraproject.org/contribute
+[14]: https://discussion.fedoraproject.org/c/desktop/silverblue
+[15]: https://webchat.freenode.net/#silverblue
diff --git a/sources/tech/20200516 Fatih-s question.md b/sources/tech/20200516 Fatih-s question.md
new file mode 100644
index 0000000000..1225c624a8
--- /dev/null
+++ b/sources/tech/20200516 Fatih-s question.md
@@ -0,0 +1,214 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Fatih’s question)
+[#]: via: (https://dave.cheney.net/2020/05/16/fatihs-question)
+[#]: author: (Dave Cheney https://dave.cheney.net/author/davecheney)
+
+Fatih’s question
+======
+
+A few days ago Fatih posted [this question][1] on twitter.
+
+I’m going to attempt to give my answer, however to do that I need to apply some simplifications as my previous attempts to answer it involved a lot of phrases like _a pointer to a pointer_, and other unhelpful waffling. Hopefully my simplified answer can be useful in building a mental framework to answer Fatih’s original question.
+
+### Restating the question
+
+Fatih’s original tweet showed [four different variations][2] of `json.Unmarshal`. I’m going to focus on the last two, which I’ll rewrite a little:
+
+```
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type Result struct {
+ Foo string `json:"foo"`
+}
+
+func main() {
+ content := []byte(`{"foo": "bar"}`)
+ var result1, result2 *Result
+
+ err := json.Unmarshal(content, &result1)
+ fmt.Println(result1, err) // &{bar}
+
+ err = json.Unmarshal(content, result2)
+ fmt.Println(result2, err) // json: Unmarshal(nil *main.Result)
+}
+```
+
+Restated in words, `result1` and `result2` are the same type; `*Result`. Decoding into `result1` works as expected, whereas decoding into `result2` causes the `json` package to complain that the value passed to `Unmarshal` is `nil`. However, both values were declared without an initialiser so both would have taken on the type’s zero value, `nil`.
+
+Eagle eyed readers will have spotted that the reason for the difference is the first` `invocation is passed `&result1`, while the second is passed `result2`, but this explanation is unsatisfactory because the documentation for `json.Unmarshal` states:
+
+> Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. **If v is nil or not a pointer**, Unmarshal returns an InvalidUnmarshalError.
+
+Which is confusing because `result1` and `result2` _are_ pointers. Furthermore, without initialisation, both _are_ `nil`. Now, the documentation is correct (as you’d expect from a package that has been hammered on for a decade), but explaining _why_ takes a little more investigation.
+
+### Functions receive a copy of their arguments
+
+Every assignment in Go is a copy, this includes function arguments and return values.
+
+```
+package main
+
+import (
+ "fmt"
+)
+
+func increment(v int) {
+ v++
+}
+
+func main() {
+ v := 1
+ increment(v)
+ fmt.Println(v) // 1
+}
+```
+
+In this example, `increment` is operating on a _copy_ of `main`‘s `v`. This is because the `v` declared in `main` and `increment`‘s `v` parameter have different addresses in memory. Thus changes to `increment`‘s `v` cannot affect the contents of `main`‘s `v`.
+
+```
+package main
+
+import (
+ "fmt"
+)
+
+func increment(v *int) {
+ *v++
+}
+
+func main() {
+ v := 1
+ increment(&v)
+ fmt.Println(v) // 2
+}
+```
+
+If we wanted to write `increment` in a way that it could affect the contents of its caller we would need to pass a reference, a pointer, to `main.v`.[1][3] This example demonstrates why `json.Unmarshal` needs a pointer to the value to decode JSON into.
+
+### Pointers to pointers
+
+Returning to the original question, both `result1` and `result2` are declared as `*Result`, that is, pointers to a `Result` value. We established that you have to pass the address of caller’s value to `json.Unmarshal` otherwise it won’t be able to alter the contents of the caller’s value. Why then must we pass the address of `result1`, a `**Result`, a pointer to a pointer to a `Result`, for the operation to succeed.
+
+To explain this another detour is required. Consider this code:
+
+```
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type Result struct {
+ Foo *string `json:"foo"`
+}
+
+func main() {
+ content := []byte(`{"foo": "bar"}`)
+ var result1 *Result
+
+ err := json.Unmarshal(content, &result1)
+ fmt.Printf("%#v %v", result1, err) // &main.Result{Foo:(*string)(0xc0000102f0)}
+}
+```
+
+In this example `Result` contains a pointer typed field, `Foo *string`. During JSON decoding `Unmarshal` allocated a new `string` value, stored the value `bar` in it, then placed the address of the string in `Result.Foo`. This behaviour is quite handy as it frees the caller from having to initialise `Result.Foo` and makes it easier to detect when a field was not initialised because the JSON did not contain a value. Beyond the convenience this offers for simple examples it would be prohibitively difficult for the caller to properly initialise all the reference type fields in a structure before decoding unknown JSON without first inspecting the incoming JSON which itself may be problematic if the input is coming from an `io.Reader` without the ability to rewind the input.
+
+> To unmarshal JSON into a pointer, Unmarshal first handles the case of the JSON being the JSON literal null. In that case, Unmarshal sets the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into the value pointed at by the pointer. **If the pointer is nil, Unmarshal allocates a new value for it to point to**.
+
+`json.Unmarshal`‘s handling of pointer fields is clearly documented, and works as you would expect, allocating a new value whenever there is a need to decode into a pointer shaped field. It is this behaviour that gives us a hint to what is happening in the original example.
+
+We’ve seen that when `json.Unmarshal` encounters a field which points to `nil` it will allocate a new value of the correct type and assign its address the field before proceeding. Not only is does behaviour is applied recursively–for example in the case of a complex structure which contains pointers to other structures–but it also applies to the _value passed to `Unmarshal`._
+
+```
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+func main() {
+ content := []byte(`1`)
+ var result *int
+
+ err := json.Unmarshal(content, &result)
+ fmt.Println(*result, err) // 1
+}
+```
+
+In this example `result` is not a struct, but a simple `*int` which, lacking an initialiser, defaults to `nil`. After JSON decoding, `result` now points to an `int` with the value `1`.
+
+### Putting the pieces together
+
+Now I think I’m ready to take a shot at answering Fatih’s question.
+
+`json.Unmarshal` requires the address of the variable you want to decode into, otherwise it would decode into a temporary copy which would be discard on return. Normally this is done by declaring a value, then passing its address, or explicitly initialising the the value
+
+```
+var result1 Result
+err := json.Unmarshal(content, &result1) // this is fine
+
+var result2 = new(Result)
+err = json.Unmarshal(content, result2) // and this
+
+var result3 = &Result{}
+err = json.Unmarshal(content, result3) // this is also fine
+```
+
+In all three cases the address that the `*Result` points too is not `nil`, it points to initialised memory that `json.Unmarshal` decodes into.
+
+Now consider what happens when `json.Unmarshal` encounters this
+
+```
+var result4 *Result
+err = json.Unmarshal(content, result4) // err json: Unmarshal(nil *main.Result)
+```
+
+`result2`, `result3`, and the expression `&result1` point to a `Result`. However `result4`, even though it has the same type as the previous three, does not point to initialised memory, it points to `nil`. Thus, according to the examples we saw previously, before `json.Unmarshal` can decode into it, the memory `result4` points too must be initialised.
+
+However, because each function receives a copy of its arguments, the caller’s `result4` variable and the copy inside `json.Unmarshal` are unique. `json.Unmarshal` can allocate a new `Result` value and decode into it, but it cannot alter `result4` to point to this new value because it was not provided with a reference to `result4`, only a copy of its contents.
+
+ 1. This does not violate the _everything is a copy_ rule, a copy of a pointer to `main.v` still points to `main.v`.[][4]
+
+
+
+#### Related posts:
+
+ 1. [Should methods be declared on T or *T][5]
+ 2. [Ice cream makers and data races][6]
+ 3. [Understand Go pointers in less than 800 words or your money back][7]
+ 4. [Slices from the ground up][8]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://dave.cheney.net/2020/05/16/fatihs-question
+
+作者:[Dave Cheney][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://dave.cheney.net/author/davecheney
+[b]: https://github.com/lujun9972
+[1]: https://twitter.com/fatih/status/1260683136842608640
+[2]: https://play.golang.org/p/g2yUIYrV67F
+[3]: tmp.dRxkHxYRQS#easy-footnote-bottom-1-4153 (This does not violate the everything is a copy rule, a copy of a pointer to main.v still points to main.v.)
+[4]: tmp.dRxkHxYRQS#easy-footnote-1-4153
+[5]: https://dave.cheney.net/2016/03/19/should-methods-be-declared-on-t-or-t (Should methods be declared on T or *T)
+[6]: https://dave.cheney.net/2014/06/27/ice-cream-makers-and-data-races (Ice cream makers and data races)
+[7]: https://dave.cheney.net/2017/04/26/understand-go-pointers-in-less-than-800-words-or-your-money-back (Understand Go pointers in less than 800 words or your money back)
+[8]: https://dave.cheney.net/2018/07/12/slices-from-the-ground-up (Slices from the ground up)
diff --git a/sources/tech/20200518 Using Fedora to implement REST API in JavaScript- part 2.md b/sources/tech/20200518 Using Fedora to implement REST API in JavaScript- part 2.md
new file mode 100644
index 0000000000..b02822c4fa
--- /dev/null
+++ b/sources/tech/20200518 Using Fedora to implement REST API in JavaScript- part 2.md
@@ -0,0 +1,208 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Using Fedora to implement REST API in JavaScript: part 2)
+[#]: via: (https://fedoramagazine.org/using-fedora-to-implement-rest-api-in-javascript-part-2/)
+[#]: author: (Vaclav Keil https://fedoramagazine.org/author/vaclavk/)
+
+Using Fedora to implement REST API in JavaScript: part 2
+======
+
+![][1]
+
+In [part 1][2] previously, you saw how to quickly create a simple API service using Fedora Workstation, Express, and JavaScript. This article shows you the simplicity of how to create a new API. This part shows you how to:
+
+ * Install a DB server
+ * Build a new route
+ * Connect a new datasource
+ * Use Fedora terminal to send and receive data
+
+
+
+### Generating an app
+
+Please refer to the [previous article][2] for more details. But to make things simple, change to your work directory and generate an app skeleton.
+```
+
+```
+
+$ cd our-work-directory
+$ npx express-generator –no-view –git /myApp
+$ cd myApp
+$ npm i
+```
+
+```
+
+### Installing a database server
+
+In this part, we’ll install MariaDB database. MariaDB is the Fedora default database.
+
+```
+$ dnf module list mariadb | sort -u ## lists the streams available
+$ sudo dnf module install mariadb:10.3 ##10.4 is the latest
+```
+
+_Note: the default profile is mariadb/server_.
+
+For those who need to spin up a Docker container a ready made container with Fedora 31 is available.
+
+```
+$ docker pull registry.fedoraproject.org/f31/mariadb
+$ docker run -d --name mariadb_database -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -e MYSQL_DATABASE=db -p 3306:3306 registry.fedoraproject.org/f31/mariadb
+```
+
+Now start the MariaDB service.
+
+```
+$ sudo systemctl start mariadb
+```
+
+If you’d like the service to start at boot, you can also enable it in systemd:
+
+```
+$ sudo systemctl enable mariadb ## start at boot
+```
+
+Next, setup the database as needed:
+
+```
+$ mysql -u root -p ## root password is blank
+MariaDB> CREATE DATABASE users;
+MariaDB> create user dbuser identified by ‘123456‘;
+MariaDB> grant select, insert, update, create, drop on users.* to dbuser;
+MariaDB> show grants for dbuser;
+MariaDB> \q
+```
+
+A database connector is needed to use the database with Node.js.
+
+```
+$ npm install mariadb ## installs MariaDB Node.js connector
+```
+
+We’ll leverage Sequelize in this sample API. Sequelize is a promise-based Node.js ORM (Object Relational Mapper) for Postgres, MySQL, MariaDB, SQLite and Microsoft SQL Server.
+
+```
+$ npm install sequelize ## installs Sequelize
+```
+
+### Connecting a new datasource
+
+Now, create a new _db_ folder and create a new file _sequelize.js_ there:
+
+```
+const Sequelize = require('sequelize'),
+ sequelize = new Sequelize(process.env.db_name || 'users', process.env.db_user || 'dbuser', process.env.db_pass || '123456', {
+ host: 'localhost',
+ dialect: 'mariadb',
+ ssl: true
+})
+
+module.exports = sequelize
+```
+
+_Note: For the sake of completeness I‘m including a link to the related Github repo: _
+
+Let‘s create a new file _models/user.js_. A nice feature of a Sequelize model is that it helps us to create the necessary tables and colums automatically. The code snippet responsible for doing this is seen below:
+
+```
+sequelize.sync({
+force: false
+})
+```
+
+Note: never switch to true with a production database – it would _drop your tables at app start_!
+
+We will refer to the earlier created sequelize.js this way:
+
+```
+const sequelize = require('../db/sequelize')
+```
+
+### Building new routes
+
+Next, you’ll create a new file _routes/user.js_. You already have _routes/users.js_ from the previous article. You can copy and paste the code in and proceed with editing it.
+
+You’ll also need a reference to the previously created model.
+
+```
+const User = require('../models/user')
+```
+
+Change the route path to _/users_ and also create a new **post** method route.
+
+Mind the async – await keywords there. An interaction with a database will take some time and this one will do the trick. Yes, an async function returns a promise and this one makes promises easy to use.
+
+_Note: This code is not production ready, since it would also need to include an authentication feature._
+
+We‘ll make the new route working this way:
+
+```
+const userRouter = require('./routes/user')
+app.use(userRouter)
+```
+
+Let‘s also remove the existing _usersRouter_. The _routes/users.js_ can be deleted too.
+
+```
+$ npm start
+```
+
+With the above command, you can launch your new app.
+
+### Using the terminal to send and retrieve data
+
+Let’s create a new database record through the post method:
+
+```
+$ curl -d 'name=Adam' http://localhost:3000/users
+```
+
+To retrieve the data created through the API, do an HTTP GET request:
+
+```
+$ curl http://localhost:3000/users
+```
+
+The console output of the curl command is a JSON array containing data of all the records in the _Users_ table.
+
+_Note: This is not really the usual end result — an application consumes the API finally. The API will usually also have endpoints to update and remove data._
+
+### More automation
+
+Let‘s assume we might want to create an API serving many tables. It‘s possible and very handy to automatically generate models for Sequelize from our database. Sequelize-auto will do the heavy lifting for us. The resulting files (_models.js_) would be placed and imported within the _/models_ directory.
+
+```
+$ npm install sequelize-auto
+```
+
+A node.js connector is needed to use this one and we have it already installed for MariaDB.
+
+### Conclusion
+
+It‘s possible to develop and run an API using Fedora, Fedora default MariaDB, JavaScript and efficiently develop a solution like with a noSQL database. For those used to working with MongoDB or a similar noSQL database, Fedora and MariaDB are important open-source enablers.
+
+* * *
+
+_Photo by [Mazhar Zandsalimi][3] on [Unsplash][4]._
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/using-fedora-to-implement-rest-api-in-javascript-part-2/
+
+作者:[Vaclav Keil][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://fedoramagazine.org/author/vaclavk/
+[b]: https://github.com/lujun9972
+[1]: https://fedoramagazine.org/wp-content/uploads/2020/05/javascript-api-2-816x345.jpg
+[2]: https://fedoramagazine.org/using-fedora-to-quickly-implement-rest-api-with-javascript/
+[3]: https://unsplash.com/@m47h4r?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
+[4]: https://unsplash.com/s/photos/javascript?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText
diff --git a/sources/tech/20200519 How to use Windows Subsystem for Linux to open Linux on Windows 10 machines.md b/sources/tech/20200519 How to use Windows Subsystem for Linux to open Linux on Windows 10 machines.md
new file mode 100644
index 0000000000..e610f7eb2f
--- /dev/null
+++ b/sources/tech/20200519 How to use Windows Subsystem for Linux to open Linux on Windows 10 machines.md
@@ -0,0 +1,153 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to use Windows Subsystem for Linux to open Linux on Windows 10 machines)
+[#]: via: (https://www.networkworld.com/article/3543845/how-to-use-windows-subsystem-for-linux-to-open-linux-on-windows-10-machines.html)
+[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
+
+How to use Windows Subsystem for Linux to open Linux on Windows 10 machines
+======
+Opening a Linux terminal on a Windows 10 desktop can help you practice your Linux skills and explore Windows from an entirely different point of view. In this post, we look at Ubuntu 18.04 running through Windows Subsystem for Linux (WSL).
+[Nicolas Solerieu modified by IDG Comm. / Linux][1] [(CC0)][2]
+
+Believe it or not, it's possible to open a Linux terminal on a Windows 10 system and you might be surprised how much Linux functionality you’ll be able to get by doing so.
+
+You can run Linux commands, traipse around the provided Linux file system and even take a novel look at Windows files. The experience isn’t altogether different than opening a terminal window on a Linux desktop, with a few interesting exceptions.
+
+[[Get regularly scheduled insights by signing up for Network World newsletters.]][3]
+
+What is needed to make this happen is something called the Windows Subsystem for Linux (WSL) and a Windows 10 x86 PC.
+
+### Linux versions for WSL
+
+There are a number of options for running Linux on top of Windows. The Linux OS choices include:
+
+ * [Ubuntu 16.04 LTS][4]
+ * [Ubuntu 18.04 LTS][5]
+ * [openSUSE Leap 15.1][6]
+ * [SUSE Linux Enterprise Server 12 SP5][7]
+ * [SUSE Linux Enterprise Server 15 SP1][8]
+ * [Kali Linux][9]
+ * [Debian GNU/Linux][10]
+ * [Fedora Remix for WSL][11]
+ * [Pengwin][12]
+ * [Pengwin Enterprise][13]
+ * [Alpine WSL][14]
+
+
+
+Ubuntu 18.04 LTS is just one option and, in this post, we’ll take a look at how the terminal runs on Windows using this particular distribution and how much it feels like working on a Linux system directly.
+
+If you want to look into the process of putting an Ubuntu distribution on your Windows system, you can start with this page:
+
+
+
+As part of the initial setup of installing your Linux on Windows terminal, you’ll be asked to create your user account. Once you do that and open the terminal, you can start to explore. One of the most noticeable differences between your Linux-on-Windows terminal and a terminal window on a Linux system is that examining processes isn’t going to show you much. After all, Windows will be providing the bulk of the required OS support. You’re likely to see something like this:
+
+```
+myacct@hostname:~$ ps -ef
+UID PID PPID C STIME TTY TIME CMD
+root 1 0 0 12:45 ? 00:00:00 /init
+root 7 1 0 12:45 tty1 00:00:00 /init
+shs 8 7 0 12:45 tty1 00:00:00 -bash
+shs 166 8 0 13:32 tty1 00:00:00 ps -ef
+```
+
+Yes, that's it.
+
+If you’re anything like me, one of your next moves might be to get a handle on the available commands. If you just count the files in the **/bin** and **/usr/bin** directories, you should see that there are a lot of commands:
+
+```
+myacct@hostname:~$ ls /bin | wc -l
+171
+myacct@hostname:~$ ls /usr/bin | wc -l
+707
+```
+
+You can list available commands with commands like these (output truncated for this post):
+
+```
+myacct@hostname:~$ ls /bin | head -25 | column
+bash btrfs-map-logical bunzip2 bzegrep bzip2recover
+btrfs btrfs-select-super busybox bzexe bzless
+btrfs-debug-tree btrfs-zero-log bzcat bzfgrep bzmore
+btrfs-find-root btrfsck bzcmp bzgrep cat
+btrfs-image btrfstune bzdiff bzip2 chacl
+
+myacct@hostname:~$ ls /usr/bin | head -25 | column
+NF aa-exec apport-cli apt apt-extracttempl*
+VGAuthService acpi_listen apport-collect apt-add-repository apt-ftparchive
+X11 add-apt-repository apport-unpack apt-cache apt-get
+[ addpart appres apt-cdrom apt-key
+aa-enabled apport-bug apropos apt-config apt-mark
+```
+
+You can update the system with **apt** commands (sudo apt update, sudo apt upgrade). You can even use Linux commands to move to the Windows disk partitions as you like and . Notice the last three entries in the output below. These represent several drives on the system.
+
+```
+myacct@hostname:~$ df -k
+Filesystem 1K-blocks Used Available Use% Mounted on
+rootfs 973067784 326920584 646147200 34% /
+none 973067784 326920584 646147200 34% /dev
+none 973067784 326920584 646147200 34% /run
+none 973067784 326920584 646147200 34% /run/lock
+none 973067784 326920584 646147200 34% /run/shm
+none 973067784 326920584 646147200 34% /run/user
+cgroup 973067784 326920584 646147200 34% /sys/fs/cgroup
+C:\ 973067784 326920584 646147200 34% /mnt/c <== C drive
+I:\ 976760000 231268208 745491792 24% /mnt/I <== external drive
+L:\ 409599996 159240 409440756 1% /mnt/l <== USB thumb drive
+```
+
+If you’re interested in moving out of the Linux space and into the Windows portion of the file system within your **WSL** session, you can do that easily. Replace “myname” with your Windows account name and a **cd /mnt/c/Users/_myname_/Desktop** will take you to your Windows desktop. From there, don’t be surprised if in listing your files you see **WRL####.tmp** files that don’t seem to exist when you look at your desktop and don’t show up if you look at your files by opening a command prompt. These appear to be temporary files used by Windows for document management. You might also see files listed that look like **‘~$nux notes.docx’** – perhaps ghosts of files that were once located on your desktop. You won’t see those files when you look at your desktop on Windows – even using a **cmd** window.
+
+Note that you’ll also see Windows directories such as **‘Program Files’** in single quotes when listed in your Linux terminal as you would any file with blanks included in their names. You can even start a Windows executable from your Linux terminal. For example:
+
+```
+myacct@hostname: $ cd /mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0
+myacct@hostname: $ powershell.exe
+```
+
+If you do this, type **exit** when you want to end the **powershell** session.
+
+Linux commands all seem to work as expected, though I don’t get any output when I run the **who** command.
+
+Windows **.txt** files will display with **cat** commands, but the last line in a file will likely be displayed on the same line as the following shell prompt. This is because these files won’t end with a linefeed as Linux text files do.
+
+You can create other accounts and switch user to them (e.g., **su – nemo**) if you like, but not log into them directly.
+
+You can also update the system with apt commands (**sudo apt update**, **sudo apt upgrade**).
+
+Join the Network World communities on [Facebook][15] and [LinkedIn][16] to comment on topics that are top of mind.
+
+--------------------------------------------------------------------------------
+
+via: https://www.networkworld.com/article/3543845/how-to-use-windows-subsystem-for-linux-to-open-linux-on-windows-10-machines.html
+
+作者:[Sandra Henry-Stocker][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
+[b]: https://github.com/lujun9972
+[1]: https://unsplash.com/photos/4gRNmhGzYZE
+[2]: https://creativecommons.org/publicdomain/zero/1.0/
+[3]: https://www.networkworld.com/newsletters/signup.html
+[4]: https://www.microsoft.com/store/apps/9pjn388hp8c9
+[5]: https://www.microsoft.com/store/apps/9N9TNGVNDL3Q
+[6]: https://www.microsoft.com/store/apps/9NJFZK00FGKV
+[7]: https://www.microsoft.com/store/apps/9MZ3D1TRP8T1
+[8]: https://www.microsoft.com/store/apps/9PN498VPMF3Z
+[9]: https://www.microsoft.com/store/apps/9PKR34TNCV07
+[10]: https://www.microsoft.com/store/apps/9MSVKQC78PK6
+[11]: https://www.microsoft.com/store/apps/9n6gdm4k2hnc
+[12]: https://www.microsoft.com/store/apps/9NV1GV1PXZ6P
+[13]: https://www.microsoft.com/store/apps/9N8LP0X93VCP
+[14]: https://www.microsoft.com/store/apps/9p804crf0395
+[15]: https://www.facebook.com/NetworkWorld/
+[16]: https://www.linkedin.com/company/network-world
diff --git a/sources/tech/20200520 Fedora Silverblue, an introduction for developers.md b/sources/tech/20200520 Fedora Silverblue, an introduction for developers.md
new file mode 100644
index 0000000000..a112f4ca6d
--- /dev/null
+++ b/sources/tech/20200520 Fedora Silverblue, an introduction for developers.md
@@ -0,0 +1,140 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Fedora Silverblue, an introduction for developers)
+[#]: via: (https://fedoramagazine.org/fedora-silverblue-brings-future-tech-to-the-desktop/)
+[#]: author: (Nick Hardiman https://fedoramagazine.org/author/nickhardiman/)
+
+Fedora Silverblue, an introduction for developers
+======
+
+![][1]
+
+The Fedora [Silverblue project][2] takes Fedora workstation, libostree and podman, puts them in a blender, and creates a new Immutable Fedora Workstation. Fedora Silverblue is an OS that stops you from changing the core system files arbitrarily, and readily allows you to change the environment system files. The article [What is Silverblue][3] describes the big picture, and this article drills down into details for the developer.
+
+Fedora Silverblue ties together a few different projects to make a system that is a git-like object, capable of layering packages, and has a container focused work flow. Silverblue is not the only distribution going down this road. It is the desktop equivalent of [CoreOS][4], the server OS used by [Red Hat Openshift][5].
+
+Silverblue’s idea of ‘immutable’ has nothing to do with immutable layers in a container. Silverblue keeps system files immutable by making them read-only.
+
+### Why immutable?
+
+Has an upgrade left your system in an unusable state? Have you wondered why one server in a pool of identical machines is being weird? These problems can happen when one system library – one tiny little file out of hundreds – is corrupted, badly configured or the wrong version. Or maybe your upgrade works fine but it’s not what you’d hoped for, and you want to roll back to the previous state.
+
+An immutable OS is intended to stop problems like these biting you. This is not an easy thing to achieve – simple changes, like flipping the file system between read-write and read-only, may only change a fault-finding headache to a maintenance headache.
+
+Freezing the system is good news for sysadmins, but what about developers? Setting up a development environment means heavily customizing the system, and filling it with living code that changes over time. The answer is partly a case of combining components, and partly the ability to swap between OS versions.
+
+### How it works
+
+So how do you get the benefits of immutability without losing the ability to do your work? If you’re thinking ‘containers’, good guess – part of the solution uses [podman][6]. But much of the work happens underneath the container layer, at the OS level.
+
+Fedora Silverblue ties together a few different projects to turn an immutable OS into a usable workstation. Silverblue uses libostree to provide the base system, lets you edit config files in /etc/, and provides three different ways to install packages.
+
+ * [rpm-ostree][7] installs RPM packages, similar to DNF in the traditional Fedora workstation. Use this for things that shouldn’t go in containers, like KVM/libvirt.
+ * [flatpak][8] installs packages from a central flathub repo. This is the one-stop shop for graphical desktop apps like LibreOffice.
+ * The traditional _dnf install_ still works, but only inside a [toolbox][9] (a Fedora container). A developer’s workbench goes in a toolbox.
+
+
+
+If you want to know more about these components, check out [Pieces of Silverblue][10].
+
+### Rolling back and pinning upgrades
+
+All operating systems need upgrades. Features are added, security holes are plugged and bugs are squashed. But sometimes an upgrade is not a developer’s friend.
+
+A developer depends on many things to get the job done. A good development environment is stuffed with libraries, editors, toolchains and apps that are controlled by the OS, not the developer. An upgrade may cause trouble. Have any of these situations happened to you?
+
+ * A new encryption library is too strict, and an upgrade stopped an API working.
+ * Code works well, but has deprecated syntax. An upgrade brought error-throwing misery.
+ * The development environment is lovingly hand-crafted. An upgrade broke dependencies and added conflicts.
+
+
+
+In a traditional environment, unpicking a troublesome upgrade is hard. In Silverblue, it’s easy. Silverblue keeps two copies of the OS – your current upgrade and your previous version. Point the OS at the previous version, reboot, and you’ve got your old system files back.
+
+You aren’t limited to two copies of your file system – you can keep more by pinning your favorite versions. Dusty Mabe, one of the engineers who has been working on the system since the [Project Atomic][11] days, describes how to pin extra copies of the OS in his article [Pinning Deployments in OSTree Based Systems][12].
+
+Your home directory is not affected by rolling back. Rpm-ostree does not touch /etc/ and /var/.
+
+### System updates and package installs
+
+Silverblue’s rpm-ostree treats all the files as one object, stored in a repository. The working file system is a checked-out copy of this object. After a system update, you get two objects in that repository – one current object and one updated object. The updated object is checked out and becomes the new file system.
+
+You install your workhorse applications in toolboxes, which provide container isolation. And you install your desktop applications using Flatpak.
+
+This new OS requires a shift in approach. For instance, you don’t have to keep only one copy of your system files – you can store a few and select which one you use. That means you can swap back and forth between an old Fedora release and the rawhide (development) version in a matter of minutes.
+
+### Build your own Silverblue VM
+
+You can safely install Fedora Silverblue in a VM on your workstation. If you’ve got a hypervisor and half an hour to spare (10 minutes for ISO download, and 20 minutes for the build), you can see for yourself.
+
+ 1. Download Fedora Silverblue ISO from
+ 2. (not Fedora workstation from ).
+ 3. Boot a VM with the Fedora Silverblue ISO. You can squeeze Fedora into compute resources of 1 CPU, 1024MiB of memory and 12GiB of storage, but bigger is better.
+ 4. Answer [Anaconda][13]’s questions.
+ 5. Wait for the [Gnome][14] desktop to appear.
+ 6. Answer [Initial Setup][15]’s questions.
+
+
+
+Then you’re ready to set up your developer’s tools. If you’re looking for an IDE, check these out. Use flatpak on the desktop to install them.
+
+ * [Gnome Builder][16] (Gnome’s official IDE)
+ * [Eclipse][17]
+ * [Code::Blocks][18]
+
+
+
+Finally, use the CLI to create your first toolbox. Load it with modules using [npm][19], [gem][20], [pip][21], [git][22] or your other favorite tools.
+
+### Help!
+
+If you get stuck, ask questions at the [forum][23].
+
+If you’re looking for ideas about how to use Silverblue, read articles in the [magazine][24].
+
+### Is Silverblue for you?
+
+Silverblue is full of shiny new tech. That in itself is enough to attract the cool kids, like moths to a flame. But this OS is not for everyone. It’s a young system, so some bugs will still be lurking in there. And pioneering tech requires a change of habit – that’s extra cognitive load that the new user may not want to take on.
+
+The OS brings immutable benefits, like keeping your system files safe. It also brings some drawbacks, like the need to reboot after adding system packages. Silverblue also enables new ways of working. If you want to explore new directions in the OS, find out if Silverblue brings benefits to your work.
+
+--------------------------------------------------------------------------------
+
+via: https://fedoramagazine.org/fedora-silverblue-brings-future-tech-to-the-desktop/
+
+作者:[Nick Hardiman][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://fedoramagazine.org/author/nickhardiman/
+[b]: https://github.com/lujun9972
+[1]: https://fedoramagazine.org/wp-content/uploads/2020/04/silverblue-introfordev-816x345.png
+[2]: https://silverblue.fedoraproject.org/
+[3]: https://fedoramagazine.org/what-is-silverblue/
+[4]: http://coreos.com/
+[5]: https://www.openshift.com/products/container-platform
+[6]: https://github.com/containers/libpod
+[7]: https://rpm-ostree.readthedocs.io/en/latest/
+[8]: https://docs.flatpak.org/en/latest/
+[9]: https://github.com/containers/toolbox
+[10]: https://fedoramagazine.org/pieces-of-fedora-silverblue/
+[11]: https://www.projectatomic.io/
+[12]: https://www.projectatomic.io/blog/2018/05/pinning-deployments-ostree-based-systems/
+[13]: https://fedoraproject.org/wiki/Anaconda
+[14]: https://www.gnome.org/
+[15]: https://fedoraproject.org/wiki/InitialSetup
+[16]: https://wiki.gnome.org/Apps/Builder
+[17]: https://www.eclipse.org/ide/
+[18]: http://www.codeblocks.org/
+[19]: https://www.npmjs.com/package/package
+[20]: https://rubygems.org/
+[21]: https://pypi.org/
+[22]: https://git-scm.com/
+[23]: https://discussion.fedoraproject.org/c/desktop/silverblue/6
+[24]: https://fedoramagazine.org/?s=silverblue
diff --git a/sources/tech/20200521 Glico (Weighted Rock Paper Scissors).md b/sources/tech/20200521 Glico (Weighted Rock Paper Scissors).md
new file mode 100644
index 0000000000..77e3cfb5ed
--- /dev/null
+++ b/sources/tech/20200521 Glico (Weighted Rock Paper Scissors).md
@@ -0,0 +1,141 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Glico (Weighted Rock Paper Scissors))
+[#]: via: (https://theartofmachinery.com/2020/05/21/glico_weighted_rock_paper_scissors.html)
+[#]: author: (Simon Arneaud https://theartofmachinery.com)
+
+Glico (Weighted Rock Paper Scissors)
+======
+
+This still isn’t the blog post I said I was going to write about now, but I figured some game theory would make a good post at the moment, especially when a lot of people I know are working at home with kids who need entertaining. Here’s some stuff about a traditional Japanese kids’ game called Glico, a form of weighted Rock Paper Scissors (RPS).
+
+### Glico
+
+I’ll assume you’re familiar with regular RPS. It’s pretty obvious how to play well: the three plays, “rock”, “paper” and “scissors”, are equally strong, so the only trick is to play them unpredictably enough.
+
+But what happens if the three plays have different values? Weighted RPS, under the name “Glico”, has been a well-known Japanese children’s game since at least before WWII, but let me explain an English adaptation. Traditionally it’s played starting at the bottom of a flight of stairs, and the aim is to get to the top first. Players can climb up steps by winning rounds of RPS. The trick is that the number of steps depends on the winning hand in each round. A player who wins with “rock” gets to climb up four steps by spelling out R-O-C-K, and similarly “paper” is worth five steps and “scissors” worth eight. This simple twist to the game creates whole new layers of offence and defence as players struggle to win with “scissors” as much as possible, without being too predictable and vulnerable.
+
+(The rules for the Japanese version vary by region, but usually “rock” is worth 3 steps, while “paper” and “scissors” are worth 6. The mnemonic is that “rock”, “paper” and “scissors” are referred to as グー, パー and チョキ respectively, and the words spelled out when playing are グリコ (“Glico”, a food/confectionary brand), パイナップル (pineapple) and チョコレート (chocolate).)
+
+Just a few notes before getting into the maths: The game works best with two players, but in the traditional rules for three or more players, each round is handled by having multiple rematches. Each time there’s a clear winning hand (e.g., two players with “paper” beating one with “rock”) the losers are eliminated until there’s one winner. That can take a long time, so cycling systematically between pairs of players might be faster for several players. (I’ll assume two players from now on.) Also, older kids sometimes add an extra challenge by requiring an exact landing at the top of the stairs to win. For example, if you’re five steps from the top, only “paper” will win; “scissors” will overshoot by three steps, and you’ll end up three steps back down from the top. Be warned: that makes gameplay a lot harder.
+
+### Calculating the optimal strategy
+
+Simple strategies like “just play rock” are what game theorists call “pure strategies”. By design, no pure strategy in RPS is better than all others, and an adaptive opponent can quickly learn to exploit any pure strategy (e.g., by always playing “paper” against someone who always plays “rock”). Any decent player will play RPS with something like a “mixed strategy” (selecting from the pure strategies at random, maybe with different probabilities). Game theory tells us that finite, two-player, zero-sum games always have optimal mixed strategies — i.e., a mixed strategy that’s as good or better than any other, even against an adaptive opponent. You might do better by exploiting a weak opponent, but you can’t do better against a perfect one. In plain RPS, the statistically unbeatable strategy is to play each hand with equal probability (\frac{1}{3}).
+
+Glico is made up of multiple rounds of weighted RPS. A truly optimal player won’t just use one set of probabilities (p_{r}), (p_{p}) and (p_{s}) for playing “rock”, “paper” and “scissors” each round. The optimal probabilities will vary depending the position of both players on the stairs. For example, a player who is four steps from winning is either happy with any winning hand, or only wants “rock”, depending on the rules, and (theoretically) both players should recognise that and adapt their probabilities accordingly. However, it’s more practical to play with an optimal greedy strategy — i.e., assuming everyone is just trying to get the maximum step value each round.
+
+I’ll calculate an optimal greedy strategy for weighted RPS in two ways. One way is longer but uses nothing but high school algebra and logical thinking, while the other way uses the power of linear programming.
+
+#### The longer way
+
+The greedy version of Glico has no end goal; the players are just trying to win points. It helps with solving the game if we make it zero sum — any time you win (N) points, your opponent loses (N) points, and vice versa. That just scales and shifts the score per round, so it doesn’t change the optimal strategy. Why do it? We know that optimal players can’t get any advantage over each other because the game is symmetric. If the game is zero sum, that means that no strategy can have an expected value of more than 0 points. That lets us write some equations. For example, playing “rock” might win you 4 points against “scissors”, or lose you 5 against “paper”. Against an optimal opponent, we can say
+
+[4p_{s} - 5p_{p} \leq 0]
+
+Is the inequality necessary? When would a pure strategy have a negative value against a non-adaptive but optimal player? Imagine if we added a fourth pure strategy, “bomb”, that simply gave 1000 points to the opponent. Obviously no optimal player would ever play “bomb”, so (p_{b} = 0). Playing “bomb” against an optimal player would have expected value -1000. We can say that some pure strategies are just _bad_: they have suboptimal value against an optimal opponent, and an optimal player will never play them. Other pure strategies have optimal value against an optimal opponent, and they’re reasonable to include in an optimal strategy.
+
+Bad pure strategies aren’t always as obvious as “bomb”, but we can argue that none of the pure strategies in RPS are bad. “Rock” is the only way to beat “scissors”, and “paper” is the only way to beat “rock”, and “scissors” is the only way to beat “paper”. At least one must be in the optimal strategy, so we can expect them all to be. So let’s make that (\leq) into (=), and add the equations for playing “paper” and “scissors”, plus the fact that these are probabilities that add up to 1:
+
+[\begin{matrix} {4p_{s} - 5p_{p}} & {= 0} \ {5p_{r} - 8p_{s}} & {= 0} \ {8p_{p} - 4p_{r}} & {= 0} \ {p_{r} + p_{p} + p_{s}} & {= 1} \ \end{matrix}]
+
+That’s a system of linear equations that can be solved algorithmically using Gaussian elimination — either by hand or by using any good numerical algorithms software. I won’t go into the details, but here’s the solution:
+
+[\begin{matrix} p_{r} & {= 0.4706} \ p_{p} & {= 0.2353} \ p_{s} & {= 0.2941} \ \end{matrix}]
+
+Even though it’s worth the least, an optimal player will play “rock” almost half the time to counterattack “scissors”. The rest of the time is split between “paper” and “scissors”, with a slight bias towards “scissors”.
+
+#### The powerful way
+
+The previous solution needed special-case analysis: it exploited the symmetry of the game, and made some guesses about how good/bad the pure strategies are. What about games that are more complex, or maybe not even symmetric (say, because one player has a handicap)? There’s a more general solution using what’s called linear programming (which dates to when “programming” just meant “scheduling” or “planning”).
+
+By the way, linear programming (LP) has a funny place in computer science. There are some industries and academic circles where LP and generalisations like mixed integer programming are super hot. Then there are computer science textbooks that never even mention them, so there are industries where the whole topic is pretty much unheard of. It might be because it wasn’t even known for a long time if LP problems can be solved in polynomial time (they can), so LP doesn’t have the same theoretical elegance as, say, shortest path finding, even if it has a lot of practical use.
+
+Anyway, solving weighted RPS with LP is pretty straightforward. We just need to describe the game using a bunch of linear inequalities in multiple variables, and express strategic value as a linear function that can be optimised. That’s very similar to what was done before, but this time we won’t try to guess at the values of any strategies. We’ll just assume we’re choosing values (p_{r}), (p_{p}) and (p_{s}) to play against an opponent who scores an average (v) against us each round. The opponent is smart enough to choose a strategy that’s as least as good as any pure strategy, so we can say
+
+[\begin{matrix} {4p_{s} - 5p_{p}} & {\leq v} \ {5p_{r} - 8p_{s}} & {\leq v} \ {8p_{p} - 4p_{r}} & {\leq v} \ \end{matrix}]
+
+The opponent can only play some combination of “rock”, “paper” and “scissors”, so (v) can’t be strictly greater than all of them — at least one of the inequalities above must be tight. To model the gameplay fully, the only other constraints we need are the rules of probability:
+
+[\begin{matrix} {p_{r} + p_{p} + p_{s}} & {= 1} \ p_{r} & {\geq 0} \ p_{p} & {\geq 0} \ p_{s} & {\geq 0} \ \end{matrix}]
+
+Now we’ve modelled the problem, we just need to express what needs to be optimised. That’s actually dead simple: we just want to minimise (v), the average score the opponent can win from us. An LP solver can find a set of values for all variables that minimises (v) within the constraints, and we can read off the optimal strategy directly.
+
+I’ve tried a few tools, and the [Julia][1] library [JuMP][2] has my current favourite FOSS API for throwaway optimisation problems. Here’s some code:
+
+```
+# You might need Pkg.add("JuMP"); Pkg.add("GLPK")
+using JuMP
+using GLPK
+
+game = Model(GLPK.Optimizer)
+
+@variable(game, 0 <= pr <= 1)
+@variable(game, 0 <= pp <= 1)
+@variable(game, 0 <= ps <= 1)
+@variable(game, v)
+
+@constraint(game, ptotal, pr + pp + ps == 1)
+@constraint(game, rock, 4*ps - 5*pp <= v)
+@constraint(game, paper, 5*pr - 8*ps <= v)
+@constraint(game, scissors, 8*pp - 4*pr <= v)
+
+@objective(game, Min, v)
+
+println(game)
+optimize!(game)
+
+println("Opponent's value: ", value(v))
+println("Rock: ", value(pr))
+println("Paper: ", value(pp))
+println("Scissors: ", value(ps))
+```
+
+Here’s the output:
+
+```
+Min v
+Subject to
+ ptotal : pr + pp + ps = 1.0
+ rock : 4 ps - 5 pp - v ≤ 0.0
+ paper : 5 pr - 8 ps - v ≤ 0.0
+ scissors : 8 pp - 4 pr - v ≤ 0.0
+ pr ≥ 0.0
+ pp ≥ 0.0
+ ps ≥ 0.0
+ pr ≤ 1.0
+ pp ≤ 1.0
+ ps ≤ 1.0
+
+Opponent's value: 0.0
+Rock: 0.47058823529411764
+Paper: 0.23529411764705882
+Scissors: 0.29411764705882354
+```
+
+As argued in the previous solution, the best value the opponent can get against the optimal player is 0.
+
+### What does optimality mean?
+
+The optimal solution was calculated assuming an all-powerful opponent. It guarantees that even the best weighted RPS player can’t get an advantage over you, but it turns out you can’t get an advantage over a terrible player, either, if you insist on playing this “optimal” strategy. That’s because weighted RPS has no bad plays, in the sense that “bomb” is bad. _Any_ strategy played against the above “optimal” strategy will have expected value of 0, so it’s really a defensive, or “safe” strategy. To play truly optimally and win against a bad player, you’ll have to adapt your strategy. For example, if your opponent plays “scissors” too often and “paper” not enough, you should adapt by playing “rock” more often. Of course, your opponent might just be pretending to be weak, and could start taking advantage of your deviation from the safe strategy.
+
+Games don’t always work out like that. For example, in theory, you could derive an optimal safe strategy for more complex games like poker. Such a strategy would tend to win against normal humans because even the best normal humans make bad poker plays. On the other hand, a “shark” at the table might be able to win against the “fish” faster by exploiting their weaknesses more aggressively. If you’re thinking of using LP to directly calculate a strategy for Texas Hold’em, though, sorry, but you’ll hit a combinatorial explosion of pure strategies as you account for all the cases like “if I’m dealt AJ on the big blind and I call a four-blind raise from the button preflop and then the flop is a rainbow 3K9…”. Only heavily simplified toy poker games are solvable with the general approach.
+
+--------------------------------------------------------------------------------
+
+via: https://theartofmachinery.com/2020/05/21/glico_weighted_rock_paper_scissors.html
+
+作者:[Simon Arneaud][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://theartofmachinery.com
+[b]: https://github.com/lujun9972
+[1]: https://julialang.org/
+[2]: https://github.com/JuliaOpt/JuMP.jl
diff --git a/sources/tech/20200521 Use the internet from the command line with curl.md b/sources/tech/20200521 Use the internet from the command line with curl.md
new file mode 100644
index 0000000000..c580ea0879
--- /dev/null
+++ b/sources/tech/20200521 Use the internet from the command line with curl.md
@@ -0,0 +1,186 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Use the internet from the command line with curl)
+[#]: via: (https://opensource.com/article/20/5/curl-cheat-sheet)
+[#]: author: (Seth Kenlon https://opensource.com/users/seth)
+
+Use the internet from the command line with curl
+======
+Download our new curl cheat sheet. Curl is a fast and efficient way to
+pull the information you need from the internet without using a
+graphical interface.
+![Cheat Sheet cover image][1]
+
+Curl is commonly considered a non-interactive web browser. That means it's able to pull information from the internet and display it in your terminal or save it to a file. This is literally what web browsers, such as Firefox or Chromium, do except they _render_ the information by default, while curl downloads and displays raw information. In reality, the curl command does much more and has the ability to transfer data to or from a server using one of many supported protocols, including HTTP, FTP, SFTP, IMAP, POP3, LDAP, SMB, SMTP, and many more. It's a useful tool for the average terminal user, a vital convenience for the sysadmin, and a quality assurance tool for microservices and cloud developers.
+
+Curl is designed to work without user interaction, so unlike Firefox, you must think about your interaction with online data from start to finish. For instance, if you want to view a web page in Firefox, you launch a Firefox window. After Firefox is open, you type the website you want to visit into the URL field or a search engine. Then you navigate to the site and click on the page you want to see.
+
+The same concepts apply to curl, except you do it all at once: you launch curl at the same time you feed it the internet location you want and tell it whether you want to the data to be saved in your terminal or to a file. The complexity increases when you have to interact with a site that requires authentication or with an API, but once you learn the **curl** command syntax, it becomes second nature. To help you get the hang of it, we collected the pertinent syntax information in a handy [cheat sheet][2].
+
+### Download a file with curl
+
+You can download a file with the **curl** command by providing a link to a specific URL. If you provide a URL that defaults to **index.html**, then the index page is downloaded, and the file you downloaded is displayed on your terminal screen. You can pipe the output to less or tail or any other command:
+
+
+```
+$ curl "" | tail -n 4
+ <h1>Example Domain</h1>
+ <p>This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.</p>
+ <p><a href="[https://www.iana.org/domains/example"\>More][3] information...</a></p>
+</div></body></html>
+```
+
+Because some URLs contain special characters that your shell normally interprets, it's safest to surround your URL in quotation marks.
+
+Some files don't translate well to being displayed in a terminal. You can use the **\--remote-name** option to cause the file to be saved according to what it's called on the server:
+
+
+```
+$ curl --remote-name ""
+$ ls
+linux-distro.iso
+```
+
+Alternatively, you can use the **\--output** option to name your download whatever you want:
+
+
+```
+`curl "http://example.com/foo.html" --output bar.html`
+```
+
+### List contents of a remote directory with curl
+
+Because curl is non-interactive, it's difficult to browse a page for downloadable elements. Provided that the remote server you're connecting to allows it, you can use **curl** to list the contents of a directory:
+
+
+```
+`$ curl --list-only "https://example.com/foo/"`
+```
+
+### Continue a partial download
+
+If you're downloading a very large file, you might find that you have to interrupt the download. Curl is intelligent enough to determine where you left off and continue the download. That means the next time you're downloading a 4GB Linux distribution ISO and something goes wrong, you never have to go back to the start. The syntax for **\--continue-at** is a little unusual: if you know the byte count where your download was interrupted, you can provide it; otherwise, you can use a lone dash (**-**) to tell curl to detect it automatically:
+
+
+```
+`$ curl --remote-name --continue-at - "https://example.com/linux-distro.iso"`
+```
+
+### Download a sequence of files
+
+If you need to download several files—rather than just one big file—curl can help with that. Assuming you know the location and file-name pattern of the files you want to download, you can use curl's sequencing notation: the start and end point between a range of integers, in brackets. For the output filename, use **#1** to indicate the first variable:
+
+
+```
+`$ curl "https://example.com/file_[1-4].webp" --output "file_#1.webp"`
+```
+
+If you need to use another variable to represent another sequence, denote each variable in the order it appears in the command. For example, in this command, **#1** refers to the directories **images_000** through **images_009**, while **#2** refers to the files **file_1.webp** through **file_4.webp**:
+
+
+```
+$ curl "" \
+\--output "file_#1-#2.webp"
+```
+
+### Download all PNG files from a site
+
+You can do some rudimentary web scraping to find what you want to download, too, using only **curl** and **grep**. For instance, say you need to download all images associated with a web page you're archiving. First, download the page referencing the images. Pipe the page to grep with a search for the image type you're targeting (PNG in this example). Finally, create a **while** loop to construct a download URL and to save the files to your computer:
+
+
+```
+$ curl |\
+grep --only-matching 'src="[^"]*.[png]"' |\
+cut -d\" -f2 |\
+while read i; do \
+curl " -o "${i##*/}"; \
+done
+```
+
+This is just an example, but it demonstrates how flexible curl can be when combined with a Unix pipe and some clever, but basic, parsing.
+
+### Fetch HTML headers
+
+Protocols used for data exchange have a lot of metadata embedded in the packets that computers send to communicate. HTTP headers are components of the initial portion of data. It can be helpful to view these headers (especially the response code) when troubleshooting your connection to a site:
+
+
+```
+curl --head ""
+HTTP/2 200
+accept-ranges: bytes
+age: 485487
+cache-control: max-age=604800
+content-type: text/html; charset=UTF-8
+date: Sun, 26 Apr 2020 09:02:09 GMT
+etag: "3147526947"
+expires: Sun, 03 May 2020 09:02:09 GMT
+last-modified: Thu, 17 Oct 2019 07:18:26 GMT
+server: ECS (sjc/4E76)
+x-cache: HIT
+content-length: 1256
+```
+
+### Fail quickly
+
+A 200 response is the usual HTTP indicator of success, so it's what you usually expect when you contact a server. The famous 404 response indicates that a page can't be found, and 500 means there was a server error.
+
+To see what errors are happening during negotiation, add the **\--show-error** flag:
+
+
+```
+`$ curl --head --show-error "http://opensource.ga"`
+```
+
+These can be difficult for you to fix unless you have access to the server you're contacting, but curl generally tries its best to resolve the location you point it to. Sometimes when testing things over a network, seemingly endless retries just waste time, so you can force curl to exit upon failure quickly with the **\--fail-early** option:
+
+
+```
+`curl --fail-early "http://opensource.ga"`
+```
+
+### Redirect query as specified by a 3xx response
+
+The 300 series of responses, however, are more flexible. Specifically, the 301 response means that a URL has been moved permanently to a different location. It's a common way for a website admin to relocate content while leaving a "trail" so people visiting the old location can still find it. Curl doesn't follow a 301 redirect by default, but you can make it continue on to a 301 destination by using the **\--location** option:
+
+
+```
+$ curl "" | grep title
+<title>301 Moved Permanently</title>
+$ curl --location ""
+<title>Internet Assigned Numbers Authority</title>
+```
+
+### Expand a shortened URL
+
+The **\--location** option is useful when you want to look at shortened URLs before visiting them. Shortened URLs can be useful for social networks with character limits (of course, this may not be an issue if you use a [modern and open source social network][4]) or for print media in which users can't just copy and paste a long URL. However, they can also be a little dangerous because their destination is, by nature, concealed. By combining the **\--head** option to view just the HTTP headers and the **\--location** option to unravel the final destination of a URL, you can peek into a shortened URL without loading the full resource:
+
+
+```
+$ curl --head --location \
+""
+```
+
+### [Download our curl cheat sheet][2]
+
+Once you practice thinking about the process of exploring the web as a single command, curl becomes a fast and efficient way to pull the information you need from the internet without bothering with a graphical interface. To help you build it into your usual workflow, we've created a [curl cheat sheet][2] with common curl uses and syntax, including an overview of using it to query an API.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/curl-cheat-sheet
+
+作者:[Seth Kenlon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/seth
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coverimage_cheat_sheet.png?itok=lYkNKieP (Cheat Sheet cover image)
+[2]: https://opensource.com/downloads/curl-command-cheat-sheet
+[3]: https://www.iana.org/domains/example"\>More
+[4]: https://opensource.com/article/17/4/guide-to-mastodon
diff --git a/sources/tech/20200522 A beginner-s guide to web scraping with Python.md b/sources/tech/20200522 A beginner-s guide to web scraping with Python.md
new file mode 100644
index 0000000000..010744161b
--- /dev/null
+++ b/sources/tech/20200522 A beginner-s guide to web scraping with Python.md
@@ -0,0 +1,493 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (A beginner's guide to web scraping with Python)
+[#]: via: (https://opensource.com/article/20/5/web-scraping-python)
+[#]: author: (Julia Piaskowski https://opensource.com/users/julia-piaskowski)
+
+A beginner's guide to web scraping with Python
+======
+Get some hands-on experience with essential Python tools to scrape
+complete HTML sites.
+![HTML code][1]
+
+There are plenty of great books to help you learn Python, but who actually reads these A to Z? (Spoiler: not me).
+
+Many people find instructional books useful, but I do not typically learn by reading a book front to back. I learn by doing a project, struggling, figuring some things out, and then reading another book. So, throw away your book (for now), and let's learn some Python.
+
+What follows is a guide to my first scraping project in Python. It is very low on assumed knowledge in Python and HTML. This is intended to illustrate how to access web page content with Python library [requests][2] and parse the content using [BeatifulSoup4][3], as well as JSON and [pandas][4]. I will briefly introduce [Selenium][5], but I will not delve deeply into how to use that library—that topic deserves its own tutorial. Ultimately I hope to show you some tricks and tips to make web scraping less overwhelming.
+
+### Installing our dependencies
+
+All the resources from this guide are available at my [GitHub repo][6]. If you need help installing Python 3, check out the tutorials for [Linux][7], [Windows][8], and [Mac][9].
+
+
+```
+$ python3 -m venv
+$ source venv/bin/activate
+$ pip install requests bs4 pandas
+```
+
+If you like using JupyterLab, you can run all the code using this [notebook][10]. There are a lot of ways to [install JupyterLab][11], and this is one of them:
+
+
+```
+# from the same virtual environment as above, run:
+$ pip install jupyterlab
+```
+
+### Setting a goal for our web scraping project
+
+Now we have our dependencies installed, but what does it take to scrape a webpage?
+
+Let's take a step back and be sure to clarify our goal. Here is my list of requirements for a successful web scraping project.
+
+ * We are gathering information that is worth the effort it takes to build a working web scraper.
+ * We are downloading information that can be legally and ethically gathered by a web scraper.
+ * We have some knowledge of how to find the target information in HTML code.
+ * We have the right tools: in this case, it's the libraries **BeautifulSoup** and **requests**.
+ * We know (or are willing to learn) how to parse JSON objects.
+ * We have enough data skills to use **pandas**.
+
+
+
+A comment on HTML: While HTML is the beast that runs the Internet, what we mostly need to understand is how tags work. A tag is a collection of information sandwiched between angle-bracket enclosed labels. For example, here is a pretend tag, called "pro-tip":
+
+
+```
+<pro-tip> All you need to know about html is how tags work </pro-tip>
+```
+
+We can access the information in there ("All you need to know…") by calling its tag "pro-tip." How to find and access a tag will be addressed further in this tutorial. For more of a look at HTML basics, check out [this article][12].
+
+### What to look for in a web scraping project
+
+Some goals for gathering data are more suited for web scraping than others. My guidelines for what qualifies as a good project are as follows.
+
+There is no public API available for the data. It would be much easier to capture structured data through an API, and it would help clarify both the legality and ethics of gathering the data. There needs to be a sizable amount of structured data with a regular, repeatable format to justify this effort. Web scraping can be a pain. BeautifulSoup (bs4) makes this easier, but there is no avoiding the individual idiosyncrasies of websites that will require customization. Identical formatting of the data is not required, but it does make things easier. The more "edge cases" (departures from the norm) present, the more complicated the scraping will be.
+
+Disclaimer: I have zero legal training; the following is not intended to be formal legal advice.
+
+On the note of legality, accessing vast troves of information can be intoxicating, but just because it's possible doesn't mean it should be done.
+
+There is, thankfully, public information that can guide our morals and our web scrapers. Most websites have a [robots.txt][13] file associated with the site, indicating which scraping activities are permitted and which are not. It's largely there for interacting with search engines (the ultimate web scrapers). However, much of the information on websites is considered public information. As such, some consider the robots.txt file as a set of recommendations rather than a legally binding document. The robots.txt file does not address topics such as ethical gathering and usage of the data.
+
+Questions I ask myself before beginning a scraping project:
+
+ * Am I scraping copyrighted material?
+ * Will my scraping activity compromise individual privacy?
+ * Am I making a large number of requests that may overload or damage a server?
+ * Is it possible the scraping will expose intellectual property I do not own?
+ * Are there terms of service governing use of the website, and am I following those?
+ * Will my scraping activities diminish the value of the original data? (for example, do I plan to repackage the data as-is and perhaps siphon off website traffic from the original source)?
+
+
+
+When I scrape a site, I make sure I can answer "no" to all of those questions.
+
+For a deeper look at the legal concerns, see the 2018 publications [Legality and Ethics of Web Scraping by Krotov and Silva][14] and [Twenty Years of Web Scraping and the Computer Fraud and Abuse Act by Sellars][15].
+
+### Now it's time to scrape!
+
+After assessing the above, I came up with a project. My goal was to extract addresses for all Family Dollar stores in Idaho. These stores have an outsized presence in rural areas, so I wanted to understand how many there are in a rather rural state.
+
+The starting point is the [location page for Family Dollar][16].
+
+![Family Dollar Idaho locations page][17]
+
+To begin, let's load up our prerequisites in our Python virtual environment. The code from here is meant to be added to a Python file (_scraper.py_ if you're looking for a name) or be run in a cell in JupyterLab.
+
+
+```
+import requests # for making standard html requests
+from bs4 import BeautifulSoup # magical tool for parsing html data
+import json # for parsing data
+from pandas import DataFrame as df # premier library for data organization
+```
+
+Next, we request data from our target URL.
+
+
+```
+page = requests.get("")
+soup = BeautifulSoup(page.text, 'html.parser')
+```
+
+BeautifulSoup will take HTML or XML content and transform it into a complex tree of objects. Here are several common object types that we will use.
+
+ * **BeautifulSoup**—the parsed content
+ * **Tag**—a standard HTML tag, the main type of bs4 element you will encounter
+ * **NavigableString**—a string of text within a tag
+ * **Comment**—a special type of NavigableString
+
+
+
+There is more to consider when we look at **requests.get()** output. I've only used **page.text()** to translate the requested page into something readable, but there are other output types:
+
+ * **page.text()** for text (most common)
+ * **page.content()** for byte-by-byte output
+ * **page.json()** for JSON objects
+ * **page.raw()** for the raw socket response (no thank you)
+
+
+
+I have only worked on English-only sites using the Latin alphabet. The default encoding settings in **requests** have worked fine for that. However, there is a rich internet world beyond English-only sites. To ensure that **requests** correctly parses the content, you can set the encoding for the text:
+
+
+```
+page = requests.get(URL)
+page.encoding = 'ISO-885901'
+soup = BeautifulSoup(page.text, 'html.parser')
+```
+
+Taking a closer look at BeautifulSoup tags, we see:
+
+ * The bs4 element **tag** is capturing an HTML tag
+ * It has both a name and attributes that can be accessed like a dictionary: **tag['someAttribute']**
+ * If a tag has multiple attributes with the same name, only the first instance is accessed.
+ * A tag's children are accessed via **tag.contents**.
+ * All tag descendants can be accessed with **tag.contents**.
+ * You can always access the full contents as a string with: **re.compile("your_string")** instead of navigating the HTML tree.
+
+
+
+### Determine how to extract relevant content
+
+Warning: this process can be frustrating.
+
+Extraction during web scraping can be a daunting process filled with missteps. I think the best way to approach this is to start with one representative example and then scale up (this principle is true for any programming task). Viewing the page's HTML source code is essential. There are a number of ways to do this.
+
+You can view the entire source code of a page using Python in your terminal (not recommended). Run this code at your own risk:
+
+
+```
+print(soup.prettify())
+```
+
+While printing out the entire source code for a page might work for a toy example shown in some tutorials, most modern websites have a massive amount of content on any one of their pages. Even the 404 page is likely to be filled with code for headers, footers, and so on.
+
+It is usually easiest to browse the source code via **View Page Source** in your favorite browser (right-click, then select "view page source"). That is the most reliable way to find your target content (I will explain why in a moment).
+
+![Family Dollar page source code][18]
+
+
+
+In this instance, I need to find my target content—an address, city, state, and zip code—in this vast HTML ocean. Often, a simple search of the page source (**ctrl + F**) will yield the section where my target location is located. Once I can actually see an example of my target content (the address for at least one store), I look for an attribute or tag that sets this content apart from the rest.
+
+It would appear that first, I need to collect web addresses for different cities in Idaho with Family Dollar stores and visit those websites to get the address information. These web addresses all appear to be enclosed in a **href** tag. Great! I will try searching for that using the **find_all** command:
+
+
+```
+dollar_tree_list = soup.find_all('href')
+dollar_tree_list
+```
+
+Searching for **href** did not yield anything, darn. This might have failed because **href** is nested inside the class **itemlist**. For the next attempt, search on **item_list**. Because "class" is a reserved word in Python, **class_** is used instead. The bs4 function **soup.find_all()** turned out to be the Swiss army knife of bs4 functions.
+
+
+```
+dollar_tree_list = soup.find_all(class_ = 'itemlist')
+for i in dollar_tree_list[:2]:
+ print(i)
+```
+
+Anecdotally, I found that searching for a specific class was often a successful approach. We can learn more about the object by finding out its type and length.
+
+
+```
+type(dollar_tree_list)
+len(dollar_tree_list)
+```
+
+The content from this BeautifulSoup "ResultSet" can be extracted using **.contents**. This is also a good time to create a single representative example.
+
+
+```
+example = dollar_tree_list[2] # a representative example
+example_content = example.contents
+print(example_content)
+```
+
+Use **.attr** to find what attributes are present in the contents of this object. Note: **.contents** usually returns a list of exactly one item, so the first step is to index that item using the bracket notation.
+
+
+```
+example_content = example.contents[0]
+example_content.attrs
+```
+
+Now that I can see that **href** is an attribute, that can be extracted like a dictionary item:
+
+
+```
+example_href = example_content['href']
+print(example_href)
+```
+
+### Putting together our web scraper
+
+All that exploration has given us a path forward. Here's the cleaned-up version of the logic we figured out above.
+
+
+```
+city_hrefs = [] # initialise empty list
+
+for i in dollar_tree_list:
+ cont = i.contents[0]
+ href = cont['href']
+ city_hrefs.append(href)
+
+# check to be sure all went well
+for i in city_hrefs[:2]:
+ print(i)
+```
+
+The output is a list of URLs of Family Dollar stores in Idaho to scrape.
+
+That said, I still don't have address information! Now, each city URL needs to be scraped to get this information. So we restart the process, using a single, representative example.
+
+
+```
+page2 = requests.get(city_hrefs[2]) # again establish a representative example
+soup2 = BeautifulSoup(page2.text, 'html.parser')
+```
+
+![Family Dollar map and code][19]
+
+The address information is nested within **type= "application/ld+json"**. After doing a lot of geolocation scraping, I've come to recognize this as a common structure for storing address information. Fortunately, **soup.find_all()** also enables searching on **type**.
+
+
+```
+arco = soup2.find_all(type="application/ld+json")
+print(arco[1])
+```
+
+The address information is in the second list member! Finally!
+
+I extracted the contents (from the second list item) using **.contents** (this is a good default action after filtering the soup). Again, since the output of contents is a list of one, I indexed that list item:
+
+
+```
+arco_contents = arco[1].contents[0]
+arco_contents
+```
+
+Wow, looking good. The format presented here is consistent with the JSON format (also, the type did have "**json**" in its name). A JSON object can act like a dictionary with nested dictionaries inside. It's actually a nice format to work with once you become familiar with it (and it's certainly much easier to program than a long series of RegEx commands). Although this structurally looks like a JSON object, it is still a bs4 object and needs a formal programmatic conversion to JSON to be accessed as a JSON object:
+
+
+```
+arco_json = json.loads(arco_contents)
+
+[/code] [code]
+
+type(arco_json)
+print(arco_json)
+```
+
+In that content is a key called **address** that has the desired address information in the smaller nested dictionary. This can be retrieved thusly:
+
+
+```
+arco_address = arco_json['address']
+arco_address
+```
+
+Okay, we're serious this time. Now I can iterate over the list store URLs in Idaho:
+
+
+```
+locs_dict = [] # initialise empty list
+
+for link in city_hrefs:
+ locpage = requests.get(link) # request page info
+ locsoup = BeautifulSoup(locpage.text, 'html.parser')
+ # parse the page's content
+ locinfo = locsoup.find_all(type="application/ld+json")
+ # extract specific element
+ loccont = locinfo[1].contents[0]
+ # get contents from the bs4 element set
+ locjson = json.loads(loccont) # convert to json
+ locaddr = locjson['address'] # get address
+ locs_dict.append(locaddr) # add address to list
+```
+
+### Cleaning our web scraping results with pandas
+
+We have loads of data in a dictionary, but we have some additional crud that will make reusing our data more complex than it needs to be. To do some final data organization steps, we convert to a pandas data frame, drop the unneeded columns "**@type**" and "**country**"), and check the top five rows to ensure that everything looks alright.
+
+
+```
+locs_df = df.from_records(locs_dict)
+locs_df.drop(['@type', 'addressCountry'], axis = 1, inplace = True)
+locs_df.head(n = 5)
+```
+
+Make sure to save results!!
+
+
+```
+df.to_csv(locs_df, "family_dollar_ID_locations.csv", sep = ",", index = False)
+```
+
+We did it! There is a comma-separated list of all the Idaho Family Dollar stores. What a wild ride.
+
+### A few words on Selenium and data scraping
+
+[Selenium][5] is a common utility for automatic interaction with a webpage. To explain why it's essential to use at times, let's go through an example using Walgreens' website. **Inspect Element** provides the code for what is displayed in a browser:
+
+![Walgreens location page and code][20]
+
+
+
+While **View Page Source** provides the code for what **requests** will obtain:
+
+![Walgreens source code][21]
+
+When these two don't agree, there are plugins modifying the source code—so, it should be accessed after the page has loaded in a browser. **requests** cannot do that, but **Selenium** can.
+
+Selenium requires a web driver to retrieve the content. It actually opens a web browser, and this page content is collected. Selenium is powerful—it can interact with loaded content in many ways (read the documentation). After getting data with **Selenium**, continue to use **BeautifulSoup** as before:
+
+
+```
+url = "[https://www.walgreens.com/storelistings/storesbycity.jsp?requestType=locator\&state=ID][22]"
+driver = webdriver.Firefox(executable_path = 'mypath/geckodriver.exe')
+driver.get(url)
+soup_ID = BeautifulSoup(driver.page_source, 'html.parser')
+store_link_soup = soup_ID.find_all(class_ = 'col-xl-4 col-lg-4 col-md-4')
+```
+
+I didn't need Selenium in the case of Family Dollar, but I do keep it on hand for those times when rendered content differs from source code.
+
+### Wrapping up
+
+In conclusion, when using web scraping to accomplish a meaningful task:
+
+ * Be patient
+ * Consult the manuals (these are very helpful)
+
+
+
+If you are curious about the answer:
+
+![Family Dollar locations map][23]
+
+There are many many Family Dollar stores in America.
+
+The complete source code is:
+
+
+```
+import requests
+from bs4 import BeautifulSoup
+import json
+from pandas import DataFrame as df
+
+page = requests.get("")
+soup = BeautifulSoup(page.text, 'html.parser')
+
+# find all state links
+state_list = soup.find_all(class_ = 'itemlist')
+
+state_links = []
+
+for i in state_list:
+ cont = i.contents[0]
+ attr = cont.attrs
+ hrefs = attr['href']
+ state_links.append(hrefs)
+
+# find all city links
+city_links = []
+
+for link in state_links:
+ page = requests.get(link)
+ soup = BeautifulSoup(page.text, 'html.parser')
+ familydollar_list = soup.find_all(class_ = 'itemlist')
+ for store in familydollar_list:
+ cont = store.contents[0]
+ attr = cont.attrs
+ city_hrefs = attr['href']
+ city_links.append(city_hrefs)
+# to get individual store links
+store_links = []
+
+for link in city_links:
+ locpage = requests.get(link)
+ locsoup = BeautifulSoup(locpage.text, 'html.parser')
+ locinfo = locsoup.find_all(type="application/ld+json")
+ for i in locinfo:
+ loccont = i.contents[0]
+ locjson = json.loads(loccont)
+ try:
+ store_url = locjson['url']
+ store_links.append(store_url)
+ except:
+ pass
+
+# get address and geolocation information
+stores = []
+
+for store in store_links:
+ storepage = requests.get(store)
+ storesoup = BeautifulSoup(storepage.text, 'html.parser')
+ storeinfo = storesoup.find_all(type="application/ld+json")
+ for i in storeinfo:
+ storecont = i.contents[0]
+ storejson = json.loads(storecont)
+ try:
+ store_addr = storejson['address']
+ store_addr.update(storejson['geo'])
+ stores.append(store_addr)
+ except:
+ pass
+
+# final data parsing
+stores_df = df.from_records(stores)
+stores_df.drop(['@type', 'addressCountry'], axis = 1, inplace = True)
+stores_df['Store'] = "Family Dollar"
+
+df.to_csv(stores_df, "family_dollar_locations.csv", sep = ",", index = False)
+```
+
+\--
+_Author's note: This article is an adaptation of a [talk I gave at PyCascades][24] in Portland, Oregon on February 9, 2020._
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/web-scraping-python
+
+作者:[Julia Piaskowski][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/julia-piaskowski
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/bus_html_code.png?itok=VjUmGsnl (HTML code)
+[2]: https://requests.readthedocs.io/en/master/
+[3]: https://beautiful-soup-4.readthedocs.io/en/latest/
+[4]: https://pandas.pydata.org/
+[5]: https://www.selenium.dev/
+[6]: https://github.com/jpiaskowski/pycas2020_web_scraping
+[7]: https://opensource.com/article/20/4/install-python-linux
+[8]: https://opensource.com/article/19/8/how-install-python-windows
+[9]: https://opensource.com/article/19/5/python-3-default-mac
+[10]: https://github.com/jpiaskowski/pycas2020_web_scraping/blob/master/example/Familydollar_location_scrape-all-states.ipynb
+[11]: https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html
+[12]: https://opensource.com/article/20/4/build-websites
+[13]: https://www.contentkingapp.com/academy/robotstxt/
+[14]: https://www.researchgate.net/publication/324907302_Legality_and_Ethics_of_Web_Scraping
+[15]: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3221625
+[16]: https://locations.familydollar.com/id/
+[17]: https://opensource.com/sites/default/files/uploads/familydollar1.png (Family Dollar Idaho locations page)
+[18]: https://opensource.com/sites/default/files/uploads/familydollar2.png (Family Dollar page source code)
+[19]: https://opensource.com/sites/default/files/uploads/familydollar3.png (Family Dollar map and code)
+[20]: https://opensource.com/sites/default/files/uploads/walgreens1.png (Walgreens location page and code)
+[21]: https://opensource.com/sites/default/files/uploads/walgreens2.png (Walgreens source code)
+[22]: https://www.walgreens.com/storelistings/storesbycity.jsp?requestType=locator\&state=ID
+[23]: https://opensource.com/sites/default/files/uploads/family_dollar_locations.png (Family Dollar locations map)
+[24]: https://2020.pycascades.com/talks/adventures-in-babysitting-webscraping-for-python-and-html-novices/
diff --git a/sources/tech/20200522 Fast data modeling with JavaScript.md b/sources/tech/20200522 Fast data modeling with JavaScript.md
new file mode 100644
index 0000000000..9c565d6e90
--- /dev/null
+++ b/sources/tech/20200522 Fast data modeling with JavaScript.md
@@ -0,0 +1,452 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Fast data modeling with JavaScript)
+[#]: via: (https://opensource.com/article/20/5/data-modeling-javascript)
+[#]: author: (Szymon https://opensource.com/users/schodevio)
+
+Fast data modeling with JavaScript
+======
+This tutorial showcases a method to model data in just a few minutes.
+![Analytics: Charts and Graphs][1]
+
+As a backend developer at the [Railwaymen][2], a software house in Kraków, Poland, some of my tasks rely on models that manipulate and customize data retrieved from a database. When I wanted to improve my skills in frontend frameworks, I [chose Vue][3], and I thought it would be good to have a similar way to model data in a store. I started with some libraries that I found through [NPM][4], but they offered many more features than I needed.
+
+So I decided to build my own solution, and I was very surprised that the base took less than 15 lines of code and is very flexible. I implemented this solution in an open source application which I developed and called [Evally][5] - a web app that helps businesses keep track of their employees' performance reviews and professional development. It reminds managers or HR representatives about employees' upcoming evaluations and gathers all of the data needed to assess their performance in the fairest way.
+
+### Model and list
+
+The only things you need to do are to create a class and use the defaultsDeep function in the [Lodash][6] JavaScript library:
+
+
+```
+`_.defaultsDeep(object, [sources])`
+```
+
+Arguments:
+
+ * `object (Object)`: The destination object
+ * `[sources] (...Object)`: The source objects
+
+
+
+Returns:
+
+ * `(Object)`: Returns object
+
+
+
+This helper function: [Lodash Docs][7]
+
+> "Assigns recursively own and inherited enumerable string keyed properties of source objects to the destination object for all destination properties that resolve to undefined. Source objects are applied from left to right. Once a property is set, additional values of the same property are ignored."
+
+For example:
+
+
+```
+_.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } })
+ // => { 'a': { 'b': 2, 'c': 3 } }
+```
+
+That's all! To try it out, create a file called **base.js** and import the defaultsDeep function from the Lodash package:
+
+
+```
+ // base.js
+ import defaultsDeep from "lodash/defaultsDeep";
+```
+
+Next, create and export the Model class, where constructor will use the Lodash helper function to assign values to all passed attributes and initialize the attributes that were not received with default values:
+
+
+```
+ // base.js
+ // ...
+
+ export class Model {
+ constructor(attributes = {}) {
+ defaultsDeep(this, attributes, this.defaults);
+ }
+ }
+```
+
+Now, create your first real model, Employee, with attributes for firstName, lastName, position and hiredAt where "position" defines "Programmer" as the default value:
+
+
+```
+ // employee.js
+ import { Model } from "./base.js";
+
+ export class Employee extends Model {
+ get defaults() {
+ return {
+ firstName: "",
+ lastName: "",
+ position: "Programmer",
+ hiredAt: ""
+ };
+ }
+ }
+```
+
+Next, begin creating employees:
+
+
+```
+// app.js
+ import { Employee } from "./employee.js";
+
+ const programmer = new Employee({
+ firstName: "Will",
+ lastName: "Smith"
+ });
+
+ // => Employee {
+ // firstName: "Will",
+ // lastName: "Smith",
+ // position: "Programmer",
+ // hiredAt: "",
+ // constructor: Object
+ // }
+
+ const techLeader = new Employee({
+ firstName: "Charles",
+ lastName: "Bartowski",
+ position: "Tech Leader"
+ });
+
+ // => Employee {
+ // firstName: "Charles",
+ // lastName: "Bartowski",
+ // position: "Tech Leader",
+ // hiredAt: "",
+ // constructor: Object
+ // }
+```
+
+You have two employees, and the first one's position is assigned from the defaults. Here's how multiple employees can be defined:
+
+
+```
+ // base.js
+
+ // ...
+
+ export class List {
+ constructor(items = []) {
+ this.models = items.map(item => new this.model(item));
+ }
+ }
+
+[/code] [code]
+
+ // employee.js
+ import { Model, List } from "./base.js";
+
+ // …
+
+ export class EmployeesList extends List {
+ get model() {
+ return Employee;
+ }
+ }
+```
+
+The List class constructor maps an array of received items into an array of desired models. The only requirement is to provide a correct model class name:
+
+
+```
+ // app.js
+ import { Employee, EmployeesList } from "./employee.js";
+
+ // …
+
+ const employees = new EmployeesList([
+ {
+ firstName: "Will",
+ lastName: "Smith"
+ },
+ {
+ firstName: "Charles",
+ lastName: "Bartowski",
+ position: "Tech Leader"
+ }
+ ]);
+
+ // => EmployeesList {models: Array[2], constructor: Object}
+ // models: Array[2]
+ // 0: Employee
+ // firstName: "Will"
+ // lastName: "Smith"
+ // position: "Programmer"
+ // hiredAt: ""
+ // <constructor>: "Employee"
+ // 1: Employee
+ // firstName: "Charles"
+ // lastName: "Bartowski"
+ // position: "Tech Leader"
+ // hiredAt: ""
+ // <constructor>: "Employee"
+ // <constructor>: "EmployeesList"
+```
+
+### Ways to use this approach
+
+This simple solution allows you to keep your data structure in one place and avoid code repetition. The [DRY][8] principle rocks! You can also customize your models as needed, such as in the following examples.
+
+#### Custom getters
+
+Do you need one attribute to be dependent on the others? No problem; you can do this by improving your Employee model:
+
+
+```
+// employee.js
+ import { Model } from "./base.js";
+
+ export class Employee extends Model {
+ get defaults() {
+ return {
+ firstName: "",
+ lastName: "",
+ position: "Programmer",
+ hiredAt: ""
+ };
+ }
+
+ get fullName() {
+ return [this.firstName, this.lastName].join(' ')
+ }
+
+ }
+
+[/code] [code]
+
+// app.js
+ import { Employee, EmployeesList } from "./employee.js";
+
+ // …
+
+ console.log(techLeader.fullName);
+ // => Charles Bartowski
+```
+
+Now you don't have to repeat the code to do something as simple as displaying the employee's full name.
+
+#### Date formatting
+
+Model is a good place to define other formats for given attributes. The best examples are dates:
+
+
+```
+// employee.js
+ import { Model } from "./base.js";
+ import moment from 'moment';
+
+ export class Employee extends Model {
+ get defaults() {
+ return {
+ firstName: "",
+ lastName: "",
+ position: "Programmer",
+ hiredAt: ""
+ };
+ }
+
+ get formattedHiredDate() {
+ if (!this.hiredAt) return "---";
+
+ return moment(this.hiredAt).format('MMMM DD, YYYY');
+ }
+ }
+
+[/code] [code]
+
+// app.js
+ import { Employee, EmployeesList } from "./employee.js";
+
+ // …
+
+ techLeader.hiredAt = "2020-05-01";
+
+ console.log(techLeader.formattedHiredDate);
+ // => May 01, 2020
+```
+
+Another case related to dates (which I discovered developing the Evally app) is the ability to operate with different date formats. Here's an example that uses datepicker:
+
+ 1. All employees fetched from the database have the hiredAt date in the format:
+YEAR-MONTH-DAY, e.g., 2020-05-01
+ 2. You need to display the hiredAt date in a more friendly format:
+MONTH DAY, YEAR, e.g., May 01, 2020
+ 3. A datepicker uses the format:
+DAY-MONTH-YEAR, e.g., 01-05-2020
+
+
+
+Resolve this issue with:
+
+
+```
+// employee.js
+ import { Model } from "./base.js";
+ import moment from 'moment';
+
+ export class Employee extends Model {
+
+ // …
+
+ get formattedHiredDate() {
+ if (!this.hiredAt) return "---";
+
+ return moment(this.hiredAt).format('MMMM DD, YYYY');
+ }
+
+ get hiredDate() {
+ return (
+ this.hiredAt
+ ? moment(this.hiredAt).format('DD-MM-YYYY')
+ : ''
+ );
+ }
+
+ set hiredDate(date) {
+ const mDate = moment(date, 'DD-MM-YYYY');
+
+ this.hiredAt = (
+ mDate.isValid()
+ ? mDate.format('YYYY-MM-DD')
+ : ''
+ );
+ }
+ }
+```
+
+This adds getter and setter functions to handle datepicker's functionality.
+
+
+```
+ // Get date from server
+ techLeader.hiredAt = '2020-05-01';
+ console.log(techLeader.formattedHiredDate);
+ // => May 01, 2020
+
+ // Datepicker gets date
+ console.log(techLeader.hiredDate);
+ // => 01-05-2020
+
+ // Datepicker sets new date
+ techLeader.hiredDate = '15-06-2020';
+
+ // Display new date
+ console.log(techLeader.formattedHiredDate);
+ // => June 15, 2020
+```
+
+This makes it very simple to manage multiple date formats.
+
+#### Storage for model-related information
+
+Another use for a model class is storing general information related to the model, like paths for routing:
+
+
+```
+// employee.js
+ import { Model } from "./base.js";
+ import moment from 'moment';
+
+ export class Employee extends Model {
+
+ // …
+
+ static get routes() {
+ return {
+ employeesPath: '/api/v1/employees',
+ employeePath: id => `/api/v1/employees/${id}`
+ }
+ }
+
+ }
+
+[/code] [code]
+
+ // Path for POST requests
+ console.log(Employee.routes.employeesPath)
+
+ // Path for GET request
+ console.log(Employee.routes.employeePath(1))
+```
+
+### Customize the list of models
+
+Don't forget about the List class, which you can customize as needed:
+
+
+```
+// employee.js
+ import { Model, List } from "./base.js";
+
+ // …
+
+ export class EmployeesList extends List {
+ get model() {
+ return Employee;
+ }
+
+ findByFirstName(val) {
+ return this.models.find(item => item.firstName === val);
+ }
+
+ filterByPosition(val) {
+ return this.models.filter(item => item.position === val);
+ }
+ }
+
+[/code] [code]
+
+ console.log(employees.findByFirstName('Will'))
+ // => Employee {
+ // firstName: "Will",
+ // lastName: "Smith",
+ // position: "Programmer",
+ // hiredAt: "",
+ // constructor: Object
+ // }
+
+ console.log(employees.filterByPosition('Tech Leader'))
+ // => [Employee]
+ // 0: Employee
+ // firstName: "Charles"
+ // lastName: "Bartowski"
+ // position: "Tech Leader"
+ // hiredAt: ""
+ // <constructor>: "Employee"
+```
+
+### Summary
+
+This simple structure for data modeling in JavaScript should save you some development time. You can add new functions whenever you need them to keep your code cleaner and easier to maintain. All of this code is available in my [CodeSandbox][9], so try it out and let me know how it goes by leaving a comment below.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/data-modeling-javascript
+
+作者:[Szymon][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/schodevio
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/analytics-graphs-charts.png?itok=sersoqbV (Analytics: Charts and Graphs)
+[2]: https://railwaymen.org/
+[3]: https://blog.railwaymen.org/vue-vs-react-which-one-is-better-for-your-app-similarities-differences
+[4]: https://www.npmjs.com/
+[5]: https://github.com/railwaymen/evally
+[6]: https://lodash.com/
+[7]: https://lodash.com/docs/4.17.15
+[8]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
+[9]: https://codesandbox.io/s/02jsdatamodels-1mhtb
diff --git a/sources/tech/20200524 Diamond interface composition in Go 1.14.md b/sources/tech/20200524 Diamond interface composition in Go 1.14.md
new file mode 100644
index 0000000000..611bb2c39e
--- /dev/null
+++ b/sources/tech/20200524 Diamond interface composition in Go 1.14.md
@@ -0,0 +1,124 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Diamond interface composition in Go 1.14)
+[#]: via: (https://dave.cheney.net/2020/05/24/diamond-interface-composition-in-go-1-14)
+[#]: author: (Dave Cheney https://dave.cheney.net/author/davecheney)
+
+Diamond interface composition in Go 1.14
+======
+
+Per the [overlapping interfaces proposal][1], Go 1.14 now permits embedding of interfaces with overlapping method sets. This is a brief post explain what this change means:
+
+Let’s start with the definition of the three key interfaces from the `io` package; `io.Reader`, `io.Writer`, and `io.Closer`:
+
+```
+package io
+
+type Reader interface {
+ Read([]byte) (int, error)
+}
+
+type Writer interface {
+ Write([]byte) (int, error)
+}
+
+type Closer interface {
+ Close() error
+}
+```
+
+Just as embedding a type inside a struct allows the embedded type’s fields and methods to be accessed as if it were declared on the embedding type[1][2], the process is true for interfaces. Thus there is no difference between explicitly declaring
+
+```
+type ReadCloser interface {
+ Read([]byte) (int, error)
+ Close() error
+}
+```
+
+and using embedding to compose the interface
+
+```
+type ReadCloser interface {
+ Reader
+ Closer
+}
+```
+
+You can even mix and match
+
+```
+type WriteCloser interface {
+ Write([]byte) (int, error)
+ Closer
+}
+```
+
+However, prior to Go 1.14, if you continued to compose interface declarations in this manner you would likely find that something like this,
+
+```
+type ReadWriteCloser interface {
+ ReadCloser
+ WriterCloser
+}
+```
+
+would fail to compile
+
+```
+% go build interfaces.go
+command-line-arguments
+./interfaces.go:27:2: duplicate method Close
+```
+
+Fortunately, with Go 1.14 this is no longer a limitation, thus solving problems that typically occur with diamond-shaped embedding graphs.
+
+However, there is a catch that I ran into attempting to demonstrate this feature to the local user group–this feature is only enabled when the Go compiler uses the 1.14 (or later) spec.
+
+As near as I can make out the rules for which version of the Go spec is used during compilation appear to be:
+
+ 1. If your source code is stored inside `GOPATH` (or you have _disabled_ modules with `GO111MODULE=off`) then the version of the Go spec used to compile with matches the version of the compiler you are using. Said another way, if you have Go 1.13 installed, your Go version is 1.13. If you have Go 1.14 installed, your version is 1.14. No surprises here.
+ 2. If your source code is stored outside `GOPATH` (or you have forced modules on with `GO111MODULE=on`) then the `go` tool will take the Go version from the `go.mod` file.
+ 3. If there is no Go version listed in `go.mod` then the version of the spec will be the version of Go installed. This is identical to point 1.
+ 4. If you are in module mode, either by being outside `GOPATH` or with `GO111MODULE=on`, but there is no `go.mod` file in the current, or any parent, directory then the version of the Go spec used to compile your code defaults to Go 1.13.
+
+
+
+The last point caught me out.
+
+ 1. It is said that embedding promotes the type’s fields and methods.[][3]
+
+
+
+### Related posts:
+
+ 1. [Struct composition with Go][4]
+ 2. [term: low level serial with a high level interface][5]
+ 3. [Accidental method value][6]
+ 4. [How does the go build command work ?][7]
+
+
+
+--------------------------------------------------------------------------------
+
+via: https://dave.cheney.net/2020/05/24/diamond-interface-composition-in-go-1-14
+
+作者:[Dave Cheney][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://dave.cheney.net/author/davecheney
+[b]: https://github.com/lujun9972
+[1]: https://github.com/golang/proposal/blob/master/design/6977-overlapping-interfaces.md
+[2]: tmp.nUQHg5BP9T#easy-footnote-bottom-1-4179 (It is said that embedding promotes the type’s fields and methods.)
+[3]: tmp.nUQHg5BP9T#easy-footnote-1-4179
+[4]: https://dave.cheney.net/2015/05/22/struct-composition-with-go (Struct composition with Go)
+[5]: https://dave.cheney.net/2014/05/08/term-low-level-serial-with-a-high-level-interface (term: low level serial with a high level interface)
+[6]: https://dave.cheney.net/2014/05/19/accidental-method-value (Accidental method value)
+[7]: https://dave.cheney.net/2013/10/15/how-does-the-go-build-command-work (How does the go build command work ?)
diff --git a/sources/tech/20200525 CopyQ Clipboard Manager for Keeping a Track of Clipboard History.md b/sources/tech/20200525 CopyQ Clipboard Manager for Keeping a Track of Clipboard History.md
new file mode 100644
index 0000000000..616ee5971a
--- /dev/null
+++ b/sources/tech/20200525 CopyQ Clipboard Manager for Keeping a Track of Clipboard History.md
@@ -0,0 +1,113 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (CopyQ Clipboard Manager for Keeping a Track of Clipboard History)
+[#]: via: (https://itsfoss.com/copyq-clipboard-manager/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+CopyQ Clipboard Manager for Keeping a Track of Clipboard History
+======
+
+How do you copy-paste text? Let me guess. You either use the right click menu to copy-paste or use Ctrl+C to copy a text and Ctrl+V to paste the text. The text copied this way is saved to ‘clipboard’. The [clipboard][1] is a special location in the memory of your system that stores cut or copied text (and in some cases images).
+
+But have you ever been in a situation where you had a text copied and then you copy another text and then realize you needed the text you copied earlier? Trust me, it happens a lot.
+
+Instead of wondering about finding the previous text to copy again, you can use a clipboard manager.
+
+A clipboard manager is a handy little tool that keeps a history of the text you had copied. If you need to use the earlier copied text, you can use the clipboard manager to copy it again.
+
+![Clipboard][2]
+
+There are several clipboard managers available for Linux. In this article, I’ll cover one such tool that goes by the name CopyQ.
+
+### CopyQ Clipboard Manager
+
+[CopyQ][3] is nifty clipboard manager that has plenty of features to manage your system’s clipboard. It is an open source software available for free for major Linux distributions.
+
+Like any other clipboard manager, CopyQ monitors the system clipboard and saves its content. It can save both text and images from the clipboard.
+
+CopyQ sits in the system tray and you can easily access it from there. From the system tray, just click on the text that you want. It will automatically copy this text and you would notice that the copied text moves on to the top of the saved clipboards.
+
+![][4]
+
+In the system tray, it shows only the five recent clips. You can open the main window using the “Show/hide main window” option in the system tray. CopyQ saves up to 200 clips. You may edit the clipboard items here.
+
+![][5]
+
+You may also set a keyboard shortcut to bring the clipboard with a few key combination. This option is available in Preferences->Shortcuts.
+
+![][6]
+
+If you decide to use it, I advise enabling the autostart so that CopyQ runs automatically when you start your system. By default, it saves 200 items in the history and that’s a lot in my opinion. You may want to change that as well.
+
+![][7]
+
+CopyQ is an advanced clipboard manager with plenty of additional features. You can search for text in the saved clipboard items. You can sort, create, edit or change the order of the clipboard items.
+
+You can ignore clipboard copied from some windows or containing some text. You can also temporarily disable clipboard saving. CopyQ also supports [Vim][8]-like editor and shortcut for Vim fans.
+
+There are many more features that you may explore on your own. For me, the most notable feature is that it gives me easy access to older copied text, and I am happy with that.
+
+### Installing CopyQ on Linux
+
+CopyQ is available for Linux, Windows and macOS. You can get the executable file for Windows and macOS [from its website][3].
+
+For Linux, CopyQ is available in the repositories of all major Linux distributions. Which means that you can find it in your software center or install it using your distribution’s package manager.
+
+Ubuntu users may find it in the software center if [universe repository is enabled][9].
+
+![CopyQ in Ubuntu Software Center][10]
+
+Alternatively, you can use the apt command to install it:
+
+```
+sudo apt install copyq
+```
+
+Ubuntu users also have the option to [use the official PPA][11] and always get the latest stable CopyQ version. For example, at the time of writing this article, CopyQ version in Ubuntu 20.04 is 3.10 while [PPA has newer version][12] 3.11. It’s your choice really.
+
+```
+sudo add-apt-repository ppa:hluk/copyq
+sudo apt update
+sudo apt install copyq
+```
+
+You may also want to know [how to remove PPA][13] later.
+
+### Do you use a clipboard manager?
+
+I find it surprising that many people are not even aware of an essential utility like clipboard manager. For me, it’s one of the [essential productivity tools on Linux][14].
+
+As I mentioned at the beginning of the article, there are several clipboard managers available for Linux. CopyQ is one of such tools. Do you use or know of some other similar clipboard tool? Why not let us know in the comments?
+
+If you started using CopyQ after reading this article, do share your experience with it. What you liked and what you didn’t like? The comment section is all yours.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/copyq-clipboard-manager/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://www.computerhope.com/jargon/c/clipboar.htm
+[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/clipboard.png?ssl=1
+[3]: https://hluk.github.io/CopyQ/
+[4]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/copyq-system-tray.png?ssl=1
+[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/copyq-main-window.png?ssl=1
+[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/copyq-shortcuts.png?ssl=1
+[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/copyq-auto-start.png?ssl=1
+[8]: https://itsfoss.com/vim-8-release-install/
+[9]: https://itsfoss.com/ubuntu-repositories/
+[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/copyq-software-center.png?resize=800%2C474&ssl=1
+[11]: https://itsfoss.com/ppa-guide/
+[12]: https://launchpad.net/~hluk/+archive/ubuntu/copyq
+[13]: https://itsfoss.com/how-to-remove-or-delete-ppas-quick-tip/
+[14]: https://itsfoss.com/productivity-tips-ubuntu/
diff --git a/sources/tech/20200525 Debian-s Decision to Drop Old Drivers has Upset Vintage Hardware Users.md b/sources/tech/20200525 Debian-s Decision to Drop Old Drivers has Upset Vintage Hardware Users.md
new file mode 100644
index 0000000000..fb2b9005ea
--- /dev/null
+++ b/sources/tech/20200525 Debian-s Decision to Drop Old Drivers has Upset Vintage Hardware Users.md
@@ -0,0 +1,85 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Debian’s Decision to Drop Old Drivers has Upset Vintage Hardware Users)
+[#]: via: (https://itsfoss.com/debian-dropping-old-drivers/)
+[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
+
+Debian’s Decision to Drop Old Drivers has Upset Vintage Hardware Users
+======
+
+It is always a tough decision to drop support for older hardware for the latest Linux distribution releases. Just like [Ubuntu decided to drop support for 32-bit systems][1], Debian’s X Strike Force (XFS) team decided to drop a list of input and video drivers.
+
+### Debian is considering to drop support for really old hardware
+
+![][2]
+
+In case you didn’t know, the XFS team is responsible for maintaining packages the [X Window System][3] in [Debian][4]. And, the list of drivers that [they want to remove][5] are:
+
+ * xserver-xorg-input-aiptek
+ * xserver-xorg-input-elographics
+ * xserver-xorg-input-mtrack
+ * xserver-xorg-input-mutouch
+ * xserver-xorg-input-void
+ * server-xorg-video-ast
+ * xserver-xorg-video-mach64
+
+
+ * xserver-xorg-video-neomagic
+ * xserver-xorg-video-r128
+ * xserver-xorg-video-savage
+ * xserver-xorg-video-siliconmotion
+ * xserver-xorg-video-sisusb
+ * xserver-xorg-video-tdfx
+ * xserver-xorg-video-trident
+
+
+
+So, Mach 64, [ATI Rage R128][6], Savage, Silicon Motion, SiS, Trident, and NeoMagic are some of the graphics chipsets that would be affected. The reason (as stated by them) to drop these drivers is:
+
+> They are either unmaintained upstream or provide no value to the distribution.
+
+Now, that could make sense, if the packages are no longer maintained. But, upstream some of these X.org drivers are still **maintained** even if there are no frequent updates to them. For instance, in 2018, a [new display driver update was released for the ATI RAGE 128][7], as reported by Phoronix.
+
+### Vintage hardware owners are going to be upset
+
+Obviously, the vintage hardware users aren’t quite happy with the decision because a handful of people still own (or actively use) old hardware i.e. around 20 years older.
+
+From the original list of drivers mentioned in the [bug report][5], **Geode display driver** was initially decided to be removed but wasn’t dropped.
+
+It was also reported that the “**xserver-xorg-video-r128**” driver is required for older Apple hardware (iMac). And, a user reported about the missing video driver on his iMac.
+
+For most of the users, this decision may not actually affect any “production” systems because I don’t think anyone is probably going to utilize 20-year old hardware for commercial purposes.
+
+The hobbyists and collectors who like to preserve older tech are surely going to be impacted by this decision.
+
+### Wrapping Up
+
+In my opinion, dropping the support for incredibly dated hardware is not entirely a bad move.
+
+But, if there is a demand for the support of vintage hardware, the fair share of users who want the drivers to be added in Debian should help maintain those packages. If not, I don’t think it won’t be a wise choice to have an unmaintained piece of code in Debian.
+
+What do you think about this? Feel free to share your thoughts in the comments below!
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/debian-dropping-old-drivers/
+
+作者:[Ankush Das][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/ankush/
+[b]: https://github.com/lujun9972
+[1]: https://itsfoss.com/ubuntu-drops-32-bit-desktop/
+[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/debian-bug-report-driver-drop.jpg?ssl=1
+[3]: https://en.wikipedia.org/wiki/X_Window_System
+[4]: https://www.debian.org/
+[5]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=955603
+[6]: https://en.wikipedia.org/wiki/ATI_Rage_series
+[7]: https://www.phoronix.com/scan.php?page=news_item&px=ATI-RAGE-128-DDX-6.11.0
diff --git a/sources/tech/20200525 EU Parliament Strongly Recommends Developing and Using Open Source Software.md b/sources/tech/20200525 EU Parliament Strongly Recommends Developing and Using Open Source Software.md
new file mode 100644
index 0000000000..bfeb5635ce
--- /dev/null
+++ b/sources/tech/20200525 EU Parliament Strongly Recommends Developing and Using Open Source Software.md
@@ -0,0 +1,84 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (EU Parliament Strongly Recommends Developing and Using Open Source Software)
+[#]: via: (https://itsfoss.com/eu-parliament-recommends-open-source/)
+[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
+
+EU Parliament Strongly Recommends Developing and Using Open Source Software
+======
+
+Europe is choosing open source more than ever. Not just limited to [EU Commissions’ decision to use Signal messaging app][1] but also [open science][2] and the [adoption of open source software by European universities][3].
+
+Now, in a recent [press release][4] by the [European Pirate Party][5], it looks like the EU Parliament is urging EU institutions to use open-source software. All thanks to the Pirate amendments for encouraging the use of open-source software.
+
+The EU Parliament not just encourages the use of open-source software, but they have also advised to prioritize development of open-source software by the EU institutions.
+
+So, not just aiming to adopt using open-source software but to develop open-source software. And, that’s definitely good news!
+
+More use of open-source software, why not? To give you some more details, here’s what they mentioned in the press release:
+
+> **In practice, from now on, all IT solutions developed by and for the EU institutions will first need to be assessed against the possibility of using Open Source solutions. Assessments will then have to be reported back to the Budgetary Control Committee of the Parliament on an annual basis, during the discharge procedure. This is a strong call for enhancing our important citizens right to transparent and trustworthy information.**
+
+### Important decision to remove vendor lock-ins
+
+![Public Money Public Code Campaign][6]
+
+No matter who made this happen — this decision of preferring open-source software over proprietary will not just help the open-source community but also helps the EU institutions in a variety of ways.
+
+Especially, relying on open-source software removes the overhead of vendor lock-ins. In other words, an EU institution does not have to rely on vendor to manage/maintain the software.
+
+The press release also addressed this by mentioning:
+
+> It is essential for the European institutions to retain control over its own technical systems, especially in a context of disinformation and foreign interference. Open Source promotes local technical support, leads to rapid development of software and helps to avoid dependency on specific suppliers or vendor lock-in effects, which exist when only one company is in charge of software or even the entire IT infrastructure supply.
+
+Any responsible local organization can take up the task while the community can still help in any way it can. This could also reduce the cost of maintaining the software among other things like improving the security of a software in a collaborative manner.
+
+### Is this a big win for open-source community?
+
+![][7]
+
+Yes, and no. We’ve seen a lot of recommendations made by the governments (or the EU government in general) to choose open-source software to keep things more secure yet transparent.
+
+Pirate’s Vice-President of EU Parliament, **Marcel Kolaja**, mentions some advantages of this decision as well:
+
+_It’s a milestone for transparent and open digitization of the European institutions. From now on, the Open Source ecosystem has a stepping ground for offering Open Source solutions and the Pirates will gladly play the role of the guardians and will try to solve and highlight any attempt to bypass this strong recommendation. It’s a really important step to remove vendor lock-ins in the Parliament“_
+
+So, this will definitely help them earn trust of their citizens by providing digital transparency while also encouraging public participation to improve the software as well. Of course, this will also help introduce the concept of open-source software to many who were unaware of it in some way.
+
+Also, ensuring open-source software for publicly financed software will enhance the meaning of freedom of speech/privacy/press.
+
+In a nutshell, these decisions do have a positive impact in one way or the other.
+
+But, the implementations of these decisions will decide how effective it’s going to be to put the words in action.
+
+### Wrapping Up
+
+I’m happy with the decision by EU Parliament here — even though I’m not a European. I guess, this should encourage other government bodies to take similar decisions or steps to ensure digital transparency while earning the trust of their citizens.
+
+To get more details on the decision, you can refer to the [official press release by the European Pirate Party][4].
+
+What do you think about it? Let me know your thoughts in the comments below!
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/eu-parliament-recommends-open-source/
+
+作者:[Ankush Das][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/ankush/
+[b]: https://github.com/lujun9972
+[1]: https://itsfoss.com/eu-commission-switches-to-signal/
+[2]: https://ec.europa.eu/research/openscience/index.cfm?pg=openaccess
+[3]: https://opensource.com/article/20/5/open-source-higher-education
+[4]: https://european-pirateparty.eu/european-parliament-strongly-recommends-any-software-developed-by-and-for-the-eu-institutions-to-be-made-publicly-available-under-free-and-open-source-software-licence/
+[5]: https://en.wikipedia.org/wiki/European_Pirate_Party
+[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/public-money-public-code.png?resize=800%2C420&ssl=1
+[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/eu-parliament-open-source.jpg?ssl=1
diff --git a/sources/tech/20200525 Encrypt Your Files Before Uploading it to Cloud With Cryptomator.md b/sources/tech/20200525 Encrypt Your Files Before Uploading it to Cloud With Cryptomator.md
new file mode 100644
index 0000000000..eda3a2990e
--- /dev/null
+++ b/sources/tech/20200525 Encrypt Your Files Before Uploading it to Cloud With Cryptomator.md
@@ -0,0 +1,184 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Encrypt Your Files Before Uploading it to Cloud With Cryptomator)
+[#]: via: (https://itsfoss.com/cryptomator/)
+[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
+
+Encrypt Your Files Before Uploading it to Cloud With Cryptomator
+======
+
+_**Open source software highlight of this week is Cryptomator. It is a unique free and open-source encryption software that lets you encrypt your data before uploading it to the cloud.**_
+
+There are several [cloud services available for Linux][1] and almost all of them do not offer [end to end encryption][2], at least not by default.
+
+Usually, the connection between your device and the server is secure. But your data stored on the server is not encrypted. Employees with direct access to the infrastructure at your cloud service providers may access this data.
+
+Of course, these companies have strict policies against such intrusion but a rogue employee can do a lot of damage. Remember the incident when a [departing Twitter employee deactivated the account of US President Donald Trump][3].
+
+If you are one of the privacy cautious people, you would want the ease of cloud storage but with the added security layer of encrypted storage.
+
+Now some [services like pCloud do provide end to end encryption][4] but that comes at an additional cost. If you could afford that, well and good. If not, you can use a free and open source tool like [Cryptomator][5].
+
+Cryptomator helps you secure your data by encrypting it before uploading it to any cloud storage services. In this article, I’m going to highlight the key features of Cryptomator along with instructions to use it.
+
+### Cryptomator: Add an encryption layer to your cloud data
+
+![][6]
+
+Cryptomator is a solution to encrypt your data locally before uploading it to the cloud.
+
+With this, you can create vaults locally and sync them to the cloud storage services you use.
+
+It’s very easy to use and you don’t need to have any specific technical knowledge to encrypt your data – that’s what Cryptomator is tailored for.
+
+### Features of Cryptomator
+
+Cryptomator is a simple encryption tool with the essential features. Here’s what it offers:
+
+ * [AES][7] and 256-bit Encryption for files.
+ * Ability to create a vault and sync it with the cloud storage service
+ * Optional recovery key for your master password of the vault
+ * Cross-platform support (Linux, Windows, macOS, Android, and iOS)
+ * Supports the dark theme for a one-time license fee.
+ * Supports [WebDAV][8], [FUSE][9], and [Dokany][10] for easy integration with your operating system.
+
+
+
+Do note that the [Android][11] and [iOS][12] apps are paid apps that you have to purchase separately while the desktop program is completely free to use. Also, you need to purchase a one-time license to unlock the dark mode. Don’t blame them please. They need to make some money in order to develop this open source software.
+
+### Installing Cryptomator on Linux
+
+Cryptomater provides an AppImage file that you can download to get started on any Linux distribution.
+
+You can get it from its [official download page][13]. In case you don’t know, please read [how to use an AppImage file][14] to get started.
+
+[Download Cryptomator][5]
+
+### How To Use Cryptomator?
+
+Attention!
+
+Encryption is a double-edged sword. It can protect you and it can hurt you as well.
+If you are encrypting your data and you forgot your encryption key, you’ll lose access to that data forever.
+Cryptomator provides a recovery key option so please be careful with both password and the recovery key. Don’t forget it or lose the recovery key.
+
+Once you have installed Cryptomator, it’s really easy to use it following the user interface or the [official documentation][15].
+
+But, to save you some time, I’ll highlight a few important things that you should know:
+
+#### Setup Your Vault
+
+![][16]
+
+After launching Cryptomator, you need to create the vault where you want to have your encrypted data.
+
+This can be an existing location or a new custom directory as per your requirements.
+
+Now that you proceed creating a new vault, you will also observe that you can open an existing vault as well (if you had one already). So, always have a backup of your vault, just in case.
+
+![][17]
+
+Here, I am assuming that you are a new user. So, obviously, proceed to create a new vault and give it a name:
+
+![][18]
+
+Next, you need to specify a storage location. If you already use OneDrive, Dropbox, Google Drive, or something similar, it might detect it automatically.
+
+![][19]
+
+However, if it doesn’t, like in my case (I use [pCloud][20]), you can select the cloud-synced directory or any other custom location manually.
+
+Once you select the location, you just need to create a password for it. It’s best to create a strong password that you can remember.
+
+![][21]
+
+Also, I’d suggest you to opt for the recovery key and store it in a separate USB drive or just print it on a paper.
+
+![][22]
+
+And, that’s it. You’re done creating your secure vault that you can sync with the cloud.
+
+![][23]
+
+Now, how do you add files to it? Let’s take a look:
+
+#### Adding Files To A Vault
+
+_**Note:** You can’t just go into the folder that you created from the file manager and files there. Follow the steps below to add files properly in your encrypted vault._
+
+Once you’ve created your vault, you just need to unlock it by typing the password as shown in the image below. If you’re on your personal computer, you can choose to save the password without needing to enter it every time you access the vault. However, I advise not to do that. Manually entering the password help in remembering it.
+
+![][24]
+
+Next, after unlocking the vault, you just need to click on “**Reveal Vault**” or reveal drive to open it using **File Manager** where you can access/modify or add files to it.
+
+#### Backup / Recover Your Vault
+
+You should simply copy-paste the folder you create to another USB drive or somewhere else other than your cloud storage folder to ensure that you have a backup of your vault.
+
+![][25]
+
+It’s important to have the **masterkey.cryptomator** file of the vault in order to open it.
+
+#### Upgrades, Preferences & Settings
+
+Note
+
+You should enable the auto-updates feature to ensure that you will have the most stable and error-free version automatically.
+
+Apart from the most important functions of the Cryptomator app, you will get a couple of other features to tweak, such as:
+
+ * Change the type of your virtual drive
+ * Tweak the vault to read-only mode
+
+
+
+You can explore the **Vault options** and the settings on Cryptomator to know about what else you can do.
+
+**Wrapping Up**
+
+Now that you know about Cryptomator, you can easily encrypt your important data locally before uploading them to the cloud.
+
+What do you think about Cryptomator? Let us know your thoughts in the comments down below!
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/cryptomator/
+
+作者:[Ankush Das][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/ankush/
+[b]: https://github.com/lujun9972
+[1]: https://itsfoss.com/cloud-services-linux/
+[2]: https://en.wikipedia.org/wiki/End-to-end_encryption
+[3]: https://www.theverge.com/2017/11/2/16600732/donald-trump-twitter-account-gone-realdonaldtrump
+[4]: https://partner.pcloud.com/r/22317
+[5]: https://cryptomator.org/
+[6]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-ft.jpg?ssl=1
+[7]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+[8]: https://en.wikipedia.org/wiki/WebDAV
+[9]: https://en.wikipedia.org/wiki/Filesystem_in_Userspace
+[10]: https://en.wikipedia.org/wiki/Dokan_Library
+[11]: https://play.google.com/store/apps/details?id=org.cryptomator&hl=en_US
+[12]: https://apps.apple.com/us/app/cryptomator/id953086535
+[13]: https://cryptomator.org/downloads/
+[14]: https://itsfoss.com/use-appimage-linux/
+[15]: https://docs.cryptomator.org
+[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-add-vault.jpg?ssl=1
+[17]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-create-open-vault.jpg?ssl=1
+[18]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-add-vault-name.jpg?ssl=1
+[19]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-vault-location.jpg?ssl=1
+[20]: https://itsfoss.com/recommends/pcloud/
+[21]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-pass.jpg?ssl=1
+[22]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-recovery.jpg?ssl=1
+[23]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-vault-success.jpg?ssl=1
+[24]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-unlock.jpg?ssl=1
+[25]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/cryptomator-master.jpg?ssl=1
diff --git a/sources/tech/20200525 How to Assign Static IP Address on Ubuntu Linux.md b/sources/tech/20200525 How to Assign Static IP Address on Ubuntu Linux.md
new file mode 100644
index 0000000000..87ddb6b839
--- /dev/null
+++ b/sources/tech/20200525 How to Assign Static IP Address on Ubuntu Linux.md
@@ -0,0 +1,179 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to Assign Static IP Address on Ubuntu Linux)
+[#]: via: (https://itsfoss.com/static-ip-ubuntu/)
+[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
+
+How to Assign Static IP Address on Ubuntu Linux
+======
+
+_**Brief: In this tutorial, you’ll learn how to assign static IP address on Ubuntu and other Linux distributions. Both command line and GUI methods have been discussed.**_
+
+IP addresses on Linux Systems in most cases are assigned by [Dynamic Host Configuration Protocol][1] (DHCP) servers. IP addresses assigned this way are dynamic which means that the IP address might change when you [restart your Ubuntu system][2]. It’s not necessary but it may happen.
+
+_**Dynamic IP is not an issue for normal desktop Linux users in most cases**_. It could become an issue if you have employed some special kind of networking between your computers.
+
+For example, you can [share your keyboard and mouse between Ubuntu and Raspberry Pi][3]. The configuration uses IP addresses of both system. If the IP address changes dynamically, then your setup won’t work.
+
+Another use case is with servers or remotely administered desktops. It is easier to set static addresses on those systems for connection stability and consistency between the users and applications.
+
+In this tutorial, I’ll show you how to set up static IP address on Ubuntu based Linux distributions. Let me show you the command line way first and then I’ll show the graphical way of doing it on desktop.
+
+### Method 1: Assign static IP in Ubuntu using command line
+
+![][4]
+
+**Note for desktop users**: Use static IP only when you need it. Automatic IP saves you a lot of headache in handling network configuration.
+
+#### Step 1: Get the name of network interface and the default gateway
+
+The first thing you need to know is the name of the network interface for which you have to set up the static IP.
+
+You can either use ip command or the network manager CLI like this:
+
+```
+nmcli d
+```
+
+In my case, it shows my Ethernet (wired) network is called enp0s25:
+
+```
+Ubuntu> nmcli d
+DEVICE TYPE STATE CONNECTION
+enp0s25 ethernet unmanaged --
+lo loopback unmanaged --
+```
+
+Next, you should note the [default gateway IP using the Linux command][5] **ip route**:
+
+```
+ip route
+default via 192.168.31.1 dev enp0s25 proto dhcp metric 600
+169.254.0.0/16 dev enp0s25 scope link metric 1000
+192.168.31.0/24 dev enp0s25 proto kernel scope link src 192.168.31.36 metric 600
+```
+
+As you can guess, the default gateway is 192.168.31.1 for me.
+
+#### Step 2: Locate Netplan configuration
+
+Ubuntu 18.04 LTS and later versions use [Netplan][6] for managing the network configuration. Netplan configuration are driven by .yaml files located in **/etc/netplan** directory.
+
+By default, you should see a .yaml file named something like 01-network-manager-all.yaml, 50-cloud-init.yaml, 01-netcfg.yaml.
+
+Whatever maybe the name, its content should look like this:
+
+```
+# Let NetworkManager manage all devices on this system
+network:
+ version: 2
+ renderer: NetworkManager
+```
+
+You need to edit this file for using static IP.
+
+#### Step 3: Edit Netplan configuration for assigning static IP
+
+_**Just for the sake of it, make a backup of your yaml file.**_
+
+Please make sure to use the correct yaml file name in the commands from here onward.
+
+Use nano editor with sudo to open the yaml file like this:
+
+```
+sudo nano /etc/netplan/01-netcfg.yaml
+```
+
+Please note that _**yaml files use spaces for indentation**_. If you use tab or incorrect indention, your changes won’t be saved.
+
+You should edit the file and make it look like this by providing the actual details of your IP address, gateway, interface name etc.
+
+```
+network:
+ version: 2
+ renderer: networkd
+ ethernets:
+ enp0s25:
+ dhcp4: no
+ addresses:
+ - 192.168.31.16/24
+ gateway4: 192.168.31.1
+ nameservers:
+ addresses: [8.8.8.8, 1.1.1.1]
+```
+
+In the above file, I have set the static IP to 192.168.31.16.
+
+Save the file and apply the changes with this command:
+
+```
+sudo netplan apply
+```
+
+You can verify it by [displaying your ip address in the terminal][7] with ‘ip a’ command.
+
+Revert the changes and go back to dynamic IP
+
+If you don’t want to use the static IP address anymore, you can revert easily.
+
+If you have backed up the original yaml file, you can delete the new one and use the backup one.
+
+Otherwise, you can change the yaml file again and make it look like this:
+
+```
+network:
+ version: 2
+ renderer: networkd
+ ethernets:
+ enp0s25:
+ dhcp4: yes
+```
+
+### Method 2: Switch to static IP address in Ubuntu graphically
+
+If you are on desktop, using the graphical method is easier and faster.
+
+Go to the settings and look for network settings. Click the gear symbol adjacent to your network connection.
+
+![][8]
+
+Next, you should go to the IPv4 tab. Under the IPv4 Method section, click on Manual.
+
+In the Addresses section, enter the IP static IP address you want, netmask is usually 24 and you already know your gateway IP with the ip route command.
+
+You may also change the DNS server if you want. You can keep Routes section to Automatic.
+
+![][9]
+
+Once everything is done, click on Apply button. See, how easy it is to set a static IP address graphically.
+
+If you haven’t read my previous article on [how to change MAC Address][10], you may want to read in conjunction with this one.
+
+More networking related articles will be rolling out, let me know your thoughts at the comments below and stay connected to our social media.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/static-ip-ubuntu/
+
+作者:[Dimitrios Savvopoulos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/dimitrios/
+[b]: https://github.com/lujun9972
+[1]: https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol
+[2]: https://itsfoss.com/schedule-shutdown-ubuntu/
+[3]: https://itsfoss.com/keyboard-mouse-sharing-between-computers/
+[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/static-ip-ubuntu.jpg?ssl=1
+[5]: https://linuxhandbook.com/find-gateway-linux/
+[6]: https://netplan.io/
+[7]: https://itsfoss.com/check-ip-address-ubuntu/
+[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/assign-static-ip-1.jpg?ssl=1
+[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/assign-static-ip-2.jpg?ssl=1
+[10]: https://itsfoss.com/change-mac-address-linux/
diff --git a/sources/tech/20200525 How to Compress PDF in Linux -GUI - Terminal.md b/sources/tech/20200525 How to Compress PDF in Linux -GUI - Terminal.md
new file mode 100644
index 0000000000..eba596bcb9
--- /dev/null
+++ b/sources/tech/20200525 How to Compress PDF in Linux -GUI - Terminal.md
@@ -0,0 +1,99 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to Compress PDF in Linux [GUI & Terminal])
+[#]: via: (https://itsfoss.com/compress-pdf-linux/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+How to Compress PDF in Linux [GUI & Terminal]
+======
+
+_**Brief: Learn how to reduce the size of a PDF file in Linux. Both command line and GUI methods have been discussed.**_
+
+I was filling some application form and it asked to upload the necessary documents in PDF format. Not a big issue. I gathered all the [scanned images and combined them in one PDF using gscan2pdf tool][1].
+
+The problem came when I tried to upload this PDF file. The upload failed because it exceeded the maximum file size limit. This only meant that I needed to somehow reduce the size of the PDF file.
+
+Now, you may use an online PDF compressing website but I don’t trust them. A file with important documents uploading to an unknown server is not a good idea. You could never be sure that they don’t keep a copy your uploaded PDF document.
+
+This is the reason why I prefer compressing PDF files on my system rather than uploading it to some random server.
+
+In this quick tutorial, I’ll show you how to reduce the size of PDF files in Linux. I’ll show both command line and GUI methods.
+
+### Method 1: Reduce PDF file size in Linux command line
+
+![][2]
+
+You can use [Ghostscript][3] command line tool for compressing a PDF file. Most Linux distributions include the open source version of Ghostscript already. However, you can still try to install it just to make sure.
+
+On Debian/Ubuntu based distributions, use the following command to install Ghostscript:
+
+```
+sudo apt install ghostscript
+```
+
+Now that you have made sure that Ghostscript is installed, you can use the following command to reduce the size of your PDF file:
+
+```
+gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed_PDF_file.pdf input_PDF_file.pdf
+```
+
+In the above command, you should add the correct path of the input and out PDF file.
+
+The command looks scary and confusing. I advise copying and pasting most of it. What you need to know is the dPDFSETTINGS parameter. This is what determines the compression level and thus the quality of your compressed PDF file.
+
+dPDFSETTINGS | Description
+---|---
+/prepress (default) | Higher quality output (300 dpi) but bigger size
+/ebook | Medium quality output (150 dpi) with moderate output file size
+/screen | Lower quality output (72 dpi) but smallest possible output file size
+
+Do keep in mind that some PDF files may not be compressed a lot or at all. Applying compression on some PDF files may even produce a file bigger than the original. There is not much you can do in such cases.
+
+### Method 2: Compress PDF files in Linux using GUI tool
+
+I understand that not everyone is comfortable with command line tool. The [PDF editors in Linux][4] doesn’t help much with compression. This is why we at It’s FOSS worked on creating a GUI version of the Ghostscript command that you saw above.
+
+[Panos][5] from It’s FOSS team [worked on creating a Python-Qt based GUI wrapper for the Ghostscript][6]. The tool gives you a simple UI where you can select your input file, select a compression level and click on the compress button to compress the PDF file.
+
+![][7]
+
+The compressed PDF file is saved in the same folder as the original PDF file. Your original PDF file remains untouched. The compressed file is renamed by appending -compressed to the original file name.
+
+If you are not satisfied with the compression, you can choose another compression level and compress the file again.
+
+You may find the source code of the PDF Compressor on our GitHub repository. To let you easily use the tool, we have packaged it in AppImage format. Please [refer to this guide to know how to use AppImage][8].
+
+[Download PDF Compressor (AppImage)][9]
+
+Please keep in mind that the tool is in early stages of developments. You may experience some issues. If you do, please let us know in the comments or even better, [file a bug here][10].
+
+We’ll try to add more packages (Snap, Deb, PPAs etc) in the future releases. If you have experience with the development and packaging, please feel free to give us a hand.
+
+Would you like It’s FOSS team to work on creating more such small desktop tools in future? Your feedback and suggestions are welcome.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/compress-pdf-linux/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://itsfoss.com/convert-multiple-images-pdf-ubuntu-1304/
+[2]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/compress-pdf-linux.jpg?ssl=1
+[3]: https://www.ghostscript.com/
+[4]: https://itsfoss.com/pdf-editors-linux/
+[5]: https://github.com/libreazer
+[6]: https://github.com/itsfoss/compress-pdf
+[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/compress-PDF.jpg?fit=800%2C448&ssl=1
+[8]: https://itsfoss.com/use-appimage-linux/
+[9]: https://github.com/itsfoss/compress-pdf/releases/download/0.1/compress-pdf-v0.1-x86_64.AppImage
+[10]: https://github.com/itsfoss/compress-pdf/issues
diff --git a/sources/tech/20200525 How to Install Linux Mint in VirtualBox -Screenshot Tutorial.md b/sources/tech/20200525 How to Install Linux Mint in VirtualBox -Screenshot Tutorial.md
new file mode 100644
index 0000000000..1fc324e817
--- /dev/null
+++ b/sources/tech/20200525 How to Install Linux Mint in VirtualBox -Screenshot Tutorial.md
@@ -0,0 +1,194 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (How to Install Linux Mint in VirtualBox [Screenshot Tutorial])
+[#]: via: (https://itsfoss.com/install-linux-mint-in-virtualbox/)
+[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
+
+How to Install Linux Mint in VirtualBox [Screenshot Tutorial]
+======
+
+_**Brief: One of safest and easiest ways to try Linux Mint is inside a virtual machine. Your real system doesn’t change at all. Learn how to install Linux Mint in VirtualBox in this tutorial.**_
+
+[Linux Mint][1] is considered one of the [best distributions for new Linux users][2]. Its flagship Cinnamon DE is one of the most popular desktop environment giving your system a look and feel of classic Window-styled desktop.
+
+If you want to try Linux Mint and see if it fits your need, you could try installing it in a virtual machine. This way, you run Linux Mint inside your current system without changing your system’s partition or boot order. One of the safest way out there as you get to run Linux like a regular desktop application inside your current operating system.
+
+![][3]
+
+Oracle’s open source virtualization tool [VirtualBox][4] is available for free on all major desktop operating systems i.e. Windows, Linux and macOS.
+
+In this beginner’s tutorial, I’ll show you the steps for installing Linux Mint in VirtualBox. I am including the screenshots for each step so that you can easily follow the tutorial.
+
+### Installing Linux Mint in VirtualBox
+
+You can follow the steps on any operating system be it Windows, Linux or macOS. You just need to install VirtualBox on your operating system and rest of the steps remain the same.
+
+**Step 1:** [Download VirtualBox from its website][4] and install it by double-clicking on the downloaded file.
+
+![][5]
+
+Next, install the latest version of Linux Mint’s ISO file from its website.
+
+[Download Linux Mint ISO][6]
+
+**Step 2:** Once your virtual Box is up & running we are ready to get started. Click the New button, click Next on the virtual machine wizard.
+
+![Create a new Virtual Machine][7]
+
+Initially you need to specify the following:
+
+ * Name: Any preferred name for your VM like Linux Mint
+ * Type: Linux
+ * Version: Ubuntu (64 bit) as Linux Mint is an Ubuntu-based distribution
+
+
+
+Before configuring any hardware resource value, please make sure that are aware of the [system requirements][8].
+
+2 GB RAM would be okay but won’t give you a good experience. 3 GB is a comfortable amount if your system has 8 GB of RAM. I choose to set my Virtual Machine to 4096 MB (4 GB) because my system has plenty of RAM.
+
+RAM consumption
+
+One of the common confusion is regarding the RAM consumption. Let’s say your Windows system has 8 GB of RAM and you assign 3 GB of RAM to Linux Mint in VirtualBox.
+
+If you are running Linux Mint inside VirtualBox, your real system (called host system) will have 5 GB of RAM available for consumption.
+
+If you are not running Linux Mint inside VirtualBox, at that moment, the entire 8 GB will be available to the host system.
+
+**Step 3:** Next, choose a Virtual Hard disk now option and click create.
+
+Choose the virtual storage allocation method (Recommended Dynamically allocated). Set your storage location for virtual hard disk by browsing drive and then specify the size of virtual hard disk (it could be anything from 12-20 GB).
+
+![Dynamic allocation can save you space if you don’t need the maximum allowance][9]
+
+**Step (4 (optional advanced settings):** Once Virtual machine has been created, click on the settings button in menu:
+
+![][10]
+
+Now, go to the Display section. Specify the Video memory (128 MB) and check “Enable 3D Acceleration”.
+
+![Don’t forget to enable the 3D Acceleration][11]
+
+Then click on System Tab → Processor and choose how many threads would you like to allocate.
+
+My system is a 4 core/4 thread system and I choose to assign half of the CPU capability i.e. 2 threads.
+
+![Select CPU cores as per the distribution requirements][12]
+
+Once you have configured everything click ok.
+
+**Step 5:** In the System settings, go to Storage (from the left sidebar). Click on the [Optical Drive] Empty as shown in the image below.
+
+You’ll be asked to browse to the Linux Mint ISO file you had downloaded earlier.
+
+![][13]
+
+Once you select your ISO, click on the start button and that’s it! Now the ISO will start running as if you are booting from a live USB.
+
+Next, you need to press enter whilst your option is start Linux Mint as per the picture below.
+
+![][14]
+
+**Step 6:** Let’s start the installation procedure.
+
+Choose the language you want for your Linux Mint virtual machine.
+
+![Choose your native language][15]
+
+I’m based in the UK, so I have a UK keyboard layout. You can choose the one you want.
+
+![Choose your keyboard layout according to your hardware configuration][16]
+
+You may check the box to download and install any third-party software during the installation.
+
+![You may install media codecs while installing Linux Mint][17]
+
+You can proceed to erase the disk and install Linux Mint.
+
+Erase disk? Really?
+
+This step may seem scary because you may think that it will harm your real system.
+
+Let me assure you that it won’t do any damage to your actual disk. Remember you created 10-20 GB of virtual disk in step 3? Now you are inside that disk.
+
+When it asks for erasing the disk, it is erasing the virtual disk created for it. It doesn’t impact your real system disk and its data.
+
+![It is safe to erase your disk only at a Virtual Machine level][18]
+
+Next, select your time zone and click continue. You may [change time zone in Linux][19] later as well.
+
+![][20]
+
+You will be prompted to create your user account, your host name (computer’s name) and to choose a password. Once done, click continue to finalize the installation.
+
+![][21]
+
+Please wait a few minutes for the process to complete.
+
+![Wait a few minutes for the process to finish][22]
+
+The installation has now finished. Click on “Restart now”.
+
+![Well done! You have successfully installed Linux Mint][23]
+
+When you reach this step, Linux Mint will be installed and ready to use!
+
+![][24]
+
+You don’t have an installation medium so just power off the virtual machine.
+
+![][25]
+
+Now to use your virtual machine, click on the start button.
+
+![][26]
+
+You can explore a fully functional system, and at this time if you shut down Linux Mint like it was physically installed, it will automatically power off the virtual machine.
+
+![][27]
+
+Enjoy Linux Mint in VirtualBox. I hope you were able to install Linux Mint in VirtualBox. If you face any issues, please let me know in the comment section. I’ll try to help you out.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/install-linux-mint-in-virtualbox/
+
+作者:[Dimitrios Savvopoulos][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/dimitrios/
+[b]: https://github.com/lujun9972
+[1]: https://www.linuxmint.com/
+[2]: https://itsfoss.com/best-linux-beginners/
+[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/install-linux-mint-in-virtualbox.png?ssl=1
+[4]: https://www.virtualbox.org/
+[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/download-virtulabox.jpg?ssl=1
+[6]: https://www.linuxmint.com/download.php
+[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/1.-Create-new.jpg?ssl=1
+[8]: https://blog.linuxmint.com/?p=3832
+[9]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/2.-Create-virtual-hard-disk.jpg?resize=800%2C472&ssl=1
+[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/3.-settings.jpg?resize=800%2C470&ssl=1
+[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/4.-display.jpg?resize=800%2C472&ssl=1
+[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/5.-cpu.jpg?resize=800%2C468&ssl=1
+[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/6.-choose-iso.jpg?resize=800%2C472&ssl=1
+[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/7.-boot.jpg?resize=800%2C459&ssl=1
+[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/8.-choose-language.png?resize=800%2C679&ssl=1
+[16]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/9.-English-UK.png?resize=800%2C679&ssl=1
+[17]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/10.-install-third-party-software.png?resize=800%2C679&ssl=1
+[18]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/11.-installation-type.png?resize=800%2C679&ssl=1
+[19]: https://itsfoss.com/change-timezone-ubuntu/
+[20]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/12.-timezone.png?resize=800%2C679&ssl=1
+[21]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/13.-user-account.png?resize=800%2C679&ssl=1
+[22]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/04/14.-installation-screen.png?resize=800%2C679&ssl=1
+[23]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/15.-installation-finish.png?resize=800%2C679&ssl=1
+[24]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/16.-remove-the-media.png?resize=800%2C679&ssl=1
+[25]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/17.-power-off.png?resize=800%2C678&ssl=1
+[26]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/18.-init-the-fresh-installed-mint.png?resize=800%2C476&ssl=1
+[27]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/04/19.-Linux-mint-19.3-final.png?resize=800%2C469&ssl=1
diff --git a/sources/tech/20200525 LanguageTool Review- Free and Open Source Grammar Checker.md b/sources/tech/20200525 LanguageTool Review- Free and Open Source Grammar Checker.md
new file mode 100644
index 0000000000..afd1a08e49
--- /dev/null
+++ b/sources/tech/20200525 LanguageTool Review- Free and Open Source Grammar Checker.md
@@ -0,0 +1,155 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (LanguageTool Review: Free and Open Source Grammar Checker)
+[#]: via: (https://itsfoss.com/languagetool-review/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+LanguageTool Review: Free and Open Source Grammar Checker
+======
+
+This week’s open source software highlight is [LanguageTool][1]. It is a proofreading software that checks the grammar, style and spelling in more than 20 languages.
+
+I have been using it for past several days and I feel confident enough to review it and share my experience with it. I have used the popular proofreading tool [Grammarly][2] in the past and I’ll make some comparison between these two tools.
+
+### LanguageTool: Open source proofreading software
+
+![][3]
+
+[LanguageTool][1] grammar checker is available in [multiple formats][4]:
+
+ * You can copy-paste your text on its website.
+ * You can install browser extension that will check for errors as you type anything, anywhere in the web browser.
+ * You can install a Java-based desktop application for offline usage.
+ * You can install add-on for LibreOffice and MS Office.
+ * Add-ons are also [available for a number of other software][5] like Sublime Text, Thunderbird, Vim, Visual Studio Code etc.
+ * [Android app][6] is also available.
+ * API is also available if you want to use LanguageTool in your software or service. API offering comes under premium services.
+
+
+
+You can find source code of LanguageTool and its related assets on [their GitHub repository][7].
+
+[LanguageTool also has a premium version][8] that you can purchase. The premium version offers additional error checks.
+
+I am using LanguageTool premium version as a browser extension. Almost all the writing I do is online and thus the browser extension is perfect for me.
+
+The most convenient way to try LanguageTool is by using its browser extension. Install the browser add-on and next time you type anything in the browser, LanguageTool will start checking your text for grammatical and spelling errors. It will also check for styling errors.
+
+### Experience with LanguageTool: How good is it?
+
+LanguageTool leaves a good first impression. It starts checking for errors as you start typing.
+
+Different types of errors have different color codes. Spelling mistakes are highlighted in red color, grammatical mistakes are in yellow colors and styling errors have a blueish shade.
+
+Clicking on the error suggestion replaces your text with the suggested one. You may also ignore the suggestion. You’ll also see number of issues identified by LanguageTool in the current text check.
+
+![Spelling mistake identified by LanguageTool][9]
+
+#### Personal dictionary
+
+You can also create your personal directory and add words in it. This is helpful because no proofreading tool can give a green light to technical terms like systemd, iptables and brand names like [WireGuard][10]. To avoid these words labeled as spelling mistakes, add them to your personal dictionary.
+
+You may edit your personal dictionary from your LanguageTool account.
+
+![LanguageTool Personal Dictionary][11]
+
+#### Details on the error suggestion
+
+If it finds grammatical errors, it also gives a quick explanation of the error. You can get more details by clicking the tool tip which takes you to a reputable external source.
+
+![You can get additional details on the errors][12]
+
+#### Synonym suggestion (in beta)
+
+If you double-click on a word, it will also suggest synonyms.
+
+![][13]
+
+#### Are there any privacy issues?
+
+If you use the online services of LanguageTool, your text is sent to their servers over an **encrypted** connection. All their servers are hosted at Hetzner Online GmbH in Germany.
+
+LanguageTool states that it doesn’t store any text that you check using its services. You can read their privacy policy [here][14].
+
+The free to use languagetool.org website shows ads (there are no third-party ads in the browser add-on). To test their claim of “sending text over an encrypted server”, I typed sample text containing words like vacuum cleaner, laptop etc.
+
+Thankfully, the displayed ad on their website was nothing related to the text I typed. I haven’t noticed any vacuum cleaner ads on the websites I visit or on Facebook. That’s a good thing.
+
+#### It doesn’t work flawlessly all the time
+
+No software is perfect and LanguageTool is not an exception. While it is helpful in finding obvious spelling and grammatical mistakes, it struggles in some simple scenario.
+
+For example, if a sentence contains several blank spaces together, LanguageTool failed to find an issue with that.
+
+![Too many whitespaces and yet it went undetected][15]
+
+This is weird because if I look at their ‘error rules’, I can see a [whitespace repetition rule][16]. I think this rule is applicable only for the Java-based LanguageTool apps, not the browser add-on I am using.
+
+I also found some other cases where LanguageTool should have identified errors but it didn’t. For example, it didn’t alert for the missing ‘to’ in the text below:
+
+![LanguageTool fails to find the missing “to”][17]
+
+When I checked it against the [Grammarly free version][2], it was able to point it out.
+
+![Grammarly was quick to identify it][18]
+
+I also found an infinite loop of suggestion. It first suggests using syntaxes as plural of syntax.
+
+![Suggestion for using ‘syntaxes’][19]
+
+And then it doesn’t accept ‘syntaxes’ as a valid word.
+
+![And then it doesn’t accept ‘syntaxes’][20]
+
+I have seen such “infinite error loop” with Grammarly as well in the past, so I won’t be too hard on LanguageTool for such issues.
+
+### Conclusion
+
+Despite some hiccups, I am satisfied with LanguageTool proofreading tool. Both free and premium version are good enough for finding obvious spelling mistakes and grammatical errors.
+
+The premium version offers over 2500 additional error checks and it costs around $15-$70 per year depending on your geographical region. This is a lot cheaper than [Grammarly][2] which costs $140 per year.
+
+I opted for the premium version because it will help this open-source project. Premium users also get email support.
+
+You are not forced to go premium, of course. You can use the free version and if you have some questions or need support, there is a [community forum][21] that you can join for free.
+
+LanguageTool can certainly be considered one of the [essential open-source tools for writers][22]. I am going to continue using LanguageTool. If you find grammatical or spelling mistakes in It’s FOSS articles in the future, blame LanguageTool, not me. Just kidding :)
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/languagetool-review/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://languagetool.org/
+[2]: https://itsfoss.com/recommends/grammarly/
+[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool.png?fit=800%2C593&ssl=1
+[4]: https://languagetool.org/compare
+[5]: http://wiki.languagetool.org/software-that-supports-languagetool-as-a-plug-in-or-add-on
+[6]: https://play.google.com/store/apps/details?id=org.softcatala.corrector
+[7]: https://github.com/languagetool-org/
+[8]: https://languagetoolplus.com/
+[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/langaugetool-error-detection.png?ssl=1
+[10]: https://itsfoss.com/wireguard/
+[11]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-personal-dictionary.png?ssl=1
+[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-error-explanation.png?ssl=1
+[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-synonym-suggestion.png?ssl=1
+[14]: https://languagetoolplus.com/legal/privacy
+[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-whitespaces.png?ssl=1
+[16]: https://community.languagetool.org/rule/show/WHITESPACE_RULE?lang=en
+[17]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-suggestion-3.jpg?fit=800%2C219&ssl=1
+[18]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-suggestion-grammarly.jpg?fit=800%2C272&ssl=1
+[19]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-suggestion.png?ssl=1
+[20]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/languagetool-suggestion-1.png?ssl=1
+[21]: https://forum.languagetool.org/
+[22]: https://itsfoss.com/open-source-tools-writers/
diff --git a/sources/tech/20200525 Using ‘apt search- and ‘apt show- Commands to Search and Find Details of Packages in Ubuntu.md b/sources/tech/20200525 Using ‘apt search- and ‘apt show- Commands to Search and Find Details of Packages in Ubuntu.md
new file mode 100644
index 0000000000..d1d80bcb5d
--- /dev/null
+++ b/sources/tech/20200525 Using ‘apt search- and ‘apt show- Commands to Search and Find Details of Packages in Ubuntu.md
@@ -0,0 +1,172 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Using ‘apt search’ and ‘apt show’ Commands to Search and Find Details of Packages in Ubuntu)
+[#]: via: (https://itsfoss.com/apt-search-command/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+Using ‘apt search’ and ‘apt show’ Commands to Search and Find Details of Packages in Ubuntu
+======
+
+_**This is a detailed beginners guide to apt search command. Using apt search and apt show commands, you can get details of the available versions, dependencies, repositories and other important information about packages in Ubuntu.**_
+
+Have you ever wondered if a certain package is available to install via [apt package manager][1]?
+
+Have you wondered if the package offered by [Ubuntu repositories][2] are the latest one or not?
+
+The apt package manager in [Ubuntu][3] and many other distribution provides two handy [apt command options][4] for this purpose.
+
+The apt search command looks for the provided string in the name and description of the packages.
+
+```
+apt search package_name
+```
+
+The apt show command provides detailed information on a package:
+
+```
+apt show package_name
+```
+
+The commands don’t require you to [be root in Ubuntu][5]. Here’s an example of these commands:
+
+![][6]
+
+### Why would you want to use apt search or apt show command?
+
+Let’s say you want to [install Gambas programming language in Ubuntu][7]. You are happy with your knowledge of the apt command so you decided to use the command line for installing application.
+
+You open a terminal and use the apt command to install gambas but it results in [unable to locate package error][8].
+
+```
+sudo apt install gambas
+Reading package lists... Done
+Building dependency tree
+Reading state information... Done
+E: Unable to locate package gambas
+```
+
+Why did Ubuntu not find the gambas package? Because there is no such package called gambas. Instead, it is available as gambas3. This is a situation where you could take the advantage of the apt search command.
+
+Let’s move to apt show command. This command provides detailed information about a package, its repository, dependencies and a lot more.
+
+Knowing what version of a package is available from the official repository could help you in deciding whether you should install it from some other sources.
+
+Quick recall
+
+The apt package manager works on a local database/cache of available packages from various repositories. This database contains the information about the available package version, dependencies etc. It doesn’t contain the entire package itself. The packages are downloaded from the remote repositories.
+
+When you run the sudo apt update command, this cache is created/updated in the /var/lib/apt/lists/ directory. The apt search and apt show commands utilize this cache.
+
+The term package is used for an application, program, software.
+
+### Search for available packages using apt search command
+
+![][9]
+
+Let me continue the gambas example. Say, you search for
+
+```
+apt search gambas
+```
+
+It will give you a huge list of packages that have “gambas” in its name or description. This output list is in alphabetical order.
+
+Now, you’ll of course have to make some intelligent prediction about the package you want. In this example, the first result says “Complete visual development environment for Gambas”. This gives you a good hint that this is the main package you are looking for.
+
+![][10]
+
+Why so many packages associated with gambas? Because a number of these gambas packages are probably dependencies that will installed automatically if you install the gambas3 package. If you use the _‘apt show gambas3_‘ command, it will show all the dependencies that will be installed with gambas3 package.
+
+Some of these listed packages could be libraries that a developer may need in some special cases while developing her/his software.
+
+#### Use apt search for package name only
+
+By default, apt search command looks for the searched term in both the name of the package and its description.
+
+You may narrow down the search by instructing the apt command to search for package names only.
+
+```
+apt search --names-only search_term
+```
+
+If you are following this as a tutorial, give it a try. Check the output with search term ‘transitional’ with and without –names-only option and you’ll see how the output changes.
+
+```
+apt search transitional
+apt search --names-only transitional
+```
+
+**Bonus Tip**: You can use ‘apt list –installed’ command to [look for installed packages in Ubuntu][11].
+
+### Get detailed information on a package using apt show command
+
+The output of the apt search commands a brief introduction of the packages. If you want more details, use the apt show command.
+
+```
+apt show exact_package_name
+```
+
+The apt show command works on the exact package name and it gives you a lot more information on the package. You get:
+
+ * Version information
+ * Repository information
+ * Origin and maintainer of the package information
+ * Where to file a bug
+ * Download and installation size
+ * Dependencies
+ * Detailed description of the package
+ * And a lot more
+
+
+
+Here’s an example:
+
+![][12]
+
+You need to give the exact package name otherwise the apt show won’t work. The good thing is that tab completion works apt show command.
+
+As you can see in the previous image, you have plenty of information that you may found helpful.
+
+The apt show command also works on installed packages. In that case, you can see which source the package was installed from. Was it a PPA or some third-party repository or universe or the main repository itself?
+
+Personally, I use apt show a lot. This helps me know if the package version provided by Ubuntu is the latest or not. Pretty handy tool!
+
+### Conclusion
+
+If you read my detailed [guide on the difference between apt and apt-get commands][13], you would know that this ‘apt search’ command works similar to ‘apt-cache search’. There is no such command as “apt-get search”.
+
+The purpose of creating apt command is to give you one tool with only enough option to manage the packages in your Debian/Ubuntu system. The apt-get, apt-cache and other apt tools still exist, and they can be used in scripting for more complex scenarios.
+
+I hope you found this introduction to **apt search** and **apt show** commands useful. I welcome your questions and suggestions on this topic.
+
+If you liked it, please share it on various Linux forums and communities you frequent. That helps us a lot. Thank you.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/apt-search-command/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://wiki.debian.org/Apt
+[2]: https://itsfoss.com/ubuntu-repositories/
+[3]: https://ubuntu.com/
+[4]: https://itsfoss.com/apt-command-guide/
+[5]: https://itsfoss.com/root-user-ubuntu/
+[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/05/apt-search-apt-show-example-800x493.png?resize=800%2C493&ssl=1
+[7]: https://itsfoss.com/install-gambas-ubuntu/
+[8]: https://itsfoss.com/unable-to-locate-package-error-ubuntu/
+[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/apt-search-command.png?ssl=1
+[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/apt-search-command-example.png?fit=800%2C297&ssl=1
+[11]: https://itsfoss.com/list-installed-packages-ubuntu/
+[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/apt-show-command-example-800x474.png?resize=800%2C474&ssl=1
+[13]: https://itsfoss.com/apt-vs-apt-get-difference/
diff --git a/sources/tech/20200525 What to do When You See -Repository does not have a release file- Error in Ubuntu.md b/sources/tech/20200525 What to do When You See -Repository does not have a release file- Error in Ubuntu.md
new file mode 100644
index 0000000000..6cfd9f34de
--- /dev/null
+++ b/sources/tech/20200525 What to do When You See -Repository does not have a release file- Error in Ubuntu.md
@@ -0,0 +1,115 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (What to do When You See “Repository does not have a release file” Error in Ubuntu)
+[#]: via: (https://itsfoss.com/repository-does-not-have-release-file-error-ubuntu/)
+[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
+
+What to do When You See “Repository does not have a release file” Error in Ubuntu
+======
+
+One of the [several ways of installing software in Ubuntu][1] is by using PPA or adding third-party repositories. A few magical lines give you easy access to a software or its newer version that is not available by default in [Ubuntu][2].
+
+All thing looks well and good until you get habitual of adding additional third-party repositories and one day, you see an error like this while [updating Ubuntu][3]:
+
+**E: The repository ‘ focal Release’ does not have a Release file.
+N: Updating from such a repository can’t be done securely, and is therefore disabled by default.
+N: See apt-secure(8) manpage for repository creation and user configuration details.**
+
+In this tutorial for Ubuntu beginners, I’ll explain what does this error mean, why do you see it and what can you do to handle this error?
+
+### Understanding “Repository does not have a release file” error
+
+![][4]
+
+Let’s go step by step here. The error message is:
+
+**E: The repository ‘ focal release’ does not have a release file**
+
+The important part of this error message is “focal release”.
+
+You probably already know that [each Ubuntu release has a codename][5]. For Ubuntu 20.04, the codename is Focal Fossa. The “focal” in the error message indicates Focal Fossa which is Ubuntu 20.04.
+
+The error is basically telling you that though you have added a third-party repository to your system’s sources list, this new repository is not available for your current Ubuntu version.
+
+_**Why so? Because probably you are using a new version of Ubuntu and the developer has not made the software available for this new version.**_
+
+At this point, I highly recommend reading my detailed guides on [PPA][6] and [Ubuntu repositories][7]. These two articles will give you a better, in-depth knowledge of the topic. Trust me, you won’t be disappointed.
+
+### How to know if the PPA/third party is available for your Ubuntu version [Optional]
+
+First you should [check your Ubuntu version and its codename][8] using ‘lsb_release -a’ command:
+
+```
+[email protected]:~$ lsb_release -a
+No LSB modules are available.
+Distributor ID: Ubuntu
+Description: Ubuntu 20.04 LTS
+Release: 20.04
+Codename: focal
+```
+
+As you can see, the codename it shows is focal. Now the next thing you can do is to go to the website of the software in question.
+
+This could be the tricky part but you can figure it out with some patience and effort.
+
+In the example here, the error complained about ****. It is a PPA repository and you may easily find its webpage. How, you may ask.
+
+Use Google or a [Google alternative search engine][9] like Duck Duck Go and search for “ppa numix”. This should give you the first result from [launchpad.net][10] which is the website used for hosting PPA related code.
+
+On the webpage of the PPA, you can go to the “Overview of published packages” and filter it by the codename of your Ubuntu version:
+
+![][11]
+
+For non-PPA third-party repository, you’ll have to check of the official website of the software and see if the repository is available for your Ubuntu version or not.
+
+### What to do if the repository is not available for your Ubuntu version
+
+In case when the repository in question is not available for your Ubuntu version, here’s what you can do:
+
+ * Delete the troublesome repository from your list of repository so that you don’t see the error every time you run the update.
+ * Get the software from another source (if it is possible).
+
+
+
+To delete the troublesome repository, start Software & Updates tool:
+
+![][12]
+
+Go to the Other Software tab and look for the repository in question. Highlight it and then click on Remove button to delete it from your system.
+
+![Remove Ppa][13]
+
+This will [delete the PPA][14] or the repository in question.
+
+Next step is to get the software from some other source and that’s totally subjective. In some cases, you can still download the DEB file from the PPA website and use the software (I have explained the steps in the [PPA guide][6]). Alternatively, you can check the project’s website if there is a Snap/Flatpak or Python version of the software available.
+
+--------------------------------------------------------------------------------
+
+via: https://itsfoss.com/repository-does-not-have-release-file-error-ubuntu/
+
+作者:[Abhishek Prakash][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://itsfoss.com/author/abhishek/
+[b]: https://github.com/lujun9972
+[1]: https://itsfoss.com/install-remove-software-manjaro/
+[2]: https://ubuntu.com/
+[3]: https://itsfoss.com/update-ubuntu/
+[4]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/Repository-does-not-have-a-release-file.png?ssl=1
+[5]: https://itsfoss.com/linux-code-names/
+[6]: https://itsfoss.com/ppa-guide/
+[7]: https://itsfoss.com/ubuntu-repositories/
+[8]: https://itsfoss.com/how-to-know-ubuntu-unity-version/
+[9]: https://itsfoss.com/privacy-search-engines/
+[10]: https://launchpad.net/
+[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/05/check-repo-version.png?ssl=1
+[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/04/software-updates-settings-ubuntu-20-04.jpg?ssl=1
+[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/05/remove-ppa.jpg?ssl=1
+[14]: https://itsfoss.com/how-to-remove-or-delete-ppas-quick-tip/
diff --git a/sources/tech/20200526 Create interactive content in WordPress with the H5P plugin.md b/sources/tech/20200526 Create interactive content in WordPress with the H5P plugin.md
new file mode 100644
index 0000000000..871439e73a
--- /dev/null
+++ b/sources/tech/20200526 Create interactive content in WordPress with the H5P plugin.md
@@ -0,0 +1,130 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Create interactive content in WordPress with the H5P plugin)
+[#]: via: (https://opensource.com/article/20/5/h5p-wordpress)
+[#]: author: (Don Watkins https://opensource.com/users/don-watkins)
+
+Create interactive content in WordPress with the H5P plugin
+======
+Turn your WordPress site into an interactive learning management system
+with this open source plugin.
+![Family learning and reading together at night in a room][1]
+
+WordPress is best known as a website content management system, but it also a great [learning management system][2] (LMS) for delivering online courses. If that is what you are looking for out of WordPress, then [H5P][3] should be the top plugin on your list.
+
+H5P is a way to create and share interactive HTML5 content, including presentations, games, quizzes, forms, and more, in a browser. You can download a wide variety of content types from H5P's [Examples and Downloads][4] page, or you can create unique content to embed in your WordPress site.
+
+H5P provides plugins and integrations for WordPress, Moodle, Drupal, Canvas, Brightspace, Blackboard, and more. In this article, I will show how to use H5P in WordPress to create a reading comprehension quiz for students.
+
+### Install the H5P plugin
+
+The first step is to install the plugin. Log into your WordPress admin panel, go to **Plugins**, select **Add New**, and search for **H5P** in the Plugins field. When you find it, select **Install Now**.
+
+![Adding the H5P plugin][5]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+H5P should now appear in the list of installed plugins. Be sure to **Activate** the plugin by going to the H5P menu at the bottom of your WordPress admin panel and clicking the button. You will see the following display—be sure to consent so you can connect to the H5P Hub.
+
+![H5P consent option][7]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+Now you can begin adding H5P content to your WordPress installation.
+
+### Create a quiz
+
+One of my favorite poems is Robert Frost's "The Road Not Taken." Suppose you are teaching a class that is studying this poem, and one of your objectives is for your students to remember the poem's author. First, create a new WordPress post on your site that contains the poem's text and its author.
+
+![Creating a WordPress post][8]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+Now you want to test your students' comprehension with an HTML5 interactive content embedded below the poem.
+
+In the WordPress admin panel, look near the bottom for the **H5P Content** menu and select it. In the menu that appears, click **Add New**.
+
+![H5P Content menu][9]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+You will see an array of content options that are available. Since you want to create a multiple-choice quiz, look for the **Multiple Choice** option and click **Get** to its right.
+
+![H5P content types][10]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+A form will open for you to start creating the quiz. Fill in the required fields (marked with a red asterisk)—give your quiz a title (e.g., "Road Not Taken Quiz"), enter a question (e.g., "Who wrote, 'The Road Not Taken'?") and correct and incorrect answers, and select the correct answer in the dialog box. When you finish creating the quiz, save the content.
+
+![H5P quiz][11]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+### Embed the quiz in a post
+
+Now you're ready to insert the quiz exactly where you want it to appear in your post. Open the post where you want to put the quiz (e.g., "The Road Not Taken" post) in your WordPress editor, and you should see an **Add H5P** button near the top of the interface. Place your cursor wherever you want the quiz to appear in the post, and click **Add H5P**. Your H5P content will appear in a dialog box like this:
+
+![H5P list of interactive content][12]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+Select the content you want, and H5P will insert an embed code (e.g., `[h5p id="1"]`) in the post, like this:
+
+![H5P embed code in a post][13]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+Save your post, then open it in your browser. The quiz is exactly where you wanted it to appear in the post:
+
+![H5P quiz shown in the post][14]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+When a student answers this question correctly, they get pleasant visual feedback:
+
+![Correct answer selection][15]
+
+(Don Watkins, [CC BY-SA 4.0][6])
+
+### The possibilities are endless
+
+H5P offers a wide range of options to add interactivity to WordPress posts. In this example, you could have created a more complex set of multiple-choice questions. H5P also has lots of other content types, including interactive video, arithmetic quizzes, an audio recorder, image hotspots, fill-in-the-blank quizzes, and [many more][4].
+
+H5P also provides [excellent documentation][16] and [great tutorials][17] to help anyone who wants to use the plugin on their WordPress site. H5P software is open source under the [MIT License][18] with the code available on [GitHub][19]. H5P also welcomes contributions to the community; check out the [developer guide][20] for more information.
+
+--------------------------------------------------------------------------------
+
+via: https://opensource.com/article/20/5/h5p-wordpress
+
+作者:[Don Watkins][a]
+选题:[lujun9972][b]
+译者:[译者ID](https://github.com/译者ID)
+校对:[校对者ID](https://github.com/校对者ID)
+
+本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
+
+[a]: https://opensource.com/users/don-watkins
+[b]: https://github.com/lujun9972
+[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/family_learning_kids_night_reading.png?itok=6K7sJVb1 (Family learning and reading together at night in a room)
+[2]: https://en.wikipedia.org/wiki/Learning_management_system
+[3]: https://h5p.org/
+[4]: https://h5p.org/content-types-and-applications
+[5]: https://opensource.com/sites/default/files/uploads/addplugins-h5p.png (Adding the H5P plugin)
+[6]: https://creativecommons.org/licenses/by-sa/4.0/
+[7]: https://opensource.com/sites/default/files/uploads/h5p-consent.png (H5P consent option)
+[8]: https://opensource.com/sites/default/files/uploads/wordpress-post.png (WordPress post)
+[9]: https://opensource.com/sites/default/files/uploads/h5p-content-menu.png (H5P Content menu)
+[10]: https://opensource.com/sites/default/files/uploads/h5p-content-types.png (H5P content types)
+[11]: https://opensource.com/sites/default/files/uploads/h5p-multiple-choice-quiz.png (H5P quiz)
+[12]: https://opensource.com/sites/default/files/uploads/h5p-insert-interactive-content.png (H5P list of interactive content)
+[13]: https://opensource.com/sites/default/files/uploads/h5p-embedded-content.png (H5P embed code in a post)
+[14]: https://opensource.com/sites/default/files/uploads/h5p-quiz.png (H5P quiz shown in the post)
+[15]: https://opensource.com/sites/default/files/uploads/h5p-correct-answer.png (Correct answer selection)
+[16]: https://h5p.org/documentation/setup/wordpress
+[17]: https://h5p.org/documentation/for-authors/tutorials
+[18]: https://h5p.org/MIT-licensed
+[19]: https://github.com/h5p
+[20]: https://h5p.org/developers
diff --git a/sources/tech/20200527 Manage startup using systemd.md b/sources/tech/20200527 Manage startup using systemd.md
new file mode 100644
index 0000000000..c0ff18a13d
--- /dev/null
+++ b/sources/tech/20200527 Manage startup using systemd.md
@@ -0,0 +1,567 @@
+[#]: collector: (lujun9972)
+[#]: translator: ( )
+[#]: reviewer: ( )
+[#]: publisher: ( )
+[#]: url: ( )
+[#]: subject: (Manage startup using systemd)
+[#]: via: (https://opensource.com/article/20/5/manage-startup-systemd)
+[#]: author: (David Both https://opensource.com/users/dboth)
+
+Manage startup using systemd
+======
+Learn how systemd determines the order services start, even though it is
+essentially a parallel system.
+![Penguin with green background][1]
+
+While setting up a Linux system recently, I wanted to know how to ensure that dependencies for services and other units were up and running before those dependent services and units start. Specifically, I needed more knowledge of how systemd manages the startup sequence, especially in determining the order services are started in what is essentially a parallel system.
+
+You may know that SystemV (systemd's predecessor, as I explained in the [first article][2] in this series) orders the startup sequence by naming the startup scripts with an SXX prefix, where XX is a number from 00 to 99. SystemV then uses the sort order by name and runs each start script in sequence for the desired runlevel.
+
+But systemd uses unit files, which can be created or modified by a sysadmin, to define subroutines for not only initialization but also for regular operation. In the [third article][3] in this series, I explained how to create a mount unit file. In this fifth article, I demonstrate how to create a different type of unit file—a service unit file that runs a program at startup. You can also change certain configuration settings in the unit file and use the systemd journal to view the location of your changes in the startup sequence.
+
+### Preparation
+
+Make sure you have removed `rhgb` and `quiet` from the `GRUB_CMDLINE_LINUX=` line in the `/etc/default/grub` file, as I showed in the [second article][4] in this series. This enables you to observe the Linux startup message stream, which you'll need for some of the experiments in this article.
+
+### The program
+
+In this tutorial, you will create a simple program that enables you to observe a message during startup on the console and later in the systemd journal.
+
+Create the shell program `/usr/local/bin/hello.sh` and add the following content. You want to ensure that the result is visible during startup and that you can easily find it when looking through the systemd journal. You will use a version of the "Hello world" program with some bars around it, so it stands out. Make sure the file is executable and has user and group ownership by root with [700 permissions][5] for security:
+
+
+```
+#!/usr/bin/bash
+# Simple program to use for testing startup configurations
+# with systemd.
+# By David Both
+# Licensed under GPL V2
+#
+echo "###############################"
+echo "######### Hello World! ########"
+echo "###############################"
+```
+
+Run this program from the command line to verify that it works correctly:
+
+
+```
+[root@testvm1 ~]# hello.sh
+###############################
+######### Hello World! ########
+###############################
+[root@testvm1 ~]#
+```
+
+This program could be created in any scripting or compiled language. The `hello.sh` program could also be located in other places based on the [Linux filesystem hierarchical structure][6] (FHS). I place it in the `/usr/local/bin` directory so that it can be easily run from the command line without having to prepend a path when I type the command. I find that many of the shell programs I create need to be run from the command line and by other tools such as systemd.
+
+### The service unit file
+
+Create the service unit file `/etc/systemd/system/hello.service` with the following content. This file does not need to be executable, but for security, it does need user and group ownership by root and [644][7] or [640][8] permissions:
+
+
+```
+# Simple service unit file to use for testing
+# startup configurations with systemd.
+# By David Both
+# Licensed under GPL V2
+#
+
+[Unit]
+Description=My hello shell script
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/hello.sh
+
+[Install]
+WantedBy=multi-user.target
+```
+
+Verify that the service unit file performs as expected by viewing the service status. Any syntactical errors will show up here:
+
+
+```
+[root@testvm1 ~]# systemctl status hello.service
+● hello.service - My hello shell script
+ Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
+ Active: inactive (dead)
+[root@testvm1 ~]#
+```
+
+You can run this "oneshot" service type multiple times without problems. The oneshot type is intended for services where the program launched by the service unit file is the main process and must complete before systemd starts any dependent process.
+
+There are seven service types, and you can find an explanation of each (along with the other parts of a service unit file) in the [systemd.service(5)][9] man page. (You can also find more information in the [resources][10] at the end of this article.)
+
+As curious as I am, I wanted to see what an error might look like. So, I deleted the "o" from the `Type=oneshot` line, so it looked like `Type=neshot`, and ran the command again:
+
+
+```
+[root@testvm1 ~]# systemctl status hello.service
+● hello.service - My hello shell script
+ Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
+ Active: inactive (dead)
+
+May 06 08:50:09 testvm1.both.org systemd[1]: /etc/systemd/system/hello.service:12: Failed to parse service type, ignoring: neshot
+[root@testvm1 ~]#
+```
+
+These results told me precisely where the error was and made it very easy to resolve the problem.
+
+Just be aware that even after you restore the `hello.service` file to its original form, the error will persist. Although a reboot will clear the error, you should not have to do that, so I went looking for a method to clear out persistent errors like this. I have encountered service errors that require the command `systemctl daemon-reload` to reset an error condition, but that did not work in this case. The error messages that can be fixed with this command always seem to have a statement to that effect, so you know to run it.
+
+It is, however, recommended that you run `systemctl daemon-reload` after changing a unit file or creating a new one. This notifies systemd that the changes have been made, and it can prevent certain types of issues with managing altered services or units. Go ahead and run this command.
+
+After correcting the misspelling in the service unit file, a simple `systemctl restart hello.service` cleared the error. Experiment a bit by introducing some other errors into the `hello.service` file to see what kinds of results you get.
+
+### Start the service
+
+Now you are ready to start the new service and check the status to see the result. Although you probably did a restart in the previous section, you can start or restart a oneshot service as many times as you want since it runs once and then exits.
+
+Go ahead and start the service (as shown below), and then check the status. Depending upon how much you experimented with errors, your results may differ from mine:
+
+
+```
+[root@testvm1 ~]# systemctl start hello.service
+[root@testvm1 ~]# systemctl status hello.service
+● hello.service - My hello shell script
+ Loaded: loaded (/etc/systemd/system/hello.service; disabled; vendor preset: disabled)
+ Active: inactive (dead)
+
+May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
+May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
+May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
+May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
+May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
+May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
+May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
+May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
+May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
+May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
+[root@testvm1 ~]#
+```
+
+Notice in the status command's output that the systemd messages indicate that the `hello.sh` script started and the service completed. You can also see the output from the script. This display is generated from the journal entries of the most recent invocations of the service. Try starting the service several times, and then run the status command again to see what I mean.
+
+You should also look at the journal contents directly; there are multiple ways to do this. One way is to specify the record type identifier, in this case, the name of the shell script. This shows the journal entries for previous reboots as well as the current session. As you can see, I have been researching and testing for this article for some time now:
+
+
+```
+[root@testvm1 ~]# journalctl -t hello.sh
+<snip>
+\-- Reboot --
+May 08 15:55:47 testvm1.both.org hello.sh[840]: ###############################
+May 08 15:55:47 testvm1.both.org hello.sh[840]: ######### Hello World! ########
+May 08 15:55:47 testvm1.both.org hello.sh[840]: ###############################
+\-- Reboot --
+May 08 16:01:51 testvm1.both.org hello.sh[840]: ###############################
+May 08 16:01:51 testvm1.both.org hello.sh[840]: ######### Hello World! ########
+May 08 16:01:51 testvm1.both.org hello.sh[840]: ###############################
+\-- Reboot --
+May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
+May 10 10:37:49 testvm1.both.org hello.sh[842]: ######### Hello World! ########
+May 10 10:37:49 testvm1.both.org hello.sh[842]: ###############################
+May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
+May 10 10:54:45 testvm1.both.org hello.sh[1380]: ######### Hello World! ########
+May 10 10:54:45 testvm1.both.org hello.sh[1380]: ###############################
+[root@testvm1 ~]#
+```
+
+To locate the systemd records for the `hello.service` unit, you can search on systemd. You can use **G+Enter** to page to the end of the journal entries and then scroll back to locate the ones you are interested in. Use the `-b` option to show only the entries for the most recent startup:
+
+
+```
+[root@testvm1 ~]# journalctl -b -t systemd
+<snip>
+May 10 10:37:49 testvm1.both.org systemd[1]: Starting SYSV: Late init script for live image....
+May 10 10:37:49 testvm1.both.org systemd[1]: Started SYSV: Late init script for live image..
+May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
+May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
+May 10 10:37:50 testvm1.both.org systemd[1]: Starting D-Bus System Message Bus...
+May 10 10:37:50 testvm1.both.org systemd[1]: Started D-Bus System Message Bus.
+```
+
+I copied a few other journal entries to give you an idea of what you might find. This command spews all of the journal lines pertaining to systemd—109,183 lines when I wrote this. That is a lot of data to sort through. You can use the pager's search facility, which is usually `less`, or you can use the built-in `grep` feature. The `-g` (or `--grep=`) option uses Perl-compatible regular expressions:
+
+
+```
+[root@testvm1 ~]# journalctl -b -t systemd -g "hello"
+[root@testvm1 ~]# journalctl -b -t systemd -g "hello"
+\-- Logs begin at Tue 2020-05-05 18:11:49 EDT, end at Sun 2020-05-10 11:01:01 EDT. --
+May 10 10:37:49 testvm1.both.org systemd[1]: Starting My hello shell script...
+May 10 10:37:49 testvm1.both.org systemd[1]: hello.service: Succeeded.
+May 10 10:37:49 testvm1.both.org systemd[1]: Finished My hello shell script.
+May 10 10:54:45 testvm1.both.org systemd[1]: Starting My hello shell script...
+May 10 10:54:45 testvm1.both.org systemd[1]: hello.service: Succeeded.
+May 10 10:54:45 testvm1.both.org systemd[1]: Finished My hello shell script.
+[root@testvm1 ~]#
+```
+
+You could use the standard GNU `grep` command, but that would not show the log metadata in the first line.
+
+If you do not want to see just the journal entries pertaining to your `hello` service, you can narrow things down a bit by specifying a time range. For example, I will start with the beginning time of `10:54:00` on my test VM, which was the start of the minute the entries above are from. ****Note that the `--since=` option must be enclosed in quotes and that this option can also be expressed as `-S "