Merge pull request #13 from LCTT/master

update from lctt project
This commit is contained in:
beamrolling 2022-05-22 20:34:14 +08:00 committed by GitHub
commit 3c96afdcba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2956 changed files with 259087 additions and 189147 deletions

View File

@ -0,0 +1,27 @@
name: LCTT Article Badge
on:
push:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: checkout old pages branch
uses: actions/checkout@v2
with:
repository: lctt/translateproject
path: build
ref: gh-pages
- name: remove pages .git
run: rm -rf ./build/.git
- name: run badge
run: sh ./scripts/badge.sh;
- uses: crazy-max/ghaction-github-pages@v2.2.0
with:
build_dir: ./build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,18 @@
name: LCTT Article Checker
on:
pull_request:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
env:
PULL_REQUEST_ID: ${{ github.event.number }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: "checkout master branch & return to pull request branch"
run: CURRENT=$(echo ${{github.ref}} | sed "s|refs/|refs/remotes/|") && git checkout master && git checkout $CURRENT
- name: run check
run: sh ./scripts/check.sh;

View File

@ -0,0 +1,28 @@
name: LCTT Article Status
on:
schedule:
- cron: "*/30 * * * *"
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: checkout old pages branch
uses: actions/checkout@v2
with:
repository: lctt/translateproject
path: build
ref: gh-pages
- name: remove pages .git
run: rm -rf ./build/.git
- name: run status
run: sh ./scripts/status.sh;
- uses: crazy-max/ghaction-github-pages@v2.2.0
with:
build_dir: ./build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,27 +0,0 @@
language: minimal
install:
- sudo apt-get install jq
- git clone --depth=1 -b gh-pages https://github.com/LCTT/TranslateProject/ build && rm -rf build/.git
script:
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then sh ./scripts/check.sh; fi'
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then sh ./scripts/badge.sh; fi'
- 'if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then sh ./scripts/status.sh; fi'
branches:
only:
- master
# - status
except:
- gh-pages
git:
submodules: false
depth: false
deploy:
provider: pages
skip_cleanup: true
github_token: $GITHUB_TOKEN
local_dir: build
on:
branch:
- master
# - status

0
published/201610/20160812 What is copyleft.md Executable file → Normal file
View File

View File

View File

@ -0,0 +1,124 @@
[#]: subject: "Creating random, secure passwords in Go"
[#]: via: "https://opensource.com/article/18/5/creating-random-secure-passwords-go"
[#]: author: "Mihalis Tsoukalos https://opensource.com/users/mtsouk"
[#]: collector: "lkxed"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14621-1.html"
在 Go 中生成随机的安全密码
======
> Go 的随机数生成器是生成难以猜测的密码的好方法。
![](https://img.linux.net.cn/data/attachment/album/202205/21/152534k13a1wly39fuywu2.jpg)
你可以使用 [Go 编程语言][2] 提供的随机数生成器来生成由 ASCII 字符组成的难以猜测的密码。尽管本文中提供的代码很容易阅读,但是你仍需要了解 Go 的基础知识,才能更好地理解它。如果你是对 Go 还不熟悉,请阅读 [Go 语言之旅][3] 来了解更多信息,然后返回此处。
在介绍实用程序和它的代码之前,让我们先来看看这个 ASCII 表的子集,它可以在 `man ascii` 命令的输出中找到:
```
30 40 50 60 70 80 90 100 110 120
 ---------------------------------
0:    (  2  <  F  P  Z  d   n   x
1:    )  3  =  G  Q  [  e   o   y
2:    *  4  >  H  R  \  f   p   z
3: !  +  5  ?  I  S  ]  g   q   {
4: "  ,  6  @  J  T  ^  h   r   |
5: #  -  7  A  K  U  _  i   s   }
6: $  .  8  B  L  V  `  j   t   ~
7: %  /  9  C  M  W  a  k   u  DEL
8: &  0  :  D  N  X  b  l   v
9: '  1  ;  E  O  Y  c  m   w
```
在所有 ASCII 字符中,可打印字符的十进制值范围为 33 到 126其他的 ASCII 值都不适合用于密码。因此,本文介绍的实用程序将生成该范围内的 ASCII 字符。
### 生成随机整数
第一个实用程序名为 `random.go`,它生成指定数量的随机整数,这些整数位于给定范围内。`random.go` 最重要的部分是这个函数:
```
func random(min, max int) int {
return rand.Intn(max-min) + min
}
```
此函数使用了 `rand.Intn()` 函数来生成一个属于给定范围的随机整数。请注意,`rand.Intn()` 返回一个属于 `[0,n)` 的非负随机整数。如果它的参数是一个负数,这个函数将会抛出异常,异常消息是:`panic: invalid argument to Intn`。你可以在 [math/rand 文档][4] 中找到 `math/rand` 包的使用说明。
`random.go` 实用程序接受三个命令行参数:生成的整数的最小值、最大值和个数。
编译和执行 `random.go` 会产生这样的输出:
```
$ go build random.go
$ ./random
Usage: ./random MIX MAX TOTAL
$ ./random 1 3 10
2 2 1 2 2 1 1 2 2 1
```
如果你希望在 Go 中生成更安全的随机数,请使用 Go 库中的 `crypto/rand` 包。
### 生成随机密码
第二个实用程序 `randomPass.go` 用于生成随机密码。`randomPass.go` 使用 `random()` 函数来生成随机整数,它们随后被以下 Go 代码转换为 ASCII 字符:
```
for {
myRand := random(MIN, MAX)
newChar := string(startChar[0] + byte(myRand))
fmt.Print(newChar)
if i == LENGTH {
break
}
i++
}
```
`MIN` 的值为 `0``MAX` 的值为 `94`,而 `startChar` 的值为 `!`,它是 ASCII 表中第一个可打印的字符(十进制 ASCII 码为 `33`)。因此,所有生成的 ASCII 字符都位于 `!``~` 之间,后者的十进制 ASCII 码为 `126`
因此,生成的每个随机数都大于 `MIN`,小于 `MAX`,并转换为 ASCII 字符。该过程继续进行,直到生成的密码达到指定的长度。
`randomPass.go` 实用程序接受单个(可选)命令行参数,以定义生成密码的长度,默认值为 8这是一个非常常见的密码长度。执行 `randomPass.go` 会得到类似下面的输出:
```
$ go run randomPass.go 1
Z
$ go run randomPass.go 10
#Cw^a#IwkT
$ go run randomPass.go
Using default values!
[PP8@'Ci
```
最后一个细节:不要忘记调用 `rand.Seed()`,并提供一个<ruby>种子<rt>seed</rt></ruby>值,以初始化随机数生成器。如果你始终使用相同的种子值,随机数生成器将生成相同的随机整数序列。
![随机数生成代码][5]
你可以在 [GitHub][6] 找到 `random.go``randomPass.go` 的源码。你也可以直接在 [play.golang.org][7] 上执行它们。
我希望这篇文章对你有所帮助。如有任何问题,请在下方发表评论或在 [Twitter][8] 上与我联系。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/creating-random-secure-passwords-go
作者:[Mihalis Tsoukalos][a]
选题:[lkxed][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/mtsouk
[b]: https://github.com/lkxed
[1]: https://opensource.com/sites/default/files/lead-images/laptop-password.jpg
[2]: https://golang.org/
[3]: https://tour.golang.org/welcome/1
[4]: https://golang.org/pkg/math/rand/
[5]: https://opensource.com/sites/default/files/styles/panopoly_image_original/public/uploads/random.png?itok=DG0QPUGX
[6]: https://github.com/mactsouk/opensource.com
[7]: https://play.golang.org/
[8]: https://twitter.com/mactsouk

View File

@ -0,0 +1,153 @@
[#]: subject: "Build a concurrent TCP server in Go"
[#]: via: "https://opensource.com/article/18/5/building-concurrent-tcp-server-go"
[#]: author: "Mihalis Tsoukalos https://opensource.com/users/mtsouk"
[#]: collector: "lkxed"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14623-1.html"
在 Go 中实现一个支持并发的 TCP 服务端
======
![](https://img.linux.net.cn/data/attachment/album/202205/22/115536nkfuuf4dklgg7fsx.jpg)
> 仅用大约 65 行代码,开发一个用于生成随机数、支持并发的 TCP 服务端。
TCP 和 UDP 服务端随处可见,它们基于 TCP/IP 协议栈,通过网络为客户端提供服务。在这篇文章中,我将介绍如何使用 [Go 语言][2] 开发一个用于返回随机数、支持并发的 TCP 服务端。对于每一个来自 TCP 客户端的连接,它都会启动一个新的 goroutine轻量级线程来处理相应的请求。
你可以在 GitHub 上找到本项目的源码:[concTcp.go][3]。
### 处理 TCP 连接
这个程序的主要逻辑在 `handleConnection()` 函数中,具体实现如下:
```
func handleConnection(c net.Conn) {
        fmt.Printf("Serving %s\n", c.RemoteAddr().String())
        for {
                netData, err := bufio.NewReader(c).ReadString('\n')
                if err != nil {
                        fmt.Println(err)
                        return
                }
                temp := strings.TrimSpace(string(netData))
                if temp == "STOP" {
                        break
                }
                result := strconv.Itoa(random()) + "\n"
                c.Write([]byte(string(result)))
        }
        c.Close()
}
```
如果 TCP 客户端发送了一个 “STOP” 字符串,为它提供服务的 goroutine 就会终止否则TCP 服务端就会返回一个随机数给它。只要客户端不主动终止,服务端就会一直提供服务,这是由 `for` 循环保证的。具体来说,`for` 循环中的代码使用了 `bufio.NewReader(c).ReadString('\n')` 来逐行读取客户端发来的数据,并使用 `c.Write([]byte(string(result)))` 来返回数据(生成的随机数)。你可以在 Go 的 net 标准包 [文档][4] 中了解更多。
### 支持并发
`main()` 函数的实现部分,每当 TCP 服务端收到 TCP 客户端的连接请求,它都会启动一个新的 goroutine 来为这个请求提供服务。
```
func main() {
        arguments := os.Args
        if len(arguments) == 1 {
                fmt.Println("Please provide a port number!")
                return
        }
        PORT := ":" + arguments[1]
        l, err := net.Listen("tcp4", PORT)
        if err != nil {
                fmt.Println(err)
                return
        }
        defer l.Close()
        rand.Seed(time.Now().Unix())
        for {
                c, err := l.Accept()
                if err != nil {
                        fmt.Println(err)
                        return
                }
                go handleConnection(c)
        }
}
```
首先,`main()` 确保程序至少有一个命令行参数。注意,现有代码并没有检查这个参数是否为有效的 TCP 端口号。不过,如果它是一个无效的 TCP 端口号,`net.Listen()` 就会调用失败,并返回一个错误信息,类似下面这样:
```
$ go run concTCP.go 12a
listen tcp4: lookup tcp4/12a: nodename nor servname provided, or not known
$ go run concTCP.go -10
listen tcp4: address -10: invalid port
```
`net.Listen()` 函数用于告诉 Go 接受网络连接,因而承担了服务端的角色。它的返回值类型是 `net.Conn`,后者实现了 `io.Reader``io.Writer` 接口。此外,`main()` 函数中还调用了 `rand.Seed()` 函数,用于初始化随机数生成器。最后,`for` 循环允许程序一直使用 `Accept()` 函数来接受 TCP 客户端的连接请求,并以 goroutine 的方式来运行 `handleConnection(c)` 函数,处理客户端的后续请求。
### net.Listen() 的第一个参数
`net.Listen()` 函数的第一个参数定义了使用的网络类型,而第二个参数定义了服务端监听的地址和端口号。第一个参数的有效值为 `tcp`、`tcp4`、`tcp6`、`udp`、`udp4`、`udp6`、`ip`、`ip4`、`ip6`、`Unix`Unix 套接字)、`Unixgram` 和 `Unixpacket`,其中:`tcp4`、`udp4` 和 `ip4` 只接受 IPv4 地址,而 `tcp6`、`udp6` 和 `ip6` 只接受 IPv6 地址。
### 服务端并发测试
`concTCP.go` 需要一个命令行参数,来指定监听的端口号。当它开始服务 TCP 客户端时,你会得到类似下面的输出:
```
$ go run concTCP.go 8001
Serving 127.0.0.1:62554
Serving 127.0.0.1:62556
```
`netstat` 的输出可以确认 `congTCP.go` 正在为多个 TCP 客户端提供服务,并且仍在继续监听建立连接的请求:
```
$ netstat -anp TCP | grep 8001
tcp4       0      0  127.0.0.1.8001         127.0.0.1.62556        ESTABLISHED
tcp4       0      0  127.0.0.1.62556        127.0.0.1.8001         ESTABLISHED
tcp4       0      0  127.0.0.1.8001         127.0.0.1.62554        ESTABLISHED
tcp4       0      0  127.0.0.1.62554        127.0.0.1.8001         ESTABLISHED
tcp4       0      0  *.8001                 *.*                    LISTEN
```
在上面输出中,最后一行显示了有一个进程正在监听 8001 端口,这意味着你可以继续连接 TCP 的 8001 端口。第一行和第二行显示了有一个已建立的 TCP 网络连接,它占用了 8001 和 62556 端口。相似地,第三行和第四行显示了有另一个已建立的 TCP 连接,它占用了 8001 和 62554 端口。
下面这张图片显示了 `concTCP.go` 在服务多个 TCP 客户端时的输出:
![concTCP.go TCP 服务端测试][5]
类似地,下面这张图片显示了两个 TCP 客户端的输出(使用了 `nc` 工具):
![是用 nc 工具作为 concTCP.go 的 TCP 客户端][6]
你可以在 [维基百科][7] 上找到更多关于 `nc`(即 `netcat`)的信息。
### 总结
现在,你学会了如何用大约 65 行 Go 代码来开发一个生成随机数、支持并发的 TCP 服务端,这真是太棒了!如果你想要让你的 TCP 服务端执行别的任务,只需要修改 `handleConnection()` 函数即可。
--------------------------------------------------------------------------------
via: https://opensource.com/article/18/5/building-concurrent-tcp-server-go
作者:[Mihalis Tsoukalos][a]
选题:[lkxed][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/mtsouk
[b]: https://github.com/lkxed
[1]: https://opensource.com/sites/default/files/lead-images/go-golang.png
[2]: https://golang.org/
[3]: https://github.com/mactsouk/opensource.com
[4]: https://golang.org/pkg/net/
[5]: https://opensource.com/sites/default/files/uploads/tcp-in-go_server.png
[6]: https://opensource.com/sites/default/files/uploads/tcp-in-go_client.png
[7]: https://en.wikipedia.org/wiki/Netcat

View File

@ -0,0 +1,86 @@
[#]: subject: "Why you should choose mindfulness over multitasking"
[#]: via: "https://opensource.com/article/19/4/mindfulness-over-multitasking"
[#]: author: "Sarah Wall https://opensource.com/users/sarahwall"
[#]: collector: "lkxed"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14581-1.html"
你为什么应该选择专注而非一心多用
======
> 如果你有时候会感觉大脑处于停滞状态,那么你可能正在遭受一心多用和决策疲劳。
![](https://img.linux.net.cn/data/attachment/album/202205/11/232939ixz3xfnhwxn5oz2i.jpg)
想象一下,你刚完成了日常工作,坐在电脑前,手里拿着晨间咖啡,正准备开始新的一天。突然,一条 Slack 消息弹了出来,你扫了一眼邮件,然后切回 Slack。你打开日历看看下一次会议是什么时候令你惊讶的是它 15 分钟后就要开始了!你回到办公桌前,开始检查待办事项,想看看在这短短 15 分钟内还能给自己安排什么任务,但不巧的是,这时你的一个同事请求你帮他解决一个问题。大半天就这样过去了,而你根本没有意识到……
我的许多日子都是这样度过的,不断地多个任务之间徘徊。有些时候,我发现自己盯着电脑,大脑完全停滞。如果你也发现自己处于这种情况,这可能是你的大脑发出的信号,提醒你休息一下。你可能正在遭受一心多用和决策疲劳。
平均而言,成年人每天要做大约 [35000 个决定][2]!它们可能是简单的决定,如吃什么或穿什么,也可能是需要更多思考的决定,如下一个假期去哪里或从事哪个职业。每天你都面临着大量的选择,它们占据了你的头脑。
### 分散注意力的一心多用
不只有你一个人每天面临着数以千计的决定,事实上,一心多用早已成为忙碌的、工作中的专业人士的常态。问题是,一心多用的伤害比它的帮助更大。你越是为了处理多任务而分散注意力,你的生产力就越是下降。
在一项研究中,自称是一心多用者的人,被要求以他们感觉自然的速度,在各种任务之间来回切换。同时,研究的对照组,被要求按顺序,一次完成一项工作。研究表明,多任务组的效率要低得多。每次他们切换任务时,都会出现速度减慢的情况,因为他们需要时间来回忆到目前为止所做的细节和步骤。这最终 [额外花费了大约 40% 的时间][3],并导致整体准确度降低。每次专注于一项任务的人,总体上花费的时间更少,并且完成了所有的任务。
### 选择专注
当大脑集中在一项活动上时,它的功能是最理想的。选择专注而不是一心多用,将使你在一天中获得更好的感受,并帮助你完成更好的工作。
“专注”可以被定义为有意识和察觉的。它实际上是指活在当下,并将注意力集中于眼前的事情上。在工作场所,专注有很多好处。它的诀窍在于建立边界和习惯,使你能够对每项任务给予充分的关注。
保持积极主动,为每天必须完成的项目排好优先级,并制定一个完成计划。这将使你能够在一些重要的事情上取得真正的进展,而不是被动应付。你的待办事项清单上的每个项目,都应该是独立、明确、可操作的。每天专注于三到五项任务,不要太多。
### 三种在工作日休息的方法
不要忘记把“休息”也放进一天的计划中。大脑每小时需要几分钟的休息,以休养生息,避免倦怠。休息一下对你的心理健康也有好处,最终 [有助于生产力的提高][4]。
这里有三种简单的“休息”方法,请把它们融入到你忙碌的一天中吧!
#### 1、移动身体
花 10 分钟时间,离开你的椅子,站起来走一走。如果你的时间很紧张,可以站起来伸展两分钟。改变身体所处的位置,并专注于当下,将有助于缓解积聚在你心中的精神紧张。
#### 2、多笑
休息一下,与你的朋友和工作中的同事交谈。笑声可以减少压力荷尔蒙,并引发内啡肽的释放,内啡肽是人体天然的的化学物质,它会使人感觉良好。欢声笑语的小憩有助于放松你的头脑,对你的灵魂也有好处。
#### 3、深呼吸
用两分钟的休息时间来重置你的身心,使用腹部深呼吸。它可以使你的身心平静下来,改善氧气流动,并给你带来自然的能量提升。
1. 挺直坐正,将注意力放在腹部,感受它的柔软和放松。
2. 从缓慢的深吸气开始,数三下,让氧气依次充满你的腹部、肋骨和上胸。
3. 停顿一秒钟,然后与深吸气相反,从上胸、肋骨和腹部呼气,最后将腹部拉向脊柱。
4. 再次停顿,然后重复。
### 重置自己
下次当你发现自己处于停滞状态,或是正在强迫状态不佳的自己完成一项任务时,请尝试上面的一些提示。最好是短暂休息一下,重置身心,而不要试图强行完成任务。相信我,你的身体和大脑会感谢你的!
本文改编自《BodyMindSpirit》上的 [让自己休息一下][5] 和 ImageX 的博文 [专注而不是一心多用][6]。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/4/mindfulness-over-multitasking
作者:[Sarah Wall][a]
选题:[lkxed][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/sarahwall
[b]: https://github.com/lkxed
[1]: https://opensource.com/sites/default/files/lead-images/life_tree_clouds.png
[2]: https://go.roberts.edu/leadingedge/the-great-choices-of-strategic-leaders
[3]: http://www.apa.org/research/action/multitask.aspx
[4]: https://opensource.com/article/19/3/guide-being-more-productive
[5]: https://body-mind-spirit-coach.com/2019/01/02/give-yourself-a-break/
[6]: https://imagexmedia.com/mindfullness-over-multitasking
[7]: https://events.drupal.org/seattle2019/sessions/mindless-multitasking-dummy%E2%80%99s-guide-productivity
[8]: https://events.drupal.org/seattle2019

View File

View File

@ -0,0 +1,150 @@
[#]: collector: (lujun9972)
[#]: translator: (Starryi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-14557-1.html)
[#]: subject: (Watching activity on Linux with watch and tail commands)
[#]: via: (https://www.networkworld.com/article/3529891/watching-activity-on-linux-with-watch-and-tail-commands.html)
[#]: author: (Sandra Henry-Stocker https://www.networkworld.com/author/Sandra-Henry_Stocker/)
使用 watch 和 tail 命令监视 Linux 上的活动
======
![](https://img.linux.net.cn/data/attachment/album/202205/07/091736ja5yt2yottef0kl4.jpg)
> watch 和 tail 命令可以帮助监视 Linux 系统上的活动。本文介绍了这两个命令的一些有用的使用方法。
`watch``tail` 命令为持续监视 Linux 系统上的活动提供了一些有趣的选项。
也就是说,你可以通过 `watch` 来显示谁已登录,并随着用户登录和注销不断更新,而不是仅仅提出问题并获得答案(例如询问 `who` 并获取当前登录用户的列表)。
使用 `tail`,你可以显示文件的底部并在添加内容时查看内容。这种监控一般非常有用,并且比定期运行命令所需的工作更少。
### 使用 watch 命令
使用 `watch` 的最简单示例之一是使用命令 `watch who`。你会看到一个列表,其中显示了谁登录了,以及他们登录的时间和登录位置。请注意,默认设置是每两秒更新一次显示(左上角),日期和时间(右上角)将按该间隔自行更新。用户列表将随着用户登录和注销而增长和缩小。
```
$ watch who
```
此命令将显示如下所示的登录列表:
```
Every 2.0s: who dragonfly: Thu Feb 27 10:52:00 2020
nemo pts/0 2020-02-27 08:07 (192.168.0.11)
shs pts/1 2020-02-27 10:58 (192.168.0.5)
```
你可以通过添加 `-n` 选项(例如 `-n 10`)来修改更新间的不同秒数,以修改更新间隔,从而获取较少的更新频率。
```
$ watch -n 10 who
```
上述命令将以新的间隔显示,并且显示的时间更新频率较低,从而使显示时间与所选间隔保持一致。
```
Every 10.0s: who dragonfly: Thu Feb 27 11:05:47 2020
nemo pts/0 2020-02-27 08:07 (192.168.0.11)
shs pts/1 2020-02-27 10:58 (192.168.0.5)
```
如果你希望仅查看命令的输出,而不是标题(前 2 行),则可以通过添加 `-t`(无标题)选项来省略这些行。
```
$ watch -t who
```
然后,你的屏幕将显示如下所示:
```
nemo pts/0 2020-02-27 08:07 (192.168.0.11)
shs pts/1 2020-02-27 10:58 (192.168.0.5)
```
如果每次运行监视的命令时,输出都是相同的,则只有标题行(如果未省略)会更改。其余显示的信息将保持不变。
如果你希望 `watch` 命令在它正在监视的命令的输出发生更新后立即退出,则可以使用 `-g`(将其视为“<ruby>离开<rt>go away</rt></ruby>”)选项。例如,如果你只是在等待其他人开始登录系统,则可以选择执行此操作。
你还可以使用 `-d`<ruby>差异<rt>differences</rt></ruby>)选项突出显示显示输出中的更改。突出显示只会持续一个间隔(默认为 2 秒),但有助于引起你对更新的注意。
下面是一个更复杂的示例,该示例使用 `watch` 命令显示正在侦听连接的服务及其使用的端口。虽然输出不太可能更改,但它会提醒你任何新服务正在启动或关闭。
```
$ watch 'sudo lsof -i -P -n | grep LISTEN'
```
值得注意的是,正在运行的命令需要用引号扩起来,以确保不会将 `watch` 命令的输出发送到 `grep` 命令。
使用 `watch -h` 命令将为你提供命令选项的列表。
```
$ watch -h
Usage:
watch [options] command
Options:
-b, --beep beep if command has a non-zero exit
-c, --color interpret ANSI color and style sequences
-d, --differences[=<permanent>]
highlight changes between updates
-e, --errexit exit if command has a non-zero exit
-g, --chgexit exit when output from command changes
-n, --interval <secs> seconds to wait between updates
-p, --precise attempt run command in precise intervals
-t, --no-title turn off header
-x, --exec pass command to exec instead of "sh -c"
-h, --help display this help and exit
-v, --version output version information and exit
```
### 使用 tail -f
`tail -f` 命令与 `watch` 有一些相同之处。它也会在添加文件时显示文件的底部和其他内容。你不必一次又一次地运行 `tail` 命令,而是运行一个命令并获得可重复更新显示视图的结果。例如,你可以使用如下命令查看系统日志:
```
$ tail -f /var/log/syslog
```
某些文件(如 `/var/log/wtmp`)不适合这种类型的处理,因为它们的格式不是普通文本文件,但是通过组合 `watch``tail`,你可以获得类似的结果,如下所示:
```
watch 'who /var/log/wtmp | tail -20'
```
无论有多少用户仍处于登录状态,此命令都将只显示最近的 5 次登录。如果发生其他登录,显示结果将添加一行记录并删除顶行记录。
```
Every 60.0s: who /var/log/wtmp | tail -5 dragonfly: Thu Feb 27 12:46:07 2020
shs pts/0 2020-02-27 08:07 (192.168.0.5)
nemo pts/1 2020-02-27 08:26 (192.168.0.5)
shs pts/1 2020-02-27 10:58 (192.168.0.5)
nemo pts/1 2020-02-27 11:34 (192.168.0.5)
dory pts/1 2020-02-27 12:14 (192.168.0.5)
```
对你有时可能想要监视的信息,无论监视进程、登录名还是系统资源,`watch` 和 `tail -f` 命令都可以提供自动更新视图,从而使监视任务变得更加容易。
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3529891/watching-activity-on-linux-with-watch-and-tail-commands.html
作者:[Sandra Henry-Stocker][a]
选题:[lujun9972][b]
译者:[Starryi](https://github.com/Starryi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.networkworld.com/author/Sandra-Henry_Stocker/
[b]: https://github.com/lujun9972
[1]: https://www.networkworld.com/newsletters/signup.html
[2]: https://www.networkworld.com/article/3440100/take-the-intelligent-route-with-consumption-based-storage.html?utm_source=IDG&utm_medium=promotions&utm_campaign=HPE21620&utm_content=sidebar ( Take the Intelligent Route with Consumption-Based Storage)
[3]: https://www.facebook.com/NetworkWorld/
[4]: https://www.linkedin.com/company/network-world

0
published/202007/20200701 Customizing Bash.md Executable file → Normal file
View File

View File

@ -0,0 +1,114 @@
[#]: subject: "A Beginner's Guide to Open Source"
[#]: via: "https://ruthikegah.xyz/a-beginners-guide-to-open-source"
[#]: author: "Ruth Ikegah https://hashnode.com/@ikegah_ruth"
[#]: collector: "lkxed"
[#]: translator: "lkxed"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-14600-1.html"
开源新手指南
======
![](https://img.linux.net.cn/data/attachment/album/202205/16/144822bal5z8ij44s4jcom.jpg)
作为一名技术人员,你应该时不时会看到“<ruby>开源<rt>Open Source</rt></ruby>”这个词。你有可能在浏览推文、博文时看到过它,也有可能是在学习某一门编程语言或使用某个工具时,看到它的部分介绍写着:这个工具/语言是“开源”的。总之,开源无处不在。
在本文中,我将介绍下面这三个话题:
* 什么是开源
* 贡献于开源的好处
* 如何开始贡献
### 什么是开源
开源指的是这样一些软件、项目或社区:它们允许人们修改和分享,因为它们的设计目的就是为了让所有人都能访问。举一个关于菜谱的例子:你可以做你从未发明过的菜,因为发明这个菜谱的人公开了它。大多数时候,你也可以根据自己的口味烹饪,而不会呛到喉咙(开个玩笑)。
> <ruby>开源软件<rt>Open Source Software</rt></ruby>OSS是指源代码可供他人查看、复制、学习、修改或分享的软件。
下面是开源软件和语言的一些例子:
* Linux 操作系统
* Google 的 Android 操作系统
* Firefox 浏览器
* VLC 媒体播放器
* Python 语言、PHP 语言、MySQL 数据库
与开源软件相反的是<ruby>专有软件<rt>proprietary software</rt></ruby> / <ruby>闭源软件<rt>closed source software</rt></ruby>,只有软件的创造者才能自由使用,其他人若想使用,就得先获得法律许可才行。例如 Adobe Photoshop、微软 Office 等。
> 开源不仅限于软件或代码,技术领域的任何人都可以为开源做出贡献(各个角色)。有了开源,就有了透明度、可靠性、灵活性,并允许开放合作。
### 贡献于开源的好处
向开源项目或软件做贡献意味着“免费”让该项目变得更好。你应该会问自己,为什么我要关心或向自己强调“免费”呢?如果你是新手,你可以阅读 [Edidiong Asikpo][2] 的故事,她在 [这篇文章][3] 中说明了为什么开源是她成长的催化剂。
贡献开源的好处有很多,这里是其中一部分:
* 它能够帮助你提高现有的技能,特别是对于新手而言,因为它允许你边做边学。
* 无论身在何处,你都可以与世界各地的优秀科技人士协作或共事。
* 你可以公开自己的想法,从而改善软件、项目或社区,让世界变得更美好。
* 你可以通过贡献开源来得到大家的认可,或者成为独特或伟大事物的一部分(获得自豪感)。
* 它让你有机会成为一个人才济济、活力四射的社区的一分子,你可以从中汲取灵感,并结识志同道合的人。
* 你可以因为贡献开源而获得报酬OoO比如你可以参与一些实习包括 <ruby>[谷歌编程之夏][4]<rt>Google Summer of Code</rt></ruby>、[Outreachy][5]、<ruby>[谷歌文档季][6]<rt>Google Season of Docs</rt></ruby>,以及 Open Collective 的 <ruby>[赏金计划][7]<rt>bounty program</rt></ruby> 等。LCTT 译注:国内也有类似的开源实习机会,如“开源之夏”。)
### 如何开始贡献
我相信你会对上面提到的最后一点感兴趣吧(^o^),那么,你该如何开始为开源软件做贡献呢?
是时候介绍一下 GitHub 了!
Github 是开源项目协作的大本营,因此它是一个开始贡献开源的好地方。没听说过 GitHub没有关系它提供了文档和指南很容易就可以上手。不过我还是要提醒你学习是一个循序渐进的过程不要太心急喔。
Github 以公共<ruby>存储库<rt>repositories</rt></ruby>的形式容纳了许多开源项目。对于某个项目,你可以提交一个<ruby>议题<rt>issue</rt></ruby>,来说明你注意到的错误或问题(或进一步提出改进意见),也可以创建一个<ruby>拉取请求<rt>pull request</rt></ruby>PR并说明你的更正和改进。
我不建议你在 GitHub 上搜索项目来开始贡献这将是相当令人沮丧的。尽管你可以限定项目使用的编程语言来简化搜索过程但仍然会有一大堆东西出现在你眼前。LCCT 译注:对于可爱的小萌新来说,这实在是难以承受 >…<。)
为了更精准地找到适合自己的项目,这里有一些可供开始的途径:
* [First-timers only][8]:一个很好的资源网站,你可以在上面找到新手友好的开源项目来开始贡献。(设计师朋友,我没有忘记你!你可以查看 [Open Source Design][9] 这个网站,在上面也能找到新手友好的开源设计项目!)
* 你可以创建你自己的开源项目,把你美妙的想法变成现实,并允许其他人的合作和贡献。[这里][10] 有关于如何创建开源项目的指南。
* 加入一个社区:你可以成为某个社区的成员,这也是传播开源思想的一种方式。你可以在谷歌上搜索当地的开源社区,并积极加入其中。
最后,我想给出几个有用的提示,供你在贡献开源项目时参考:
* 在加入之前,先对项目、社区或组织做一些研究;当你在做的时候,针对不清楚的地方提出问题。
* 当你加入社区时,尽量积极地介绍自己,并说明你能帮助项目的地方。
* **不要**认为自己无法为项目提供任何帮助,停止这种念头!你有很好的想法可以分享!
* 在存储库中看看别人提交的议题如果有的话看看你能在哪些方面提供帮助你可以关注带有“good first issue”、“help-wanted”、“first-timers only”等标签的议题。
* 在开始贡献之前,一定要先看一下贡献指南,这样你在贡献时就不会有冲突。
> 哪怕只是使用一个开源工具也是一种贡献;参加一个开源活动也是一种贡献;做开源项目的志愿者,或者为开源项目提供赞助也是一种贡献。
我想用非洲开源节的口号来结束:“未来是开放的”,所以快上车吧!
感谢阅读!
如果你还有疑问或需要帮助,请在 [这里][11] 联系我,我很乐意和你讨论开源,并帮助你做出首次贡献!
**LCTT 译注读了这篇文章你是不是想要马上投身于开源贡献呢那么请考虑加入“Linux 中国翻译组LCTT”吧我们有能帮助你快速上手翻译的 [维基][12] ,有热心友爱的 QQ 群,你甚至还能够在我们的官网上获得属于自己的译者专页……心动了吗?那就立刻行动起来吧!阅读 [维基][12] 以了解如何加入我们~**
--------------------------------------------------------------------------------
via: https://ruthikegah.xyz/a-beginners-guide-to-open-source
作者:[Ruth Ikegah][a]
选题:[lkxed][b]
译者:[lkxed](https://github.com/lkxed)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://hashnode.com/@ikegah_ruth
[b]: https://github.com/lkxed
[1]: https://ruthikegah.xyz/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1596742204400%2Fk9AJL1oNC.jpeg%3Fw%3D1600%26h%3D840%26fit%3Dcrop%26crop%3Dentropy%26auto%3Dcompress%2Cformat%26format%3Dwebp&w=3840&q=75
[2]: https://hashnode.com/@didicodes
[3]: https://edidiongasikpo.com/open-source-contributions-a-catalyst-for-growth-b823fc5752b1
[4]: https://summerofcode.withgoogle.com
[5]: https://www.outreachy.org/
[6]: https://developers.google.com/season-of-docs
[7]: https://docs.opencollective.com/help/contributing/development/bounties
[8]: https://www.firsttimersonly.com/
[9]: https://opensourcedesign.net/
[10]: https://github.com/Ruth-ikegah/opensource.guide
[11]: https://twitter.com/IkegahRuth
[12]: https://lctt.github.io/wiki/intro/lctt.html

View File

@ -0,0 +1,935 @@
[#]: collector: (oska874)
[#]: translator: (gxlct008)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12747-1.html)
[#]: subject: (Go on very small hardware Part 2)
[#]: via: (https://ziutek.github.io/2018/04/14/go_on_very_small_hardware2.html)
[#]: author: (Michał Derkacz https://ziutek.github.io/)
Go 语言在极小硬件上的运用(二)
============================================================
![](https://img.linux.net.cn/data/attachment/album/201909/24/210256yihkuy8kcigugr2h.png)
在本文的 [第一部分][2] 的结尾,我承诺要写关于接口的内容。我不想在这里写有关接口或完整或简短的讲义。相反,我将展示一个简单的示例,来说明如何定义和使用接口,以及如何利用无处不在的 `io.Writer` 接口。还有一些关于<ruby>反射<rt>reflection</rt></ruby><ruby>半主机<rt>semihosting</rt></ruby>的内容。
![STM32F030F4P6](https://ziutek.github.io/images/mcu/f030-demo-board/board.jpg)
接口是 Go 语言的重要组成部分。如果你想了解更多有关它们的信息,我建议你阅读《[高效的 Go 编程][3]》 和 [Russ Cox 的文章][4]。
### 并发 Blinky 回顾
当你阅读前面示例的代码时,你可能会注意到一中打开或关闭 LED 的反直觉方式。 `Set` 方法用于关闭 LED`Clear` 方法用于打开 LED。这是由于在 <ruby>漏极开路配置<rt>open-drain configuration</rt></ruby> 下驱动了 LED。我们可以做些什么来减少代码的混乱让我们用 `On``Off` 方法来定义 `LED` 类型:
```
type LED struct {
pin gpio.Pin
}
func (led LED) On() {
led.pin.Clear()
}
func (led LED) Off() {
led.pin.Set()
}
```
现在我们可以简单地调用 `led.On()``led.Off()`,这不会再引起任何疑惑了。
在前面的所有示例中,我都尝试使用相同的 <ruby>漏极开路配置<rt>open-drain configuration</rt></ruby>来避免代码复杂化。但是在最后一个示例中,对于我来说,将第三个 LED 连接到 GND 和 PA3 引脚之间并将 PA3 配置为<ruby>推挽模式<rt>push-pull mode</rt></ruby>会更容易。下一个示例将使用以此方式连接的 LED。
但是我们的新 `LED` 类型不支持推挽配置,实际上,我们应该将其称为 `OpenDrainLED`,并定义另一个类型 `PushPullLED`
```
type PushPullLED struct {
pin gpio.Pin
}
func (led PushPullLED) On() {
led.pin.Set()
}
func (led PushPullLED) Off() {
led.pin.Clear()
}
```
请注意,这两种类型都具有相同的方法,它们的工作方式也相同。如果在 LED 上运行的代码可以同时使用这两种类型,而不必注意当前使用的是哪种类型,那就太好了。 接口类型可以提供帮助:
```
package main
import (
"delay"
"stm32/hal/gpio"
"stm32/hal/system"
"stm32/hal/system/timer/systick"
)
type LED interface {
On()
Off()
}
type PushPullLED struct{ pin gpio.Pin }
func (led PushPullLED) On() {
led.pin.Set()
}
func (led PushPullLED) Off() {
led.pin.Clear()
}
func MakePushPullLED(pin gpio.Pin) PushPullLED {
pin.Setup(&gpio.Config{Mode: gpio.Out, Driver: gpio.PushPull})
return PushPullLED{pin}
}
type OpenDrainLED struct{ pin gpio.Pin }
func (led OpenDrainLED) On() {
led.pin.Clear()
}
func (led OpenDrainLED) Off() {
led.pin.Set()
}
func MakeOpenDrainLED(pin gpio.Pin) OpenDrainLED {
pin.Setup(&gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain})
return OpenDrainLED{pin}
}
var led1, led2 LED
func init() {
system.SetupPLL(8, 1, 48/8)
systick.Setup(2e6)
gpio.A.EnableClock(false)
led1 = MakeOpenDrainLED(gpio.A.Pin(4))
led2 = MakePushPullLED(gpio.A.Pin(3))
}
func blinky(led LED, period int) {
for {
led.On()
delay.Millisec(100)
led.Off()
delay.Millisec(period - 100)
}
}
func main() {
go blinky(led1, 500)
blinky(led2, 1000)
}
```
我们定义了 `LED` 接口,它有两个方法: `On``Off``PushPullLED``OpenDrainLED` 类型代表两种驱动 LED 的方式。我们还定义了两个用作构造函数的 `Make*LED` 函数。这两种类型都实现了 `LED` 接口,因此可以将这些类型的值赋给 `LED` 类型的变量:
```
led1 = MakeOpenDrainLED(gpio.A.Pin(4))
led2 = MakePushPullLED(gpio.A.Pin(3))
```
在这种情况下,<ruby>可赋值性<rt>assignability</rt></ruby>在编译时检查。赋值后,`led1` 变量包含一个 `OpenDrainLED{gpio.A.Pin(4)}`,以及一个指向 `OpenDrainLED` 类型的方法集的指针。 `led1.On()` 调用大致对应于以下 C 代码:
```
led1.methods->On(led1.value)
```
如你所见,如果仅考虑函数调用的开销,这是相当廉价的抽象。
但是,对接口的任何赋值都会导致包含有关已赋值类型的大量信息。对于由许多其他类型组成的复杂类型,可能会有很多信息:
```
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
10356 196 212 10764 2a0c cortexm0.elf
```
如果我们不使用 [反射][5],可以通过避免包含类型和结构字段的名称来节省一些字节:
```
$ egc -nf -nt
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
10312 196 212 10720 29e0 cortexm0.elf
```
生成的二进制文件仍然包含一些有关类型的必要信息和关于所有导出方法(带有名称)的完整信息。在运行时,主要是当你将存储在接口变量中的一个值赋值给任何其他变量时,需要此信息来检查可赋值性。
我们还可以通过重新编译所导入的包来删除它们的类型和字段名称:
```
$ cd $HOME/emgo
$ ./clean.sh
$ cd $HOME/firstemgo
$ egc -nf -nt
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
10272 196 212 10680 29b8 cortexm0.elf
```
让我们加载这个程序,看看它是否按预期工作。这一次我们将使用 [st-flash][6] 命令:
```
$ arm-none-eabi-objcopy -O binary cortexm0.elf cortexm0.bin
$ st-flash write cortexm0.bin 0x8000000
st-flash 1.4.0-33-gd76e3c7
2018-04-10T22:04:34 INFO usb.c: -- exit_dfu_mode
2018-04-10T22:04:34 INFO common.c: Loading device parameters....
2018-04-10T22:04:34 INFO common.c: Device connected is: F0 small device, id 0x10006444
2018-04-10T22:04:34 INFO common.c: SRAM size: 0x1000 bytes (4 KiB), Flash: 0x4000 bytes (16 KiB) in pages of 1024 bytes
2018-04-10T22:04:34 INFO common.c: Attempting to write 10468 (0x28e4) bytes to stm32 address: 134217728 (0x8000000)
Flash page at addr: 0x08002800 erased
2018-04-10T22:04:34 INFO common.c: Finished erasing 11 pages of 1024 (0x400) bytes
2018-04-10T22:04:34 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL core id
2018-04-10T22:04:34 INFO flash_loader.c: Successfully loaded flash loader in sram
11/11 pages written
2018-04-10T22:04:35 INFO common.c: Starting verification of write complete
2018-04-10T22:04:35 INFO common.c: Flash written and verified! jolly good!
```
我没有将 NRST 信号连接到编程器,因此无法使用 `-reset` 选项,必须按下复位按钮才能运行程序。
![Interfaces](https://ziutek.github.io/images/mcu/f030-demo-board/interfaces.png)
看来,`st-flash` 与此板配合使用有点不可靠(通常需要复位 ST-LINK 加密狗)。此外,当前版本不会通过 SWD 发出复位命令(仅使用 NRST 信号)。软件复位是不现实的,但是它通常是有效的,缺少它会将会带来不便。对于<ruby>板卡程序员<rt>board-programmer</rt></ruby> 来说 OpenOCD 工作得更好。
### UART
UART<ruby>通用异步收发传输器<rt>Universal Aynchronous Receiver-Transmitter</rt></ruby>)仍然是当今微控制器最重要的外设之一。它的优点是以下属性的独特组合:
* 相对较高的速度,
* 仅两条信号线(在 <ruby>半双工<rt>half-duplex</rt></ruby> 通信的情况下甚至一条),
* 角色对称,
* 关于新数据的 <ruby>同步带内信令<rt>synchronous in-band signaling</rt></ruby>(起始位),
* 在传输 <ruby><rt>words</rt></ruby> 内的精确计时。
这使得最初用于传输由 7-9 位的字组成的异步消息的 UART也被用于有效地实现各种其他物理协议例如被 [WS28xx LEDs][7] 或 [1-wire][8] 设备使用的协议。
但是,我们将以其通常的角色使用 UART从程序中打印文本消息。
```
package main
import (
"io"
"rtos"
"stm32/hal/dma"
"stm32/hal/gpio"
"stm32/hal/irq"
"stm32/hal/system"
"stm32/hal/system/timer/systick"
"stm32/hal/usart"
)
var tts *usart.Driver
func init() {
system.SetupPLL(8, 1, 48/8)
systick.Setup(2e6)
gpio.A.EnableClock(true)
tx := gpio.A.Pin(9)
tx.Setup(&gpio.Config{Mode: gpio.Alt})
tx.SetAltFunc(gpio.USART1_AF1)
d := dma.DMA1
d.EnableClock(true)
tts = usart.NewDriver(usart.USART1, d.Channel(2, 0), nil, nil)
tts.Periph().EnableClock(true)
tts.Periph().SetBaudRate(115200)
tts.Periph().Enable()
tts.EnableTx()
rtos.IRQ(irq.USART1).Enable()
rtos.IRQ(irq.DMA1_Channel2_3).Enable()
}
func main() {
io.WriteString(tts, "Hello, World!\r\n")
}
func ttsISR() {
tts.ISR()
}
func ttsDMAISR() {
tts.TxDMAISR()
}
//c:__attribute__((section(".ISRs")))
var ISRs = [...]func(){
irq.USART1: ttsISR,
irq.DMA1_Channel2_3: ttsDMAISR,
}
```
你会发现此代码可能有些复杂,但目前 STM32 HAL 中没有更简单的 UART 驱动程序(在某些情况下,简单的轮询驱动程序可能会很有用)。 `usart.Driver` 是使用 DMA 和中断来减轻 CPU 负担的高效驱动程序。
STM32 USART 外设提供传统的 UART 及其同步版本。要将其用作输出,我们必须将其 Tx 信号连接到正确的 GPIO 引脚:
```
tx.Setup(&gpio.Config{Mode: gpio.Alt})
tx.SetAltFunc(gpio.USART1_AF1)
```
在 Tx-only 模式下配置 `usart.Driver` rxdma 和 rxbuf 设置为 nil
```
tts = usart.NewDriver(usart.USART1, d.Channel(2, 0), nil, nil)
```
我们使用它的 `WriteString` 方法来打印这句名言。让我们清理所有内容并编译该程序:
```
$ cd $HOME/emgo
$ ./clean.sh
$ cd $HOME/firstemgo
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
12728 236 176 13140 3354 cortexm0.elf
```
要查看某些内容,你需要在 PC 中使用 UART 外设。
**请勿使用 RS232 端口或 USB 转 RS232 转换器!**
STM32 系列使用 3.3V 逻辑,但是 RS232 可以产生 -15 V ~ +15 V 的电压,这可能会损坏你的 MCU。你需要使用 3.3V 逻辑的 USB 转 UART 转换器。流行的转换器基于 FT232 或 CP2102 芯片。
![UART](https://ziutek.github.io/images/mcu/f030-demo-board/uart.jpg)
你还需要一些终端仿真程序(我更喜欢 [picocom][9])。刷新新图像,运行终端仿真器,然后按几次复位按钮:
```
$ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; reset run; exit'
Open On-Chip Debugger 0.10.0+dev-00319-g8f1f912a (2018-03-07-19:20)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
debug_level: 0
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
adapter speed: 950 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x080016f4 msp: 0x20000a20
adapter speed: 4000 kHz
** Programming Started **
auto erase enabled
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20000a20
wrote 13312 bytes from file cortexm0.elf in 1.020185s (12.743 KiB/s)
** Programming Finished **
adapter speed: 950 kHz
$
$ picocom -b 115200 /dev/ttyUSB0
picocom v3.1
port is : /dev/ttyUSB0
flowcontrol : none
baudrate is : 115200
parity is : none
databits are : 8
stopbits are : 1
escape is : C-a
local echo is : no
noinit is : no
noreset is : no
hangup is : no
nolock is : no
send_cmd is : sz -vv
receive_cmd is : rz -vv -E
imap is :
omap is :
emap is : crcrlf,delbs,
logfile is : none
initstring : none
exit_after is : not set
exit is : no
Type [C-a] [C-h] to see available commands
Terminal ready
Hello, World!
Hello, World!
Hello, World!
```
每次按下复位按钮都会产生新的 “HelloWorld”行。一切都在按预期进行。
要查看此 MCU 的 <ruby>双向<rt>bi-directional</rt></ruby> UART 代码,请查看 [此示例][10]。
### io.Writer 接口
`io.Writer` 接口可能是 Go 中第二种最常用的接口类型,仅次于 `error` 接口。其定义如下所示:
```
type Writer interface {
Write(p []byte) (n int, err error)
}
```
`usart.Driver` 实现了 `io.Writer`,因此我们可以替换:
```
tts.WriteString("Hello, World!\r\n")
```
```
io.WriteString(tts, "Hello, World!\r\n")
```
此外,你需要将 `io` 包添加到 `import` 部分。
`io.WriteString` 函数的声明如下所示:
```
func WriteString(w Writer, s string) (n int, err error)
```
如你所见,`io.WriteString` 允许使用实现了 `io.Writer` 接口的任何类型来编写字符串。在内部,它检查基础类型是否具有 `WriteString` 方法,并使用该方法代替 `Write`(如果可用)。
让我们编译修改后的程序:
```
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
15456 320 248 16024 3e98 cortexm0.elf
```
如你所见,`io.WriteString` 导致二进制文件的大小显着增加15776-12964 = 2812 字节。 Flash 上没有太多空间了。是什么引起了这么大规模的增长?
使用这个命令:
```
arm-none-eabi-nm --print-size --size-sort --radix=d cortexm0.elf
```
我们可以打印两种情况下按其大小排序的所有符号。通过过滤和分析获得的数据(`awk``diff`),我们可以找到大约 80 个新符号。最大的十个如下所示:
```
> 00000062 T stm32$hal$usart$Driver$DisableRx
> 00000072 T stm32$hal$usart$Driver$RxDMAISR
> 00000076 T internal$Type$Implements
> 00000080 T stm32$hal$usart$Driver$EnableRx
> 00000084 t errors$New
> 00000096 R $8$stm32$hal$usart$Driver$$
> 00000100 T stm32$hal$usart$Error$Error
> 00000360 T io$WriteString
> 00000660 T stm32$hal$usart$Driver$Read
```
因此,即使我们不使用 `usart.Driver.Read` 方法,但它被编译进来了,与 `DisableRx`、`RxDMAISR`、`EnableRx` 以及上面未提及的其他方法一样。不幸的是,如果你为接口赋值了一些内容,就需要它的完整方法集(包含所有依赖项)。对于使用大多数方法的大型程序来说,这不是问题。但是对于我们这种极简的情况而言,这是一个巨大的负担。
我们已经接近 MCU 的极限,但让我们尝试打印一些数字(你需要在 `import` 部分中用 `strconv` 替换 `io` 包):
```
func main() {
a := 12
b := -123
tts.WriteString("a = ")
strconv.WriteInt(tts, a, 10, 0, 0)
tts.WriteString("\r\n")
tts.WriteString("b = ")
strconv.WriteInt(tts, b, 10, 0, 0)
tts.WriteString("\r\n")
tts.WriteString("hex(a) = ")
strconv.WriteInt(tts, a, 16, 0, 0)
tts.WriteString("\r\n")
tts.WriteString("hex(b) = ")
strconv.WriteInt(tts, b, 16, 0, 0)
tts.WriteString("\r\n")
}
```
与使用 `io.WriteString` 函数的情况一样,`strconv.WriteInt` 的第一个参数的类型为 `io.Writer`
```
$ egc
/usr/local/arm/bin/arm-none-eabi-ld: /home/michal/firstemgo/cortexm0.elf section `.rodata' will not fit in region `Flash'
/usr/local/arm/bin/arm-none-eabi-ld: region `Flash' overflowed by 692 bytes
exit status 1
```
这一次我们的空间超出的不多。让我们试着精简一下有关类型的信息:
```
$ cd $HOME/emgo
$ ./clean.sh
$ cd $HOME/firstemgo
$ egc -nf -nt
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
15876 316 320 16512 4080 cortexm0.elf
```
很接近,但很合适。让我们加载并运行此代码:
```
a = 12
b = -123
hex(a) = c
hex(b) = -7b
```
Emgo 中的 `strconv` 包与 Go 中的原型有很大的不同。它旨在直接用于写入格式化的数字,并且在许多情况下可以替换沉重的 `fmt` 包。 这就是为什么函数名称以 `Write` 而不是 `Format` 开头,并具有额外的两个参数的原因。 以下是其用法示例:
```
func main() {
b := -123
strconv.WriteInt(tts, b, 10, 0, 0)
tts.WriteString("\r\n")
strconv.WriteInt(tts, b, 10, 6, ' ')
tts.WriteString("\r\n")
strconv.WriteInt(tts, b, 10, 6, '0')
tts.WriteString("\r\n")
strconv.WriteInt(tts, b, 10, 6, '.')
tts.WriteString("\r\n")
strconv.WriteInt(tts, b, 10, -6, ' ')
tts.WriteString("\r\n")
strconv.WriteInt(tts, b, 10, -6, '0')
tts.WriteString("\r\n")
strconv.WriteInt(tts, b, 10, -6, '.')
tts.WriteString("\r\n")
}
```
下面是它的输出:
```
-123
-123
-00123
..-123
-123
-123
-123..
```
### Unix 流 和 <ruby>莫尔斯电码<rt>Morse code</rt></ruby>
由于大多数写入的函数都使用 `io.Writer` 而不是具体类型(例如 C 中的 `FILE` ),因此我们获得了类似于 Unix <ruby><rt>stream</rt></ruby> 的功能。在 Unix 中,我们可以轻松地组合简单的命令来执行更大的任务。例如,我们可以通过以下方式将文本写入文件:
```
echo "Hello, World!" > file.txt
```
`>` 操作符将前面命令的输出流写入文件。还有 `|` 操作符,用于连接相邻命令的输出流和输入流。
多亏了流,我们可以轻松地转换/过滤任何命令的输出。例如,要将所有字母转换为大写,我们可以通过 `tr` 命令过滤 `echo` 的输出:
```
echo "Hello, World!" | tr a-z A-Z > file.txt
```
为了显示 `io.Writer` 和 Unix 流之间的类比,让我们编写以下代码:
```
io.WriteString(tts, "Hello, World!\r\n")
```
采用以下伪 unix 形式:
```
io.WriteString "Hello, World!" | usart.Driver usart.USART1
```
下一个示例将显示如何执行此操作:
```
io.WriteString "Hello, World!" | MorseWriter | usart.Driver usart.USART1
```
让我们来创建一个简单的编码器,它使用莫尔斯电码对写入的文本进行编码:
```
type MorseWriter struct {
W io.Writer
}
func (w *MorseWriter) Write(s []byte) (int, error) {
var buf [8]byte
for n, c := range s {
switch {
case c == '\n':
c = ' ' // Replace new lines with spaces.
case 'a' <= c && c <= 'z':
c -= 'a' - 'A' // Convert to upper case.
}
if c < ' ' || 'Z' < c {
continue // c is outside ASCII [' ', 'Z']
}
var symbol morseSymbol
if c == ' ' {
symbol.length = 1
buf[0] = ' '
} else {
symbol = morseSymbols[c-'!']
for i := uint(0); i < uint(symbol.length); i++ {
if (symbol.code>>i)&1 != 0 {
buf[i] = '-'
} else {
buf[i] = '.'
}
}
}
buf[symbol.length] = ' '
if _, err := w.W.Write(buf[:symbol.length+1]); err != nil {
return n, err
}
}
return len(s), nil
}
type morseSymbol struct {
code, length byte
}
//emgo:const
var morseSymbols = [...]morseSymbol{
{1<<0 | 1<<1 | 1<<2, 4}, // ! ---.
{1<<1 | 1<<4, 6}, // " .-..-.
{}, // #
{1<<3 | 1<<6, 7}, // $ ...-..-
// Some code omitted...
{1<<0 | 1<<3, 4}, // X -..-
{1<<0 | 1<<2 | 1<<3, 4}, // Y -.--
{1<<0 | 1<<1, 4}, // Z --..
}
```
你可以在 [这里][11] 找到完整的 `morseSymbols` 数组。 `//emgo:const` 指令确保 `morseSymbols` 数组不会被复制到 RAM 中。
现在我们可以通过两种方式打印句子:
```
func main() {
s := "Hello, World!\r\n"
mw := &MorseWriter{tts}
io.WriteString(tts, s)
io.WriteString(mw, s)
}
```
我们使用指向 `MorseWriter` `&MorseWriter{tts}` 的指针而不是简单的 `MorseWriter{tts}` 值,因为 `MorseWriter` 太大,不适合接口变量。
与 Go 不同Emgo 不会为存储在接口变量中的值动态分配内存。接口类型的大小受限制,相当于三个指针(适合 `slice` )或两个 `float64`(适合 `complex128`)的大小,以较大者为准。它可以直接存储所有基本类型和小型 “结构体/数组” 的值,但是对于较大的值,你必须使用指针。
让我们编译此代码并查看其输出:
```
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
15152 324 248 15724 3d6c cortexm0.elf
```
```
Hello, World!
.... . .-.. .-.. --- --..-- .-- --- .-. .-.. -.. ---.
```
### 终极闪烁
Blinky 是等效于 “HelloWorld” 程序的硬件。一旦有了摩尔斯编码器,我们就可以轻松地将两者结合起来以获得终极闪烁程序:
```
package main
import (
"delay"
"io"
"stm32/hal/gpio"
"stm32/hal/system"
"stm32/hal/system/timer/systick"
)
var led gpio.Pin
func init() {
system.SetupPLL(8, 1, 48/8)
systick.Setup(2e6)
gpio.A.EnableClock(false)
led = gpio.A.Pin(4)
cfg := gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain, Speed: gpio.Low}
led.Setup(&cfg)
}
type Telegraph struct {
Pin gpio.Pin
Dotms int // Dot length [ms]
}
func (t Telegraph) Write(s []byte) (int, error) {
for _, c := range s {
switch c {
case '.':
t.Pin.Clear()
delay.Millisec(t.Dotms)
t.Pin.Set()
delay.Millisec(t.Dotms)
case '-':
t.Pin.Clear()
delay.Millisec(3 * t.Dotms)
t.Pin.Set()
delay.Millisec(t.Dotms)
case ' ':
delay.Millisec(3 * t.Dotms)
}
}
return len(s), nil
}
func main() {
telegraph := &MorseWriter{Telegraph{led, 100}}
for {
io.WriteString(telegraph, "Hello, World! ")
}
}
// Some code omitted...
```
在上面的示例中,我省略了 `MorseWriter` 类型的定义,因为它已在前面展示过。完整版可通过 [这里][12] 获取。让我们编译它并运行:
```
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
11772 244 244 12260 2fe4 cortexm0.elf
```
![Ultimate Blinky](https://ziutek.github.io/images/mcu/f030-demo-board/morse.png)
### 反射
是的Emgo 支持 [反射][13]。`reflect` 包尚未完成,但是已完成的部分足以实现 `fmt.Print` 函数族了。来看看我们可以在小型 MCU 上做什么。
为了减少内存使用,我们将使用 <ruby>[半主机][14]<rt>semihosting</rt></ruby> 作为标准输出。为了方便起见,我们还编写了简单的 `println` 函数,它在某种程度上类似于 `fmt.Println`
```
package main
import (
"debug/semihosting"
"reflect"
"strconv"
"stm32/hal/system"
"stm32/hal/system/timer/systick"
)
var stdout semihosting.File
func init() {
system.SetupPLL(8, 1, 48/8)
systick.Setup(2e6)
var err error
stdout, err = semihosting.OpenFile(":tt", semihosting.W)
for err != nil {
}
}
type stringer interface {
String() string
}
func println(args ...interface{}) {
for i, a := range args {
if i > 0 {
stdout.WriteString(" ")
}
switch v := a.(type) {
case string:
stdout.WriteString(v)
case int:
strconv.WriteInt(stdout, v, 10, 0, 0)
case bool:
strconv.WriteBool(stdout, v, 't', 0, 0)
case stringer:
stdout.WriteString(v.String())
default:
stdout.WriteString("%unknown")
}
}
stdout.WriteString("\r\n")
}
type S struct {
A int
B bool
}
func main() {
p := &S{-123, true}
v := reflect.ValueOf(p)
println("kind(p) =", v.Kind())
println("kind(*p) =", v.Elem().Kind())
println("type(*p) =", v.Elem().Type())
v = v.Elem()
println("*p = {")
for i := 0; i < v.NumField(); i++ {
ft := v.Type().Field(i)
fv := v.Field(i)
println(" ", ft.Name(), ":", fv.Interface())
}
println("}")
}
```
`semihosting.OpenFile` 函数允许在主机端打开/创建文件。特殊路径 `:tt` 对应于主机的标准输出。
`println` 函数接受任意数量的参数,每个参数的类型都是任意的:
```
func println(args ...interface{})
```
可能是因为任何类型都实现了空接口 `interface{}``println` 使用 [类型开关][15] 打印字符串,整数和布尔值:
```
switch v := a.(type) {
case string:
stdout.WriteString(v)
case int:
strconv.WriteInt(stdout, v, 10, 0, 0)
case bool:
strconv.WriteBool(stdout, v, 't', 0, 0)
case stringer:
stdout.WriteString(v.String())
default:
stdout.WriteString("%unknown")
}
```
此外,它还支持任何实现了 `stringer` 接口的类型,即任何具有 `String()` 方法的类型。在任何 `case` 子句中,`v` 变量具有正确的类型,与 `case` 关键字后列出的类型相同。
`reflect.ValueOf(p)` 函数通过允许以编程的方式分析其类型和内容的形式返回 `p`。如你所见,我们甚至可以使用 `v.Elem()` 取消引用指针,并打印所有结构体及其名称。
让我们尝试编译这段代码。现在让我们看看如果编译时没有类型和字段名,会有什么结果:
```
$ egc -nt -nf
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
16028 216 312 16556 40ac cortexm0.elf
```
闪存上只剩下 140 个可用字节。让我们使用启用了半主机的 OpenOCD 加载它:
```
$ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; arm semihosting enable; reset run'
Open On-Chip Debugger 0.10.0+dev-00319-g8f1f912a (2018-03-07-19:20)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
debug_level: 0
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
adapter speed: 950 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x08002338 msp: 0x20000a20
adapter speed: 4000 kHz
** Programming Started **
auto erase enabled
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20000a20
wrote 16384 bytes from file cortexm0.elf in 0.700133s (22.853 KiB/s)
** Programming Finished **
semihosting is enabled
adapter speed: 950 kHz
kind(p) = ptr
kind(*p) = struct
type(*p) =
*p = {
X. : -123
X. : true
}
```
如果你实际运行此代码,则会注意到半主机运行缓慢,尤其是在逐字节写入时(缓冲很有用)。
如你所见,`*p` 没有类型名称,并且所有结构字段都具有相同的 `X.` 名称。让我们再次编译该程序,这次不带 `-nt -nf` 选项:
```
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
16052 216 312 16580 40c4 cortexm0.elf
```
现在已经包括了类型和字段名称,但仅在 ~~_main.go_ 文件中~~ `main` 包中定义了它们。该程序的输出如下所示:
```
kind(p) = ptr
kind(*p) = struct
type(*p) = S
*p = {
A : -123
B : true
}
```
反射是任何易于使用的序列化库的关键部分,而像 [JSON][16] 这样的序列化 ~~算法~~<ruby>物联网<rt>IoT</rt></ruby>时代也越来越重要。
这些就是我完成的本文的第二部分。我认为有机会进行第三部分,更具娱乐性的部分,在那里我们将各种有趣的设备连接到这块板上。如果这块板装不下,我们就换一块大一点的。
--------------------------------------------------------------------------------
via: https://ziutek.github.io/2018/04/14/go_on_very_small_hardware2.html
作者:[Michał Derkacz][a]
译者:[gxlct008](https://github.com/gxlct008)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://ziutek.github.io/
[1]:https://ziutek.github.io/2018/04/14/go_on_very_small_hardware2.html
[2]:https://linux.cn/article-11383-1.html
[3]:https://golang.org/doc/effective_go.html#interfaces
[4]:https://research.swtch.com/interfaces
[5]:https://blog.golang.org/laws-of-reflection
[6]:https://github.com/texane/stlink
[7]:http://www.world-semi.com/solution/list-4-1.html
[8]:https://en.wikipedia.org/wiki/1-Wire
[9]:https://github.com/npat-efault/picocom
[10]:https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/examples/f030-demo-board/usart/main.go
[11]:https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/examples/f030-demo-board/morseuart/main.go
[12]:https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/examples/f030-demo-board/morseled/main.go
[13]:https://blog.golang.org/laws-of-reflection
[14]:http://infocenter.arm.com/help/topic/com.arm.doc.dui0471g/Bgbjjgij.html
[15]:https://golang.org/doc/effective_go.html#type_switch
[16]:https://en.wikipedia.org/wiki/JSON

View File

@ -1,8 +1,8 @@
[#]: collector: (lujun9972)
[#]: translator: (gxlct008)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12722-1.html)
[#]: subject: (Building a Messenger App: Home Page)
[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-home-page/)
[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
@ -10,6 +10,8 @@
构建一个即时消息应用Home 页面
======
![](https://img.linux.net.cn/data/attachment/album/202010/15/213116evlwzdwwv66kmldj.jpg)
本文是该系列的第八篇。
* [第一篇: 模式][1]
@ -20,8 +22,7 @@
* [第六篇: 仅用于开发的登录][6]
* [第七篇: Access 页面][7]
继续前端部分,让我们在本文中完成 Home 页面的开发。 我们将添加一个开始对话的表单和一个包含最新对话的列表。
继续前端部分,让我们在本文中完成 `home` 页面的开发。 我们将添加一个开始对话的表单和一个包含最新对话的列表。
### 对话表单
@ -35,7 +36,7 @@
</form>
```
将该表单添加到我们显示 auth user 和 logout 按钮部分的下方。
将该表单添加到我们显示 auth userlogout 按钮部分的下方。
```js
page.getElementById('conversation-form').onsubmit = onConversationSubmit
@ -78,7 +79,7 @@ function createConversation(username) {
}
```
在提交时,我们使用用户名对 `/api/conversations` 进行 POST 请求,并重定向到 conversation 页面 (用于下一篇文章)
在提交时,我们使用用户名对 `/api/conversations` 进行 POST 请求,并重定向到 `conversation` 页面(用于下一篇文章)
### 对话列表
@ -166,8 +167,7 @@ export function escapeHTML(str) {
<script>alert('lololo')</script>
```
这将非常烦人,因为该脚本将被执行😅。
所以,永远记住要转义来自不可信来源的内容。
这将非常烦人,因为该脚本将被执行😅。所以,永远记住要转义来自不可信来源的内容。
### 消息订阅
@ -227,7 +227,7 @@ function getConversation(id) {
以上这些涵盖了主页的所有内容 😊。
在下一篇文章中,我们将对 conversation 页面进行编码。
[Souce Code][10]
- [源代码][10]
--------------------------------------------------------------------------------
@ -235,20 +235,20 @@ via: https://nicolasparada.netlify.com/posts/go-messenger-home-page/
作者:[Nicolás Parada][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/gxlct008)
校对:[校对者ID](https://github.com/校对者ID)
译者:[gxlct008](https://github.com/gxlct008)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://nicolasparada.netlify.com/
[b]: https://github.com/lujun9972
[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
[3]: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
[4]: https://nicolasparada.netlify.com/posts/go-messenger-messages/
[5]: https://nicolasparada.netlify.com/posts/go-messenger-realtime-messages/
[6]: https://nicolasparada.netlify.com/posts/go-messenger-dev-login/
[7]: https://nicolasparada.netlify.com/posts/go-messenger-access-page/
[1]: https://linux.cn/article-11396-1.html
[2]: https://linux.cn/article-11510-1.html
[3]: https://linux.cn/article-12056-1.html
[4]: https://linux.cn/article-12680-1.html
[5]: https://linux.cn/article-12685-1.html
[6]: https://linux.cn/article-12692-1.html
[7]: https://linux.cn/article-12704-1.html
[8]: https://nicolasparada.netlify.com/img/go-messenger-home-page/conversation-form.png
[9]: https://nicolasparada.netlify.com/img/go-messenger-home-page/conversation-list.png
[10]: https://github.com/nicolasparada/go-messenger-demo

View File

@ -1,8 +1,8 @@
[#]: collector: (lujun9972)
[#]: translator: (gxlct008)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12723-1.html)
[#]: subject: (Building a Messenger App: Conversation Page)
[#]: via: (https://nicolasparada.netlify.com/posts/go-messenger-conversation-page/)
[#]: author: (Nicolás Parada https://nicolasparada.netlify.com/)
@ -10,6 +10,8 @@
构建一个即时消息应用Conversation 页面
======
![](https://img.linux.net.cn/data/attachment/album/202010/15/220239arr978u7t7oulv73.jpg)
本文是该系列的第九篇,也是最后一篇。
* [第一篇: 模式][1]
@ -21,8 +23,6 @@
* [第七篇: Access 页面][7]
* [第八篇: Home 页面][8]
在这篇文章中,我们将对<ruby>对话<rt>conversation</rt></ruby>页面进行编码。此页面是两个用户之间的聊天室。在顶部我们将显示其他参与者的信息,下面接着的是最新消息列表,以及底部的消息表单。
### 聊天标题
@ -230,16 +230,15 @@ function readMessages(conversationID) {
}
```
在这里我们仍然使用 partial application 来获取会话 ID。
当新消息到达时,我们首先检查它是否来自此对话。如果是,我们会将消息条目预先添加到列表中,并向`/api/conversations/{conversationID}/read_messages`发起 POST 一个请求,以更新参与者上次阅读消息的时间。
在这里我们仍然使用这个应用的部分来获取会话 ID。
当新消息到达时,我们首先检查它是否来自此对话。如果是,我们会将消息条目预先添加到列表中,并向 `/api/conversations/{conversationID}/read_messages` 发起 POST 一个请求,以更新参与者上次阅读消息的时间。
* * *
本系列到此结束。 Messenger app 现在可以运行了。
本系列到此结束。 消息应用现在可以运行了。
~~我将在对话和消息列表中添加分页功能,并在共享源代码之前添加用户搜索。我会在准备好的时候和<ruby>托管的演示<rt>a hosted demo</rt></ruby>👨‍💻一起更新它~~
[Souce Code][13] • [Demo][14]
- [源代码][13]
- [演示][14]
--------------------------------------------------------------------------------
@ -248,20 +247,20 @@ via: https://nicolasparada.netlify.com/posts/go-messenger-conversation-page/
作者:[Nicolás Parada][a]
选题:[lujun9972][b]
译者:[gxlct008](https://github.com/gxlct008)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://nicolasparada.netlify.com/
[b]: https://github.com/lujun9972
[1]: https://nicolasparada.netlify.com/posts/go-messenger-schema/
[2]: https://nicolasparada.netlify.com/posts/go-messenger-oauth/
[3]: https://nicolasparada.netlify.com/posts/go-messenger-conversations/
[4]: https://nicolasparada.netlify.com/posts/go-messenger-messages/
[5]: https://nicolasparada.netlify.com/posts/go-messenger-realtime-messages/
[6]: https://nicolasparada.netlify.com/posts/go-messenger-dev-login/
[7]: https://nicolasparada.netlify.com/posts/go-messenger-access-page/
[8]: https://nicolasparada.netlify.com/posts/go-messenger-home-page/
[1]: https://linux.cn/article-11396-1.html
[2]: https://linux.cn/article-11510-1.html
[3]: https://linux.cn/article-12056-1.html
[4]: https://linux.cn/article-12680-1.html
[5]: https://linux.cn/article-12685-1.html
[6]: https://linux.cn/article-12692-1.html
[7]: https://linux.cn/article-12704-1.html
[8]: https://linux.cn/article-12722-1.html
[9]: https://nicolasparada.netlify.com/img/go-messenger-conversation-page/heading.png
[10]: https://nicolasparada.netlify.com/img/go-messenger-conversation-page/list.png
[11]: https://nicolasparada.netlify.com/img/go-messenger-conversation-page/form.png

View File

@ -0,0 +1,273 @@
[#]: collector: (lujun9972)
[#]: translator: (gxlct008)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12737-1.html)
[#]: subject: (Using Yarn on Ubuntu and Other Linux Distributions)
[#]: via: (https://itsfoss.com/install-yarn-ubuntu)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
在 Ubuntu 和其他 Linux 发行版上使用 Yarn
======
> 本速成教程向你展示了在 Ubuntu 和 Debian Linux 上安装 Yarn 包管理器的官方方法。你还将学习到一些基本的 Yarn 命令以及彻底删除 Yarn 的步骤。
[Yarn][1] 是 Facebook 开发的开源 JavaScript 包管理器。它是流行的 npm 包管理器的一个替代品,或者应该说是改进。 [Facebook 开发团队][2] 创建 Yarn 是为了克服 [npm][3] 的缺点。 Facebook 声称 Yarn 比 npm 更快、更可靠、更安全。
与 npm 一样Yarn 为你提供一种自动安装、更新、配置和删除从全局注册库中检索到的程序包的方法。
Yarn 的优点是它更快因为它可以缓存已下载的每个包所以无需再次下载。它还将操作并行化以最大化资源利用率。在执行每个已安装的包代码之前Yarn 还使用 [校验和来验证完整性][4]。 Yarn 还保证可以在一个系统上运行的安装,在任何其他系统上都会以完全相同地方式工作。
如果你正 [在 Ubuntu 上使用 node.js][5],那么你的系统上可能已经安装了 npm。在这种情况下你可以使用 npm 通过以下方式全局安装 Yarn
```
sudo npm install yarn -g
```
不过,我推荐使用官方方式在 Ubuntu/Debian 上安装 Yarn。
### 在 Ubuntu 和 Debian 上安装 Yarn [官方方式]
![Yarn JS][6]
这里提到的说明应该适用于所有版本的 Ubuntu例如 Ubuntu 18.04、16.04 等。同样的一组说明也适用于 Debian 和其他基于 Debian 的发行版。
由于本教程使用 `curl` 来添加 Yarn 项目的 GPG 密钥,所以最好验证一下你是否已经安装了 `curl`
```
sudo apt install curl
```
如果 `curl` 尚未安装,则上面的命令将安装它。既然有了 `curl`,你就可以使用它以如下方式添加 Yarn 项目的 GPG 密钥:
```
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
```
在此之后,将存储库添加到源列表中,以便将来可以轻松地升级 Yarn 包,并进行其余系统更新:
```
sudo sh -c 'echo "deb https://dl.yarnpkg.com/debian/ stable main" >> /etc/apt/sources.list.d/yarn.list'
```
你现在可以继续了。[更新 Ubuntu][7] 或 Debian 系统,以刷新可用软件包列表,然后安装 Yarn
```
sudo apt update
sudo apt install yarn
```
这将一起安装 Yarn 和 node.js。该过程完成后请验证是否已成功安装 Yarn。 你可以通过检查 Yarn 版本来做到这一点。
```
yarn --version
```
对我来说,它显示了这样的输出:
```
yarn --version
1.12.3
```
这意味着我的系统上安装了 Yarn 版本 1.12.3。
### 使用 Yarn
我假设你对 JavaScript 编程以及依赖项的工作原理有一些基本的了解。我在这里不做详细介绍。我将向你展示一些基本的 Yarn 命令,这些命令将帮助你入门。
#### 使用 Yarn 创建一个新项目
`npm` 一样Yarn 也可以使用 `package.json` 文件。在这里添加依赖项。所有依赖包都缓存在项目根目录下的 `node_modules` 目录中。
在项目的根目录中,运行以下命令以生成新的 `package.json` 文件:
它会问你一些问题。你可以按回车键跳过或使用默认值。
```
yarn init
yarn init v1.12.3
question name (test_yarn): test_yarn_proect
question version (1.0.0): 0.1
question description: Test Yarn
question entry point (index.js):
question repository url:
question author: abhishek
question license (MIT):
question private:
success Saved package.json
Done in 82.42s.
```
这样,你就得到了一个如下的 `package.json` 文件:
```
{
"name": "test_yarn_proect",
"version": "0.1",
"description": "Test Yarn",
"main": "index.js",
"author": "abhishek",
"license": "MIT"
}
```
现在你有了 `package.json`,你可以手动编辑它以添加或删除包依赖项,也可以使用 Yarn 命令(首选)。
#### 使用 Yarn 添加依赖项
你可以通过以下方式添加对特定包的依赖关系:
```
yarn add <包名>
```
例如,如果你想在项目中使用 [Lodash][8],则可以使用 Yarn 添加它,如下所示:
```
yarn add lodash
yarn add v1.12.3
info No lockfile found.
[1/4] Resolving packages…
[2/4] Fetching packages…
[3/4] Linking dependencies…
[4/4] Building fresh packages…
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ [email protected]
info All dependencies
└─ [email protected]
Done in 2.67s.
```
你可以看到,此依赖项已自动添加到 `package.json` 文件中:
```
{
"name": "test_yarn_proect",
"version": "0.1",
"description": "Test Yarn",
"main": "index.js",
"author": "abhishek",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.11"
}
}
```
默认情况下Yarn 将在依赖项中添加最新版本的包。如果要使用特定版本,可以在添加时指定。
```
yarn add package@version-or-tag
```
像往常一样,你也可以手动更新 `package.json` 文件。
#### 使用 Yarn 升级依赖项
你可以使用以下命令将特定依赖项升级到其最新版本:
```
yarn upgrade <包名>
```
它将查看所​​涉及的包是否具有较新的版本,并且会相应地对其进行更新。
你还可以通过以下方式更改已添加的依赖项的版本:
```
yarn upgrade package_name@version_or_tag
```
你还可以使用一个命令将项目的所有依赖项升级到它们的最新版本:
```
yarn upgrade
```
它将检查所有依赖项的版本,如果有任何较新的版本,则会更新它们。
#### 使用 Yarn 删除依赖项
你可以通过以下方式从项目的依赖项中删除包:
```
yarn remove <包名>
```
#### 安装所有项目依赖项
如果对你 `project.json` 文件进行了任何更改,则应该运行:
```
yarn
```
或者,
```
yarn install
```
一次安装所有依赖项。
### 如何从 Ubuntu 或 Debian 中删除 Yarn
我将通过介绍从系统中删除 Yarn 的步骤来完成本教程,如果你使用上述步骤安装 Yarn 的话。如果你意识到不再需要 Yarn 了,则可以将它删除。
使用以下命令删除 Yarn 及其依赖项。
```
sudo apt purge yarn
```
你也应该从源列表中把存储库信息一并删除掉:
```
sudo rm /etc/apt/sources.list.d/yarn.list
```
下一步删除已添加到受信任密钥的 GPG 密钥是可选的。但要做到这一点,你需要知道密钥。你可以使用 `apt-key` 命令获得它:
```
Warning: apt-key output should not be parsed (stdout is not a terminal) pub rsa4096 2016-10-05 [SC] 72EC F46A 56B4 AD39 C907 BBB7 1646 B01B 86E5 0310 uid [ unknown] Yarn Packaging yarn@dan.cx sub rsa4096 2016-10-05 [E] sub rsa4096 2019-01-02 [S] [expires: 2020-02-02]
```
这里的密钥是以 `pub` 开始的行中 GPG 密钥指纹的最后 8 个字符。
因此,对于我来说,密钥是 `86E50310`,我将使用以下命令将其删除:
```
sudo apt-key del 86E50310
```
你会在输出中看到 `OK`,并且 Yarn 包的 GPG 密钥将从系统信任的 GPG 密钥列表中删除。
我希望本教程可以帮助你在 Ubuntu、Debian、Linux Mint、 elementary OS 等操作系统上安装 Yarn。 我提供了一些基本的 Yarn 命令,以帮助你入门,并完成了从系统中删除 Yarn 的完整步骤。
希望你喜欢本教程,如果有任何疑问或建议,请随时在下面留言。
--------------------------------------------------------------------------------
via: https://itsfoss.com/install-yarn-ubuntu
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[gxlct008](https://github.com/gxlct008)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://yarnpkg.com/lang/en/
[2]: https://code.fb.com/
[3]: https://www.npmjs.com/
[4]: https://itsfoss.com/checksum-tools-guide-linux/
[5]: https://itsfoss.com/install-nodejs-ubuntu/
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2019/01/yarn-js-ubuntu-debian.jpeg?resize=800%2C450&ssl=1
[7]: https://itsfoss.com/update-ubuntu/
[8]: https://lodash.com/

View File

@ -0,0 +1,59 @@
[#]: collector: (lujun9972)
[#]: translator: (chenmu-kk)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12768-1.html)
[#]: subject: (My first contribution to open source: Making a decision)
[#]: via: (https://opensource.com/article/19/11/my-first-open-source-contribution-mistake-decisions)
[#]: author: (Galen Corey https://opensource.com/users/galenemco)
我的第一次开源贡献:做出决定
======
> 一位新的开源贡献者告诉你如何加入到开源项目中。
![](https://img.linux.net.cn/data/attachment/album/202010/30/112350rh0xwp1x1y6awehn.jpg)
先前,我把我的第一次开源贡献的拖延归咎于[冒牌综合症][2]。但还有一个我无法忽视的因素:我做出决定太艰难了。在[成千上百万][3]的开源项目中选择时,选择一个要做贡献的项目是难以抉择的。如此重负,以至于我常常不得不关掉我的笔记本去思考:“或许我改天再做吧”。
错误之二是让我对做出决定的恐惧妨碍了我做出第一次贡献。在理想世界里,也许开始我的开源之旅时,心中就已经有了一个真正关心和想去做的具体项目,但我有的只是总得为开源项目做出贡献的模糊目标。对于那些处于同一处境的人来说,这儿有一些帮助我挑选出合适的项目(或者至少是一个好的项目)来做贡献的策略。
### 经常使用的工具
一开始,我不认为有必要将自己局限于已经熟悉的工具或项目。有一些项目我之前从未使用过,但由于它们的社区很活跃,或者它们解决的问题很有趣,因此看起来很有吸引力。
但是,考虑我投入到这个项目中的时间有限,我决定继续投入到我了解的工具上去。要了解工具需求,你需要熟悉它的工作方式。如果你想为自己不熟悉的项目做贡献,则需要完成一个额外的步骤来了解代码的功能和目标。这个额外的工作量可能是有趣且值得的,但也会使你的工作时间加倍。因为我的目标主要是贡献,投入到我了解的工具上是缩小范围的很好方式。回馈一个你认为有用的项目也是有意义的。
### 活跃而友好的社区
在选择项目的时候,我希望在那里有人会审查我写的代码才会觉得有信心。当然,我也希望审核我代码的人是个和善的人。毕竟,把你的作品放在那里接受公众监督是很可怕的。虽然我对建设性的反馈持开放态度,但开发者社区中的一些有毒角落是我希望避免的。
为了评估我将要加入的社区,我查看了我正在考虑加入的仓库的<ruby>议题<rt>issue</rt></ruby>部分。我要查看核心团队中是否有人定期回复。更重要的是,我试着确保没有人在评论中互相诋毁(这在议题讨论中是很常见的)。我还留意了那些有行为准则的项目,概述了什么是适当的和不适当的在线互动行为。
### 明确的贡献准则
因为这是我第一次为开源项目做出贡献,在此过程中我有很多问题。一些项目社区在流程的文档记录方面做的很好,可以用来指导挑选其中的议题并发起拉取请求。 [Gatsby][4] 是这种做法的典范,尽管那时我没有选择它们,因为在此之前我从未使用过该产品。
这种清晰的文档帮助我们缓解了一些不知如何去做的不安全感。它也给了我希望:项目对新的贡献者是开放的,并且会花时间来查看我的工作。除了贡献准则外,我还查看了议题部分,看看这个项目是否使用了“<ruby>第一个好议题<rt>good first issue</rt></ruby>”标志。这是该项目对初学者开放的另一个迹象(并可以帮助你学会要做什么)。
### 总结
如果你还没有计划好选择一个项目,那么选择合适的领域进行你的第一个开源贡献更加可行。列出一系列标准可以帮助自己缩减选择范围,并为自己的第一个拉取请求找到一个好的项目。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/11/my-first-open-source-contribution-mistake-decisions
作者:[Galen Corey][a]
选题:[lujun9972][b]
译者:[chenmu-kk](https://github.com/chenmu-kk)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/galenemco
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/lightbulb-idea-think-yearbook-lead.png?itok=5ZpCm0Jh (Lightbulb)
[2]: https://opensource.com/article/19/10/my-first-open-source-contribution-mistakes
[3]: https://github.blog/2018-02-08-open-source-project-trends-for-2018/
[4]: https://www.gatsbyjs.org/contributing/

View File

@ -0,0 +1,171 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12772-1.html)
[#]: subject: (Use the internet from the command line with curl)
[#]: via: (https://opensource.com/article/20/5/curl-cheat-sheet)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
使用 curl 从命令行访问互联网
======
> 下载我们整理的 curl 备忘录。要在不使用图形界面的情况下从互联网上获取所需的信息curl 是一种快速有效的方法。
![](https://img.linux.net.cn/data/attachment/album/202010/31/000543n032ud499yy4d94v.jpg)
`curl` 通常被视作一款非交互式 Web 浏览器,这意味着它能够从互联网上获取信息,并在你的终端中显示,或将其保存到文件中。从表面看,这是 Web 浏览器,类似 Firefox 或 Chromium 所做的工作,只是它们默认情况下会*渲染*信息,而 `curl` 会下载并显示原始信息。实际上,`curl` 命令可以做更多的事情,并且能够使用多种协议与服务器进行双向传输数据,这些协议包括 HTTP、FTP、SFTP、IMAP、POP3、LDAP、SMB、SMTP 等。对于普通终端用户来说,这是一个有用的工具;而对于系统管理员,这非常便捷;对于微服务和云开发人员来说,它是一个质量保证工具。
`curl` 被设计为在没有用户交互的情况下工作,因此与 Firefox 不同,你必须从头到尾考虑与在线数据的交互。例如,如果想要在 Firefox 中查看网页,你需要启动 Firefox 窗口。打开 Firefox 后,在地址栏或搜索引擎中输入要访问的网站。然后,导航到网站,然后单击要查看的页面。
对于 `curl` 来说也是如此,不同之处在于你需要一次执行所有操作:在启动 `curl` 的同时提供需要访问的互联网地址,并告诉它是否要将数据保存在终端或文件中。当你必须与需要身份验证的网站或 API 进行交互时,会变得有点复杂,但是一旦你学习了 `curl` 命令语法,它就会变得自然而然。为了帮助你掌握它,我们在一个方便的[备忘录][2]中收集了相关的语法信息。
### 使用 curl 下载文件
你可以通过提供指向特定 URL 的链接来使用 `curl` 命令下载文件。如果你提供的 URL 默认为 `index.html`,那么将下载此页面,并将下载的文件显示在终端屏幕上。你可以将数据通过管道传递到 `less`、`tail` 或任何其它命令:
```
$ curl "http://example.com" | tail -n 4
<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 information...</a></p>
</div></body></html>
```
由于某些 URL 包含特殊字符shell 通常会将其解释,因此最安全的做法用引号将 URL 包起来。
某些文件无法很好的在终端中转换显示。你可以使用 `--remote-name` 选项使文件根据服务器上的命名进行保存:
```
$ curl --remote-name "https://example.com/linux-distro.iso"
$ ls
linux-distro.iso
```
或者,你可以使用 `--output` 选项来命名你想要下载的内容:
```
curl "http://example.com/foo.html" --output bar.html
```
### 使用 curl 列出带有远程目录的内容
因为 `curl` 不是交互式的,所以很难浏览页面上的可下载元素。如果你要连接的远程服务器允许,可以使用 `curl` 来列出目录的内容:
```
$ curl --list-only "https://example.com/foo/"
```
### 继续中断下载
如果你正在下载一个非常大的文件,你可能会发现有时候必须中断下载。`curl` 非常智能,可以确定下载从何处中断并继续下载。这意味着,下一次当你下载一个 4GB 的 Linux 发行版的 ISO 出现问题时,就不必重新开始了。`--continue-at` 的语法有点不寻常:如果你知道下载中断时的字节数,你可以提供给 `curl`;否则,你可以使用单独的一个破折号(`-`)指示 curl 自动检测:
```
$ curl --remote-name --continue-at - "https://example.com/linux-distro.iso"
```
### 下载文件序列
如果你需要下载多个文件而不是一个大文件,那么 `curl` 可以帮助你解决这个问题。假设你知道要下载的文件的位置和文件名模式,则可以使用 `curl` 的序列标记:中括号里是整数范围的起点和终点。对于输出文件名,使用 `#1` 表示第一个变量:
```
$ curl "https://example.com/file_[1-4].webp" --output "file_#1.webp"
```
如果你需要使用其它变量来表示另一个序列,按照每个变量在命令中出现的顺序表示它们。例如,在这个命令中,`#1` 指目录 `images_000``images_009`,而 `#2` 指目录 `file_1.webp``file_4.webp`
```
$ curl "https://example.com/images_00[0-9]/file_[1-4].webp" --output "file_#1-#2.webp"
```
### 从站点下载所有 PNG 文件
你也可以仅使用 `curl``grep` 进行一些基本的 Web 抓取操作,以找到想要下载的内容。例如,假设你需要下载与正在归档网页关联的所有图像,首先,下载引用了图像的页面。将页面内通过管道传输到 `grep`,搜索所需的图片类型(在此示例中为 PNG。最后创建一个 `while` 循环来构造下载 URL并将文件保存到你的计算机
```
$ curl https://example.com |\
grep --only-matching 'src="[^"]*.[png]"' |\
cut -d\" -f2 |\
while read i; do \
curl https://example.com/"${i}" -o "${i##*/}"; \
done
```
这只是一个示例,但它展示了 `curl` 与 Unix 管道和一些基本而巧妙的解析结合使用时是多么的灵活。
### 获取 HTML 头
用于数据交换的协议在计算机发送通信的数据包中嵌入了大量元数据。HTTP 头是数据初始部分的组件。在连接一个网站出现问题时,查看这些报文头(尤其是响应码)会有所帮助:
```
curl --head "https://example.com"
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
```
### 快速失败
响应 200 通常是 HTTP 成功指示符,这是你与服务器连接时通常期望的结果。著名的 404 响应表示找不到页面,而 500 则表示服务器在处理请求时出现了错误。
要查看协商过程中发生了什么错误,添加 `--show-error` 选项:
```
$ curl --head --show-error "http://opensource.ga"
```
除非你可以访问要连接的服务器,否则这些问题将很难解决,但是 `curl` 通常会尽力连接你指定的地址。有时在网络上进行测试时,无休止的重试似乎只会浪费时间,因此你可以使用 `--fail-early` 选项来强制 `curl` 在失败时迅速退出:
```
curl --fail-early "http://opensource.ga"
```
### 由 3xx 响应指定的重定向查询
300 这个系列的响应更加灵活。具体来说301 响应意味着一个 URL 已被永久移动到其它位置。对于网站管理员来说,重新定位内容并留下“痕迹”是一种常见的方式,这样访问旧地址的人们仍然可以找到它。默认情况下,`curl` 不会进行 301 重定向,但你可以使用 `--localtion` 选项使其继续进入 301 响应指向的目标:
```
$ curl "https://iana.org" | grep title
<title>301 Moved Permanently</title>
$ curl --location "https://iana.org"
<title>Internet Assigned Numbers Authority</title>
```
### 展开短网址
如果你想要在访问短网址之前先查看它们,那么 `--location` 选项非常有用。短网址对于有字符限制的社交网络(当然,如果你使用[现代和开源的社交网络][4]的话,这可能不是问题),或者对于用户不能复制粘贴长地址的印刷媒体来说是有用处的。但是,它们也可能存在风险,因为其目的地址本质上是隐藏的。通过结合使用 `--head` 选项仅查看 HTTP 头,`--location` 选项可以查看一个 URL 的最终地址,你可以查看一个短网址而无需加载其完整的资源:
```
$ curl --head --location "<https://bit.ly/2yDyS4T>"
```
### 下载我们的 curl 备忘录
一旦你开始考虑了将探索 web 由一条命令来完成,那么 `curl` 就成为一种快速有效的方式,可以从互联网上获取所需的信息,而无需麻烦图形界面。为了帮助你适应到工作流中,我们创建了一个 [curl 备忘录][2],它包含常见的 `curl` 用法和语法,包括使用它查询 API 的概述。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/5/curl-cheat-sheet
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [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

View File

@ -0,0 +1,266 @@
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12732-1.html)
[#]: subject: (Learn the basics of programming with C)
[#]: via: (https://opensource.com/article/20/8/c-programming-cheat-sheet)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
C 语言简单编程速成
======
> 我们将所有的 C 语言要素放置到一份易读的备忘录上。
![](https://img.linux.net.cn/data/attachment/album/202010/18/213610t3do3u7oev2udoyn.png)
1972 年,<ruby>丹尼斯·里奇<rt>Dennis Ritchie</rt></ruby>任职于<ruby>贝尔实验室<rt>Bell Labs</rt></ruby>,在几年前,他和他的团队成员发明了 Unix 。在创建了一个经久不衰的操作系统(至今仍在使用)之后,他需要一种好的方法来对这些 Unix 计算机编程以便它们可用执行新的任务。在现在看来这很奇怪但在当时编程语言相对较少Fortran、Lisp、[Algol][2] 以及 B 语言都很流行,但是,对于贝尔实验室的研究员们想要做的事情来说,它们还是远远不够的。丹尼斯·里奇表现出一种后来被称为程序员的主要特征的特质:创造了他自己的解决方案。他称之为 C 语言,并且在近 50 年后,它仍在广泛的使用。
### 为什么你应该学习 C 语言
今天,有很多语言为程序员提供了比 C 语言更多的特性。最明显的是 C++ 语言,这是一种以相当露骨的方式命名的语言,它构建在 C 语言之上,创建了一种很好的面向对象语言。不过,许多其它语言的存在是有充分理由的。计算机擅长一致的重复,因此任何可预见的东西都可以构建在编程语言中,对程序员来说这意味着更少的工作量。为什么在 C++ 语言中用一行语句就可以将一个 `int` 转换为一个 `long` 时(`long x = long(n);`),还要在 C 语言用两行语句呢?
然而C 语言在今天仍然有用。
首先C 语言是一种相当简约和直接的语言。除了编程的基础知识之外,并没有很高级的概念,这很大程度上是因为 C 语言实际上就是现代编程语言的基础之一。例如C 语言的特性之一是数组,但是它不提供字典(除非你自己写一个)。当你学习 C 语言时,你会学习编程的基础组成部分,它可以帮助你认识到如今的编程语言的改进及其的精心设计。
因为 C 语言是一种最小化的编程语言,你的应用程序很可能会获得性能上的提升,这在其它许多编程语言中是看不到的。当你考虑你的代码可以执行多快的时候,很容易陷入锱铢必较的境地,因此,重要的是要问清楚你是否*需要*为某一特定任务提供更多的速度。与 Python 或 Java 相比,使用 C 语言你在每行代码中需要纠结的地方更少。C 语言程序运行很快。这是 Linux 内核使用 C 语言编写的一个很好的理由。
最后C 语言很容易入门,特别是,如果你正在运行 Linux就已经能运行 C 语言代码了,因为 Linux 系统包含 GNU C 库(`glibc`)。为了编写和构建 C 语言程序,你需要做的全部工作就是安装一个编译器,打开一个文本编辑器,开始编码。
### 开始学习 C 语言
如果你正在运行 Linux ,你可以使用你的软件包管理器安装一个 C 编译器。在 Fedora 或 RHEL 上:
```
$ sudo dnf install gcc
```
在 Debian 及其衍生系统上:
```
$ sudo apt install build-essential
```
在 macOS 上,你可以 [安装 Homebrew][3] ,并使用它来安装 [GCC][4]
```
$ brew install gcc
```
在 Windows 上, 你可以使用 [MinGW][5] 安装一套最小的包含 GCC 的 GNU 实用程序集。
在 Linux 或 macOS 上验证你已经安装的 GCC
```
$ gcc --version
gcc (GCC) x.y.z
Copyright (C) 20XX Free Software Foundation, Inc.
```
在 Windows 上,提供 EXE 文件的完整路径:
```
PS> C:\MinGW\bin\gcc.exe --version
gcc.exe (MinGW.org GCC Build-2) x.y.z
Copyright (C) 20XX Free Software Foundation, Inc.
```
### C 语法
C 语言不是一种脚本语言。它是一种编译型语言,这意味着它由 C 编译器处理来产生一个二进制可执行文件。这不同于脚本语言(如 [Bash][6])或混合型语言(如 [Python][7])。
在 C 语言中,你可以创建*函数*来执行你希望做到的任务。默认情况下,执行的是一个名为 `main` 的函数。
这里是一个使用 C 语言写的简单的 “hello world” 程序:
```
#include <stdio.h>
int main() {
printf("Hello world");
return 0;
}
```
第一行包含一个被称为 `stdio.h`(标准输入和输出)的 *头文件*,它基本上是自由使用的、非常初级的 C 语言代码,你可以在你自己的程序中重复使用它。然后创建了一个由一条基本的输出语句构成的名为 `main` 的函数。保存这些文本到一个被称为 `hello.c` 的文件中,然后使用 GCC 编译它:
```
$ gcc hello.c --output hello
```
尝试运行你的 C 语言程序:
```
$ ./hello
Hello world$
```
#### 返回值
这是 Unix 哲学的一部分,一个函数在执行后“返回”一些东西:在成功时不返回任何东西,在失败时返回其它的一些东西(例如,一个错误信息)。这些返回的内容通常使用数字(确切地说是整数)表示:`0` 表示没有错误,任何大于 `0` 的数字都表示一些不成功的状态。
Unix 和 Linux 被设计成在运行成功时保持沉默是很明智的。这是为了让你在执行一系列命令时,假设没有任何错误或警告会妨碍你的工作,从而可以始终为成功执行做准备。类似地,在 C 语言中的函数在设计上也预期不出现错误。
你可以通过一个小的修改,让你的程序看起来是失败的,就可以看到这一点:
```
include <stdio.h>
int main() {
printf("Hello world");
return 1;
}
```
编译它:
```
$ gcc hello.c --output failer
```
现在使用一个内置的 Linux 测试方式来运行它。仅在*成功*时,`&&` 操作符才会执行一个命令的第二部分。例如:
```
$ echo "success" && echo "it worked"
success
it worked
```
在*失败*时,`||` 测试会执行一个命令的第二部分。
```
$ ls blah || echo "it did not work"
ls: cannot access 'blah': No such file or directory
it did not work
```
现在,尝试你的程序,在成功时,它*不*返回 `0`;而是返回 `1`
```
$ ./failer && echo "it worked"
String is: hello
```
这个程序成功地执行了,但是没有触发第二个命令。
#### 变量和类型
在一些语言中,你可以创建变量而不具体指定变量所包含的数据的*类型*。这些语言如此设计使得解释器需要对一个变量运行一些测试来视图发现变量是什么样的数据类型。例如,`var=1` 定义了一个整型数,当你创建一个表达式将 `var` 与某些东西相加时Python 知道显然它是一个整型数。它同样知道当你连接 `hello``world` 时,单词 `world` 是一个字符串。
C 语言不会为你做任何这些识别和调查;你必须自己定义你的变量类型。这里有几种变量类型,包括整型(`int`),字符型(`char`),浮点型(`float`),布尔型(`boolean`)。
你可能也注意到这里没有字符串类型。与 Python 和 Java 和 Lua 以及其它的编程语言不同C 语言没有字符串类型,而是将字符串看作一个字符数组。
这里是一些简单的代码,它建立了一个 `char` 数组变量,然后使用 [printf][9] 将数组变量和一段简单的信息打印到你的屏幕上:
```
#include <stdio.h>
int main() {
char var[6] = "hello";
printf("Your string is: %s\r\n",var);
}
```
你可能会注意到,这个代码示例向一个由五个字母组成的单词提供了六个字符的空间。这是因为在字符串的结尾有处一个隐藏的终止符,它占用了数组中的一个字节。你可以通过编译和执行代码来运行它:
```
$ gcc hello.c --output hello
$ ./hello
hello
```
### 函数
和其它的编程语言一样C 函数也接受可选的参数。你可以通过定义你希望函数接受的数据类型,来将参数从一个函数传递到另一个函数:
```
#include <stdio.h>
int printmsg(char a[]) {
printf("String is: %s\r\n",a);
}
int main() {
char a[6] = "hello";
printmsg(a);
return 0;
}
```
简单地将一个函数分解为两个函数的这种方法并不是非常有用,但是它演示了默认运行 `main` 函数以及如何在函数之间传递数据。
### 条件语句
在真实的编程中,你通常希望你的代码根据数据做出判断。这是使用*条件*语句完成的,`if` 语句是其中最基础的一个语句。
为了使这个示例程序更具动态性,你可以包含 `string.h` 头文件,顾名思义,它包含用于检查字符串的代码。尝试使用来自 `string.h` 文件中的 `strlen` 函数测试传递给 `printmsg` 函数的字符串是否大于 `0`
```
#include <stdio.h>
#include <string.h>
int printmsg(char a[]) {
size_t len = strlen(a);
if ( len > 0) {
printf("String is: %s\r\n",a);
}
}
int main() {
char a[6] = "hello";
printmsg(a);
return 1;
}
```
正如在这个示例中所实现的,该条件永远都不会是非真的,因为所提供的字符串总是 `hello`,它的长度总是大于 `0`。这个不够认真的重新实现的 `echo` 命令的最后一点要做是接受来自用户的输入。
### 命令参数
`stdio.h` 文件包含的代码在每次程序启动时提供了两个参数: 一个是命令中包含多少项的计数(`argc`),一个是包含每个项的数组(`argv`)。例如, 假设你发出这个虚构的命令:
```
$ foo -i bar
```
`argc``3``argv` 的内容是:
* `argv[0] = foo`
* `argv[1] = -i`
* `argv[2] = bar`
你可以修改示例 C 语言程序来以字符串方式接受 `argv[2]`,而不是默认的 `hello` 吗?
### 命令式编程语言
C 语言是一种命令式编程语言。它不是面向对象的,也没有类结构。使用 C 语言的经验可以教你很多关于如何处理数据,以及如何更好地管理你的代码运行时生成的数据。多使用 C 语言,你最后能够编写出其它语言(例如 Python 和 Lua可以使用的库。
想要了解更多关于 C 的知识,你需要使用它。在 `/usr/include/` 中查找有用的 C 语言头文件,并且看看你可以做什么小任务来使 C 语言对你有用。在学习的过程中,使用来自 FreeDOS 的 [Jim Hall][12] 编写的 [C 语言忘备录][11]。它在一张双面纸忘备录上放置了所有的基本要素,所以在你练习时,可以立即访问 C 语言语法的所有要素。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/8/c-programming-cheat-sheet
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean)
校对:[wxy](https://github.com/wxy)
本文由 [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/article/20/6/algol68
[3]: https://opensource.com/article/20/6/homebrew-mac
[4]: https://gcc.gnu.org/
[5]: https://opensource.com/article/20/8/gnu-windows-mingw
[6]: https://opensource.com/resources/what-bash
[7]: https://opensource.com/resources/python
[8]: http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
[9]: https://opensource.com/article/20/8/printf
[10]: http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html
[11]: https://opensource.com/downloads/c-programming-cheat-sheet
[12]: https://opensource.com/users/jim-hall

View File

@ -0,0 +1,252 @@
[#]: collector: (lujun9972)
[#]: translator: (HankChow)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12766-1.html)
[#]: subject: (Automate your container orchestration with Ansible modules for Kubernetes)
[#]: via: (https://opensource.com/article/20/9/ansible-modules-kubernetes)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
使用 Ansible 的 Kubernetes 模块实现容器编排自动化
======
> 将 Kubernetes 与 Ansible 结合实现云端自动化。此外,还可以参照我们的 Ansible 的 k8s 模块速查表。
![](https://img.linux.net.cn/data/attachment/album/202010/28/211747jhlttlf3f81xrffi.jpg)
[Ansible][2] 是实现自动化工作的优秀工具,而 [Kubernetes][3] 则是容器编排方面的利器要是把两者结合起来会有怎样的效果呢正如你所猜测的Ansible + Kubernetes 的确可以实现容器编排自动化。
### Ansible 模块
实际上Ansible 本身只是一个用于解释 YAML 文件的框架。它真正强大之处在于它[丰富的模块][4],所谓<ruby>模块<rt>module</rt></ruby>,就是在 Ansible <ruby>剧本<rt>playbook</rt></ruby> 中让你得以通过简单配置就能调用外部应用程序的一些工具。
Ansible 中有模块可以直接操作 Kubernetes也有对一些相关组件例如 [Docker][5] 和 [Podman][6]实现操作的模块。学习使用一个新模块的过程和学习新的终端命令、API 一样,可以先从文档中了解这个模块在调用的时候需要接受哪些参数,以及这些参数在外部应用程序中产生的具体作用。
### 访问 Kubernetes 集群
在使用 Ansible Kubernetes 模块之前,先要有能够访问 Kubernetes 集群的权限。在没有权限的情况下,可以尝试使用一个短期在线试用账号,但我们更推荐的是按照 Kubernetes 官网上的指引,或是参考 Braynt Son 《[入门 Kubernetes][8]》的教程安装 [Minikube][7]。Minikube 提供了一个单节点 Kubernetes 实例的安装过程,你可以像使用一个完整集群一样对其进行配置和交互。
- 下载 [Ansible k8s 速记表][9](需注册)
在安装 Minikube 之前,你需要确保你的环境支持虚拟化并安装 `libvirt`,然后对 `libvirt` 用户组授权:
```
$ sudo dnf install libvirt
$ sudo systemctl start libvirtd
$ sudo usermod --append --groups libvirt `whoami`
$ newgrp libvirt
```
#### 安装 Python 模块
为了能够在 Ansible 中使用 Kubernetes 相关的模块,你需要安装以下这些 Python 模块:
```
$ pip3.6 install kubernetes --user
$ pip3.6 install openshift --user
```
#### 启动 Kubernetes
如果你使用的是 Minikube 而不是完整的 Kubernetes 集群,请使用 `minikube` 命令在本地创建一个最精简化的 Kubernetes 实例:
```
$ minikube start --driver=kvm2 --kvm-network default
```
然后等待 Minikube 完成初始化,这个过程所需的时间会因实际情况而异。
### 获取集群信息
集群启动以后,通过 `cluster-info` 选项就可以获取到集群相关信息了:
```
$ kubectl cluster-info
Kubernetes master is running at https://192.168.39.190:8443
KubeDNS is running at https://192.168.39.190:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
```
### 使用 k8s 模块
Ansible 使用 `k8s` 这个模块来实现对 Kubernetes 的操作,在剧本中使用 `k8s` 模块就可以对 Kuvernetes 对象进行管理。这个模块描述了 `kubectl` 命令的最终状态,例如对于以下这个使用 `kubectl` 创建新的[命名空间][10]的操作:
```
$ kubectl create namespace my-namespace
```
这是一个很简单的操作,而对这个操作的最终状态用 YAML 文件来描述是这样的:
```
- hosts: localhost
  tasks:
    - name: create namespace
      k8s:
        name: my-namespace
        api_version: v1
        kind: Namespace
        state: present
```
如果你使用的是 Minikube那么主机名`hosts`)应该定义为 `localhost`。需要注意的是,所使用的模块也定义了可用参数的语法(例如 `api_version``kind` 参数)。
在运行这个剧本之前,先通过 `yamllint` 命令验证是否有错误:
```
$ yamllint example.yaml
```
确保没有错误之后,运行剧本:
```
$ ansible-playbook ./example.yaml
```
可以验证新的命名空间是否已经被创建出来:
```
$ kubectl get namespaces
NAME              STATUS   AGE
default           Active   37h
kube-node-lease   Active   37h
kube-public       Active   37h
kube-system       Active   37h
demo              Active   11h
my-namespace      Active   3s
```
### 使用 Podman 拉取容器镜像
容器是个 Linux 系统,几乎是最小化的,可以由 Kubernetes 管理。[LXC 项目][11]和 Docker 定义了大部分的容器规范。最近加入容器工具集的是 Podman它不需要守护进程就可以运行为此受到了很多用户的欢迎。
通过 Podman 可以从 Docker Hub 或者 Quay.io 等存储库拉取容器镜像。这一操作对应的 Ansible 语法也很简单,只需要将存储库网站提供的镜像路径写在剧本中的相应位置就可以了:
```
   - name: pull an image
      podman_image:
        name: quay.io/jitesoft/nginx
```
使用 `yamllint` 验证:
```
$ yamllint example.yaml
```
运行剧本:
```
$ ansible-playbook ./example.yaml
[WARNING]: provided hosts list is empty, only localhost is available.
Note that the implicit localhost does not match 'all'
PLAY [localhost] ************************
TASK [Gathering Facts] ************************
ok: [localhost]
TASK [create k8s namespace] ************************
ok: [localhost]
TASK [pull an image] ************************
changed: [localhost]
PLAY RECAP ************************
localhost: ok=3 changed=1 unreachable=0 failed=0
           skipped=0 rescued=0 ignored=0
```
### 使用 Ansible 实现部署
Ansible 除了可以执行小型维护任务以外,还可以通过剧本实现其它由 `kubectl` 实现的功能,因为两者的 YAML 文件之间只有少量的差异。在 Kubernetes 中使用的 YAML 文件只需要稍加改动,就可以在 Ansible 剧本中使用。例如下面这个用于使用 `kubectl` 命令部署 Web 服务器的 YAML 文件:
```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-webserver
spec:
  selector:
    matchLabels:
      run: my-webserver
  replicas: 1
  template:
    metadata:
      labels:
        run: my-webserver
    spec:
      containers:
      - name: my-webserver
        image: nginx
        ports:
        - containerPort: 80
```
如果你对其中的参数比较熟悉,你只要把 YAML 文件中的大部分内容放到剧本中的 `definition` 部分,就可以在 Ansible 中使用了:
```
   - name: deploy a web server
      k8s:
        api_version: v1
        namespace: my-namespace
        definition:
          kind: Deployment
          metadata:
            labels:
              app: nginx
            name: nginx-deploy
          spec:
            replicas: 1
            selector:
              matchLabels:
                app: nginx
            template:
              metadata:
                labels:
                  app: nginx
              spec:
                containers:
                  - name: my-webserver
                    image: quay.io/jitesoft/nginx
                    ports:
                      - containerPort: 80
                        protocol: TCP
```
执行完成后,使用 `kubectl` 命令可以看到预期中的的<ruby>部署<rt>deployment</rt></ruby>
```
$ kubectl -n my-namespace get pods
NAME                      READY  STATUS
nginx-deploy-7fdc9-t9wc2  1/1    Running
```
### 在云上使用模块
随着现在越来越多的开发和部署工作往云上转移的趋势,我们必须了解如何在云上实现自动化。其中 `k8s``podman_image` 这两个模块只是云开发中的其中一小部分。你可以在你的工作流程中寻找一些需要自动化的任务,并学习如何使用 Ansible 让你在这些任务上事半功倍。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/ansible-modules-kubernetes
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[HankChow](https://github.com/HankChow)
校对:[wxy](https://github.com/wxy)
本文由 [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/ship_captain_devops_kubernetes_steer.png?itok=LAHfIpek (Ship captain sailing the Kubernetes seas)
[2]: https://opensource.com/resources/what-ansible
[3]: https://opensource.com/resources/what-is-kubernetes
[4]: https://docs.ansible.com/ansible/latest/modules/modules_by_category.html
[5]: https://opensource.com/resources/what-docker
[6]: http://podman.io
[7]: https://kubernetes.io/docs/tasks/tools/install-minikube
[8]: https://opensource.com/article/18/10/getting-started-minikube
[9]: https://opensource.com/downloads/ansible-k8s-cheat-sheet
[10]: https://opensource.com/article/19/10/namespaces-and-containers-linux
[11]: https://www.redhat.com/sysadmin/exploring-containers-lxc

View File

@ -0,0 +1,64 @@
[#]: collector: (lujun9972)
[#]: translator: (chenmu-kk)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12735-1.html)
[#]: subject: (NFC vs. Bluetooth LE: When to use which)
[#]: via: (https://www.networkworld.com/article/3574932/nfc-vs-bluetooth-le-when-to-use-which.html)
[#]: author: (Jon Gold https://www.networkworld.com/author/Jon-Gold/)
近场通信 vs. 低功耗蓝牙:如何抉择
======
> 近场通信NFC和低功耗蓝牙BLE是适合企业不同用途的低功耗无线技术。
![](https://images.idgesg.net/images/article/2020/08/distributed_network_of_wifi_wi-fi_internet_connections_across_cityscape_by_metamorworks_gettyimages-926502948_2400x1600-100855926-large.jpg)
在低功率、相对短距离连接的众多选择中有两种技术脱颖而出——近场通信NFC和低功耗蓝牙BLE。两者都具有相对低廉的部署成本且易于使用。
NFC 作为许多现代智能卡片的背后技术而为大众所熟知。NFC 芯片必须十分接近(在几厘米内)读卡器来实现连接,但这是它主要企业用例(安全性和访问控制)的一个优势。
BLE 是主要蓝牙标准的低功耗衍生品,以较低的潜在吞吐量换来了能耗的显著降低,从而能够适应更广泛的潜在用例。
接下来,我们将对每种技术及其主要用例进行更深入的描述。
### NFC 的未来
NFC 在近距离接触范围内工作(设备间必须靠近到几厘米范围内来进行连接),一个可读的无源 NFC “标签”根本不需要任何独立电源,它会从读卡器的信号中汲取能量,工作频率约为 13.5MHz,在主动读取芯片时需要 100-700µA 的电量。
“短距离实际上是它的优势。”Gartner 研究高级总监兼分析师说, “NFC 的一大优点是它不仅仅是无线电,还内置了一个庞大的安全协议。”也就是说,潜在的不良行为者必须非常接近——使用专用设备、在几米的范围内——才能检测到正在发生的 NFC 连接。NFC 还可以施行在 SSL 技术上面一层以提高安全性。
考虑到 NFC 本就起源于非接触式支付技术,这不足为奇。它在这一领域的根基在于对零售商的吸引力,零售商可以利用 NFC 让客户在购买商品前获取相关的信息、获得优惠券或者向店员寻求帮助,只需将手机接触到 NFC 热点即可。
尽管 NFC 只能在一个很近的范围内使用,这限制了使用 NFC 技术用例场景但它不仅仅是为了开门和买一杯拿铁。NFC 可以用于引导连接,便于设备间轻松快速的配对,因此用户只需在会议室中将手机贴近配备好的投影仪,即可创建一个 NFC 连接,并验证智能手机是否是一个可连接的授权设备,并进行演示。演示文稿或者视频数据本身不会通过 NFC 来传输,但是 NFC 握手可作为另外的无线协议(例如 Wi-Fi 网络或者任何其他更高带宽可以传输数据的网络)间的验证,从而无需用户登录。
### BLE 的特点
相较之下BLE 的工作距离要远的多(长达几十米),其最大带宽 1 Mbit/s 约为 NFC 连接的两倍。它是著名的蓝牙技术的产物,相较于主线标准的更低功耗,它为机器到机器的连接做了优化。在连接两端的耗电量均小于 15 mA实用范围约为 10米可通过 AES 加密保护连接。
然而,根据 Forrester 首席分析师 Andre Kindness 的说法,它远非 NFC 的替代品。
他说:“从信息传递角度来看, [NFC] 比 BLE 快得多。”BLE 通常需要几分之一秒或更长时间的验证并安全连接,而 NFC 几乎在瞬间完成连接。
不过,根据 IDC 高级研究分析师 Patrick Filkins 的说法,相较于 NFCBLE 由于范围更广而有着更多的通用性。
他说:“我认为 BLE 比较适合企业”。而类似于资产追踪、室内导航和目标广告的用例只是冰山一角。
对于企业结果是相当直接的——NFC 用例大多与公司使用蓝牙的用例是分开的对于少有的可以选择的重叠相对的优势和劣势显而易见。NFC 距离很短、价格便宜、可即时连接以及数据转换率较低。BLE 的工作距离更远、传输速率更高,成本也更高,连接时还需要一点时间来进行“握手”。
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3574932/nfc-vs-bluetooth-le-when-to-use-which.html
作者:[Jon Gold][a]
选题:[lujun9972][b]
译者:[chenmu-kk](https://github.com/chenmu-kk)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.networkworld.com/author/Jon-Gold/
[b]: https://github.com/lujun9972
[1]: https://www.networkworld.com/newsletters/signup.html
[2]: https://www.facebook.com/NetworkWorld/
[3]: https://www.linkedin.com/company/network-world

View File

@ -0,0 +1,121 @@
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12726-1.html)
[#]: subject: (GNOME 3.38 is Here With Customizable App Grid, Performance Improvements and Tons of Other Changes)
[#]: via: (https://itsfoss.com/gnome-3-38-release/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
GNOME 3.38:可定制应用程序网格、性能改善
======
![](https://img.linux.net.cn/data/attachment/album/202010/16/203906xys0py0nvi1d01ss.jpg)
[GNOME 3.36][1] 带来大量亟需的改进,同时也带来性能的重大提升。现在,在 6 个月后,我们终于引来了 GNOME 3.38,并带来了一系列重大的变化。
### GNOME 3.38 主要特色
这里是 GNOME 3.38 (代码名称Orbis) 的主要亮点:
- [video](https://www.youtube.com/embed/DZ_P5W9r2JY)
#### 可定制应用程序菜单
作为 GNOME 3.38 重大更改中的一部分,应用程序网格(或称应用菜单)现在是可以可定制的。
现在,你可以通过拖拽每个应用程序图标来创建文件夹,将它们移到文件夹,或移出文件夹并将其设置回应用网格。你也可以在应用网格中随心所欲地调整图标的位置。
![][3]
此外,这些变化是一些即将到来的设计更改的基本组成部分,因此,看到我们可以期待的东西会很令人兴奋。
#### 日历菜单更新
![][4]
随着最近一次的 GNOME 更新,通知区整洁了很多,但是现在随着 GNOME 3.38 的到来,你终于可以通过日历区域的正下方访问日历事件,使事情变得方便且容易访问。
它不是一个重大的视觉改造,但也是一些改善。
#### 家长控制改善
作为 GNOME 3.38 一部分你将会注意家长控制服务。它支持与桌面、shell、设置以及其它各种各样组件的集成来帮助你限制用户可以访问的内容。
#### 重新启动按钮
一些细微的改善导致了巨大的变化,重新启动按钮正是其中的一个变化。先单击 “关闭电源” / “关机” 按钮,再单击 “重新启动” 按钮的操作来重新启动系统总是让人很烦。
因此,随着 GNOME 3.38 的到来,你将最终会注意到一个作为单独按钮的 “重新启动” ,这将节省你的单击次数,平复你烦闷的心情。
#### 屏幕录制改善
[GNOME shell 内置的屏幕录制][5] 现在是一项独立的系统服务,这可能会使录制屏幕成为一种平滑流畅的体验。
另外,窗口截屏也有一些改善,并修复了一些错误:
- [video](https://www.youtube.com/embed/c29ge3KwBk8)
#### GNOME 应用程序更新
GNOME 计算器也收到很多的错误修复。除此之外,你也将发现 [epiphany GNOME 浏览器][6] 的一些重大改变。
GNOME Boxes 现在允许你从一个操作系统列表中选择将要运行的操作系统GNOME 地图也有一些图像用户界面上的更改。
当然,不仅限于这些,你页将注意到 GNOME 控制中心、联系人、照片、Nautilus以及其它一些软件包的细微更新和修复。
#### 性能和多显示器支持改善
这里有一大堆底层的改进来全面地改善 GNOME 3.38 。例如,[Mutter][7] 有一些重要的修正,它现在允许在两个显示器中使用不同的刷新频率。
![][8]
先前,如果一台显示器的刷新频率为 60 Hz而另一台的刷新频率为 144 Hz ,那么刷新频率较慢的显示器将限制另外一台显示器的刷新频率。但是,随着在 GNOME 3.38 中的改善,它将能够处理多个显示器,而不会使显示器相互限制。
另外,[Phoronix][9] 报告的一些更改指出,在一些情况下,缩短大约 10% 的渲染时间。因此,这绝对是一个很棒的性能优化。
#### 各种各样的其它更改
* 电池百分比指示器
* 电源菜单中的重新启动选项
* 新的欢迎指引
* 指纹登录
* 二维码扫描以共享 Wi-Fi 热点
* GNOME 浏览器的隐私和其它改善
* GNOME 地图现在反应敏捷并能根据屏幕大小改变其大小
* 重新修订的图标
你可以在它们的官方 [更改日志][10] 中找到一个详细的更改列表。
### 总结
GNOME 3.38 确实是一个令人赞叹的更新,它改善了 GNOME 用户体验。尽管 GNOME 3.36 带来了性能的很大改善,但是针对 GNOME 3.38 的更多优化仍然是一件非常好的事.
GNOME 3.38 将在 Ubuntu 20.10 和 [Fedora 33][11] 中可用。Arch 和 Manjaro 用户应该很快就能获得。
我认为有很多变化是朝着正确的方向发展的。你觉得呢?
--------------------------------------------------------------------------------
via: https://itsfoss.com/gnome-3-38-release/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean)
校对:[wxy](https://github.com/wxy)
本文由 [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/gnome-3-36-release/
[2]: https://www.youtube.com/c/itsfoss?sub_confirmation=1
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/gnome-app-arranger.jpg?resize=799%2C450&ssl=1
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/gnome-3-38-calendar-menu.png?resize=800%2C721&ssl=1
[5]: https://itsfoss.com/gnome-screen-recorder/
[6]: https://en.wikipedia.org/wiki/GNOME_Web
[7]: https://en.wikipedia.org/wiki/Mutter_(software)
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/gnome-multi-monitor-refresh-rate.jpg?resize=800%2C369&ssl=1
[9]: https://www.phoronix.com/scan.php?page=news_item&px=GNOME-3.38-Last-Min-Mutter
[10]: https://help.gnome.org/misc/release-notes/3.38
[11]: https://itsfoss.com/fedora-33/

View File

@ -0,0 +1,169 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12740-1.html)
[#]: subject: (How to Reduce/Shrink LVMs \(Logical Volume Resize\) in Linux)
[#]: via: (https://www.2daygeek.com/reduce-shrink-decrease-resize-lvm-logical-volume-in-linux/)
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
如何在 Linux 中减少/缩小 LVM 大小(逻辑卷调整)
======
![](https://img.linux.net.cn/data/attachment/album/202010/21/210459ydp5an23nfzgglyy.jpg)
减少/缩小逻辑卷是数据损坏的最高风险。
所以,如果可能的话,尽量避免这种情况,但如果没有其他选择的话,那就继续。
缩减 LVM 之前,建议先做一个备份。
当你在 LVM 中的磁盘空间耗尽时,你可以通过缩小现有的没有使用全部空间的 LVM而不是增加一个新的物理磁盘在卷组上腾出一些空闲空间。
**需要注意的是:** 在 GFS2 或者 XFS 文件系统上不支持缩小。
如果你是逻辑卷管理 LVM 的新手,我建议你从我们之前的文章开始学习。
* **第一部分:[如何在 Linux 中创建/配置 LVM逻辑卷管理][1]**
* **第二部分:[如何在 Linux 中扩展/增加 LVM逻辑卷调整][2]**
![](https://img.linux.net.cn/data/attachment/album/202010/21/210610kikq1xynfje7hjaa.jpeg)
减少逻辑卷涉及以下步骤:
* 卸载文件系统
* 检查文件系统是否有任何错误
* 缩小文件系统的大小
* 缩小逻辑卷的大小
* 重新检查文件系统是否存在错误(可选)
* 挂载文件系统
* 检查减少后的文件系统大小
**比如:** 你有一个 **100GB** 的没有使用全部空间的 LVM你想把它减少到 **80GB**,这样 **20GB** 可以用于其他用途。
```
# df -h /testlvm1
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg01-lv002 100G 15G 85G 12% /testlvm1
```
### 卸载文件系统
使用 `umount` 命令卸载文件系统:
```
# umount /testlvm1
```
### 检查文件系统是否有任何错误
使用 `e2fsck` 命令检查文件系统是否有错误:
```
# e2fsck -f /dev/mapper/vg01-lv002
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/vg01-lv002: 13/6553600 files (0.0% non-contiguous), 12231854/26212352 blocks
```
### 缩小文件系统
下面的命令将把 `testlvm1` 文件系统从 **100GB** 缩小到 **80GB**
**文件系统大小调整的常用语法(`resize2fs`**
```
resize2fs [现有逻辑卷名] [新的文件系统大小]
```
实际命令如下:
```
# resize2fs /dev/mapper/vg01-lv002 80G
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/mapper/vg01-lv002 to 28321400 (4k) blocks.
The filesystem on /dev/mapper/vg01-lv002 is now 28321400 blocks long.
```
### 减少逻辑卷 LVM 容量
现在使用 `lvreduce` 命令缩小逻辑卷LVM 的大小。通过下面的命令, `/dev/mapper/vg01-lv002` 将把逻辑卷 LVM 从 100GB 缩小到 80GB。
**LVM 缩减 `lvreduce` 的常用语法**
```
lvreduce [新的 LVM 大小] [现有逻辑卷名称]
```
实际命令如下:
```
# lvreduce -L 80G /dev/mapper/vg01-lv002
WARNING: Reducing active logical volume to 80.00 GiB
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce lv002? [y/n]: y
Reducing logical volume lv002 to 80.00 GiB
Logical volume lv002 successfully resized
```
### 可选:检查文件系统是否有错误
缩减 LVM 后再次检查文件系统是否有错误:
```
# e2fsck -f /dev/mapper/vg01-lv002
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/vg01-lv002: 13/4853600 files (0.0% non-contiguous), 1023185/2021235 blocks
```
### 挂载文件系统并检查缩小后的大小
最后挂载文件系统,并检查缩小后的文件系统大小。
使用 `mount` 命令[挂载逻辑卷][4]
```
# mount /testlvm1
```
使用 [df 命令][5]检查挂载的卷。
```
# df -h /testlvm1
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg01-lv002 80G 15G 65G 18% /testlvm1
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/reduce-shrink-decrease-resize-lvm-logical-volume-in-linux/
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.2daygeek.com/author/magesh/
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-12670-1.html
[2]: https://linux.cn/article-12673-1.html
[3]: https://www.2daygeek.com/wp-content/uploads/2020/09/reduce-shrink-decrease-resize-lvm-logical-volume-in-linux-1.png
[4]: https://www.2daygeek.com/mount-unmount-file-system-partition-in-linux/
[5]: https://www.2daygeek.com/linux-check-disk-space-usage-df-command/

View File

@ -0,0 +1,129 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12748-1.html)
[#]: subject: (Linux Jargon Buster: What is FOSS \(Free and Open Source Software\)? What is Open Source?)
[#]: via: (https://itsfoss.com/what-is-foss/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
Linux 黑话解释:什么是 FOSS自由和开源软件什么是开源
======
![][7]
什么是 FOSS
在过去,我曾多次被问到这个问题,现在是时候解释一下什么是 Linux 和软件世界中的 FOSS 了。
这个区别很重要,因为 FOSS 是一个通用的词汇,它可以根据上下文的不同而有不同的含义。在这里,我讨论的是软件中的 FOSS 原则。
### 什么是 FOSS
FOSS 是指<ruby>自由和开放源码软件<rt>Free and Open Source Software</rt></ruby>。这并不意味着软件是免费的。它意味着软件的源代码是开放的,任何人都可以自由使用、研究和修改代码。这个原则允许人们像一个社区一样为软件的开发和改进做出贡献。
#### FOSS 的起源
在上世纪 60、70 年代,计算机以硬件为主,硬件价格昂贵。它们主要由大学的学者或实验室的研究人员使用。以前有限的软件都是免费的,或者是带有它们的源代码,用户可以根据自己的需要修改源代码。
在上世纪 70 年代末和 80 年代初,制造商为了不让自己的软件在竞争对手的计算机上运行,停止了分发源代码。
这种限制性的许可导致了那些习惯和喜欢修改软件的人的不便和不喜。上世纪 80 年代中期Richard Stallman 发起了<ruby>自由软件运动<rt>Free Software Movement</rt></ruby>
[Stallman 指明了一个软件要成为 FOSS 的四个基本自由][1]。
![自由软件自由][2]
为了便于理解,我将它们重新表述:
* 任何用户应能为任何目的运行软件。
* 用户应能自由查看软件的源代码,如有需要,应允许用户修改代码。
* 用户应能自由地将软件的副本分发给他人。
* 如果用户修改了代码,她/他应该可以自由地将修改后的代码发布给他人。修改后的代码必须开放源代码。
如果有兴趣,我建议阅读这篇关于 [FOSS 的历史][3]的文章。
### FOSS 中的 “Free” 并不意味着免费
![][4]
你可能已经注意到了,自由和开源软件中的 “Free” 并不意味着它是免费的,它意味着运行、修改和分发软件的“自由”。
人们经常错误地认为FOSS 或开源软件不能有价格标签。这是不正确的。
大多数 FOSS 都是免费提供的,原因有很多:
* 源代码已经向公众开放,所以一些开发者认为没有必要在下载软件时贴上价格标签。
* 有些项目是由一些志愿者免费提供的。因此,主要的开发者认为对这么多人免费贡献的东西收费是不道德的。
* 有些项目是由较大的企业或非营利组织支持和/或开发的,这些组织会雇佣开发人员在他们的开源项目上工作。
* 有些开发者创建开源项目是出于兴趣,或者出于他们对用代码为世界做贡献的热情。对他们来说,下载量、贡献和感谢的话比金钱更重要。
为了避免强调 “免费”,有些人使用了 FLOSS 这个词LCTT 译注:有时候也写作 F/LOSS。FLOSS 是<ruby>自由和开源软件<rt>Free/Libre Open Source Software</rt></ruby>的缩写。单词 Libre意为自由与 gartuit/gratis免费不同。
> “Free” 是言论自由的自由,而不是免费啤酒的免费。
### FOSS 项目如何赚钱?
开源项目不赚钱是一个神话。红帽是第一个达到 10 亿美元大关的开源公司。[IBM 以 340 亿美元收购了红帽][5]。这样的例子有很多。
许多开源项目特别是企业领域的项目都会提供收费的支持和面向企业的功能。这是红帽、SUSE Linux 和更多此类项目的主要商业模式。
一些开源项目,如 Discourse、WordPress 等,则提供其软件的托管实例,并收取一定的费用。
许多开源项目特别是桌面应用程序依靠捐赠。VLC、GIMP、Inkscape 等这类开源软件就属于这一类。有[资助开源项目的方法][6],但通常,你会在项目网站上找到捐赠链接。
利用开源软件赚钱可能很难,但也不是完全不可能。
### 但我不是程序员,我为什么要关心一个软件是否开源?
这是一个合理的问题。你不是一个软件开发者,只是一个普通的计算机用户。即使软件的源代码是可用的,你也不会理解程序的工作原理。
这很好。你不会明白,但有必要技能的人就会明白,这才是最重要的。
你可以这样想。也许你不会理解一份复杂的法律文件。但如果你有看文件的自由,并保留一份副本,你就可以咨询某个人,他可以检查文件中的法律陷阱。
换句话说,开源软件具有透明度。
### FOSS 与开源之间的区别是什么?
你会经常遇到 FOSS 和<ruby>开源<rt>Open Source</rt></ruby>的术语。它们经常被互换使用。
它们是同一件事吗?这很难用“是”和“不是”来回答。
你看FOSS 中的“Free”一词让很多人感到困惑因为人们错误地认为它是免费的。企业高管、高层和决策者往往会关注自由和开源中的“免费”。由于他们是商业人士专注于为他们的公司赚钱“自由”一词在采用 FOSS 原则时起到了威慑作用。
这就是为什么在上世纪 90 年代中期创立了一个名为<ruby>[开源促进会][8]<rt>Open Source Initiative</rt></ruby>的新组织。他们从自由和开放源码软件中去掉了“自由”一词,并创建了自己的[开放源码的定义][9],以及自己的一套许可证。
<ruby>开源<rt>Open Source</rt></ruby>”一词在软件行业特别流行。高管们对开源更加适应。开源软件的采用迅速增长,我相信 “免费”一词的删除确实起到了作用。
### 有问题吗?
这正如我在[什么是 Linux 发行版][10]一文中所解释的那样FOSS/开源的概念在 Linux 的发展和普及中起到了很大的作用。
我试图在这篇黑话解释文章中用更简单的语言解释 FOSS 和开源的概念,而试图避免在细节或技术精度上做过多的阐述。
我希望你现在对这个话题有了更好的理解。如果你有问题或建议,欢迎留言并继续讨论。
--------------------------------------------------------------------------------
via: https://itsfoss.com/what-is-foss/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://www.gnu.org/philosophy/free-sw.html
[2]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/foss-freedoms.jpg?resize=800%2C671&ssl=1
[3]: https://itsfoss.com/history-of-foss/
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/think-free-speech-not-free-beer.jpg?resize=800%2C800&ssl=1
[5]: https://itsfoss.com/ibm-red-hat-acquisition/
[6]: https://itsfoss.com/open-source-funding-platforms/
[7]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/what-is-foss.png?resize=800%2C450&ssl=1
[8]: https://opensource.org/
[9]: https://opensource.org/osd
[10]: https://itsfoss.com/what-is-linux-distribution/

View File

@ -0,0 +1,101 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12719-1.html)
[#]: subject: (Present Slides in Linux Terminal With This Nifty Python Tool)
[#]: via: (https://itsfoss.com/presentation-linux-terminal/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
在 Linux 终端中展示幻灯片
======
![](https://img.linux.net.cn/data/attachment/album/202010/15/000226j34xnkzzg7z7x9ka.jpg)
演示文稿往往是枯燥的。这就是为什么有些人会添加动画或漫画/meme 来增加一些幽默和风格来打破单调。
如果你需要在你的大学或公司的演示文稿中加入一些独特的风格,那么使用 Linux 终端怎么样?想象一下,这将是多么酷的事情啊!
### PresentLinux 终端中进行演示
在终端中可以做很多[有趣好玩的事情][1]。制作和展示幻灯片只是其中之一。
这个基于 Python 的应用名为 [Present][2],它可以让你创建基于 Markdown 和 YML 的幻灯片,你可以在你的大学或公司里演讲,并以真正的极客风格取悦人们。
我制作了一个视频,展示了在 Linux 终端中用 Present 演示一些东西的样子。
- [VIDEO](https://img.linux.net.cn/static/video/Makes%20ASCII%20Based%20Presentation%20Slides%20in%20Linux%20terminal-462902030.mp4)
#### Present 的功能
你可以用 Present 做以下事情:
* 使用 Markdown 语法在幻灯片中添加文本
* 用箭头或 `PgUp`/`Down` 键控制幻灯片
* 改变前景和背景颜色
* 在幻灯片中添加图像
* 增加代码块
* 播放模拟代码,并用 codio YML 文件输出
#### 在 Linux 上安装 Present
Present 是一个基于 Python 的工具,你可以使用 PIP 来安装它。你应该确保用这个命令[在 Ubuntu 上安装 Pip][4]
```
sudo apt install python3-pip
```
如果你使用的是其他发行版,请检查你的包管理器来安装 PIP3。
安装 PIP 后,你就可以以这种方式全局安装 Present
```
sudo pip3 install present
```
你也可以只为当前用户安装,但你也必须将 `~/.local/bin` 添加到你的 `PATH` 环境变量。
#### 在 Linux 终端中使用 Present 来创建和展示幻灯片
![][5]
由于 Present 使用了 Markdown 语法,你应该用它来创建自己的幻灯片。在这里使用 [Markdown 编辑器][6]会有帮助。
Present 需要一个 Markdown 文件来读取和播放幻灯片。你可以[下载这个示例幻灯片][7],但你需要单独下载嵌入的图像,并将它放在图像文件夹内。
* 在 Markdown 文件中使用 `—` 来分隔幻灯片。
* 使用 Markdown 语法在幻灯片中添加文本。
* 使用以下语法添加图片 `![RC] (images/name.png)`
* 通过添加像 `<! fg=white bg=red >` 这样的语法来改变幻灯片的颜色。
* 使用像 `<! effect=fireworks >` 这样的语法来添加带有效果的幻灯片。
* 使用 [codio 语法][8] 添加代码运行模拟。
* 使用 `q` 退出演示,并用左/右箭头或 `PgUp`/`Down` 键控制幻灯片。
请记住,在演示时调整终端窗口的大小会把东西搞乱,按回车键也是如此。
### 总结
如果你熟悉 Markdown 和终端,使用 Present 对你来说并不困难。
你不能把它和常规的用 Impress、MS Office 等制作的幻灯片相比,但偶尔使用,它是一个很酷的工具。如果你是计算机科学/网络专业的学生,或者是开发人员或系统管理员,你的同事一定会觉得很有趣。
--------------------------------------------------------------------------------
via: https://itsfoss.com/presentation-linux-terminal/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/funny-linux-commands/
[2]: https://github.com/vinayak-mehta/present
[4]: https://itsfoss.com/install-pip-ubuntu/
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/presentation-in-linux-terminal.png?resize=800%2C494&ssl=1
[6]: https://itsfoss.com/best-markdown-editors-linux/
[7]: https://github.com/vinayak-mehta/present/blob/master/examples/sample.md
[8]: https://present.readthedocs.io/en/latest/codio.html

View File

@ -0,0 +1,99 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12738-1.html)
[#]: subject: (Simplify your web experience with this internet protocol alternative)
[#]: via: (https://opensource.com/article/20/10/gemini-internet-protocol)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
使用互联网协议替代方案 Gemini 简化你的 Web 体验
======
> 用 Gemini 协议发现更安静、更简单的互联网新角落。
![](https://img.linux.net.cn/data/attachment/album/202010/21/070950dzph7mlm0h035h3o.jpg)
如果你很久以前就已经上网了,或者是知识非常丰富,你可能还记得一个早期的文本共享协议,叫做 [Gopher][2]。Gopher 最终被 HTTP 协议所取代当然HTTP 协议是现代万维网的基础。对于很多人来说,“<ruby>互联网<rt>internet</rt></ruby>”和“<ruby>万维网<rt>World Wide Web</rt></ruby>”是一回事,因为很多人没有意识到在网上进行了*非* www 子域下的任何操作。
但一直以来都有各种网络协议在互联网络上共享信息Telnet、FTP、SSH、Torrent、GNUnet 等等。最近,在这一系列的替代品中又多了一个,它叫 [Gemini][3]。
Gemini双子座协议以“水星计划”和“阿波罗计划”的基础实验之间的太空任务命名旨在和平地处在 Gopher 和 HTTP 之间。无论如何,它的目的并不是要取代现代 Web但它确实试图创造一个简化的网络和一个现代化的 Gopher。
它的发展历史虽然可能很年轻,但意义重大,原因有很多。当然,人们会因为技术和哲学上的原因而对现代 Web 表示质疑,但它只是一般的臃肿。当你真正想要的是一个非常具体的问题的可靠答案时,那么无数次点击谷歌搜索的结果让人感觉过头了。
许多人使用 Gopher 就是因为这个原因它的规模小到可以让小众的兴趣很容易找到。然而Gopher 是一个旧的协议,它对编程、网络和浏览做出了一些假设,但这些假设已经不再适用了。 Gemini 的目标是将最好的网络带入一种类似于 Gopher 但易于编程的格式。一个简单的 Gemini 浏览器可以用几百行代码写成,并且有一个非常好的浏览器用 1600 行左右写成。这对于程序员、学生和极简主义者来说都是一个强大的功能。
### 如何浏览 Gemini
就像早期的网络一样Gemini 的规模很小,所以有一个列表列出了运行 Gemini 网站的已知服务器。就像浏览 HTTP 站点需要一个网页浏览器一样,访问 Gemini 站点也需要一个 Gemini 浏览器。在 [Gemini 网站][4]上列出了有几个可用的浏览器。
最简单的一个是 [AV-98][5] 客户端。它是用 Python 编写的,在终端中运行。要想试试的话,请下载它:
```
$ git clone https://tildegit.org/solderpunk/AV-98.git
```
进入下载目录,运行 AV-98
```
$ cd AV-98.git
$ python3 ./main.py
```
客户端是一个交互式的提示符。它有有限的几个命令,主要的命令是简单的 `go`,后面跟着一个 Gemini 服务器地址。在已知的 [Gemini 服务器][6]列表中选择一个看起来很有趣的服务器,然后尝试访问它:
```
AV-98> go gemini://example.club
Welcome to the example.club Gemini server!
Here are some folders of ASCII art:
[1] Penguins
[2] Wildebeests
[3] Demons
```
导航是按照编号的链接来进行的。例如,要进入 `Penguins` 目录,输入 `1` 然后按回车键:
```
AV-98> 1
[1] Gentoo
[2] Emperor
[3] Little Blue
```
要返回,输入 `back` 并按回车键:
```
AV-98> back
```
更多命令,请输入 `help`
### 用 Gemini 作为你的 web 替代
Gemini 协议非常简单,初级和中级程序员都可以为其编写客户端,而且它是在互联网上分享内容的一种简单快捷的方式。虽然万维网的无处不在对广泛传播是有利的,但总有替代方案的空间。看看 Gemini发现更安静、更简单的互联网的新角落。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/gemini-internet-protocol
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [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]: https://en.wikipedia.org/wiki/Gopher_%28protocol%29
[3]: https://gemini.circumlunar.space/
[4]: https://gemini.circumlunar.space/clients.html
[5]: https://tildegit.org/solderpunk/AV-98
[6]: https://portal.mozz.us/gemini/gemini.circumlunar.space/servers

View File

@ -0,0 +1,106 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12733-1.html)
[#]: subject: (Integrate your calendar with Ansible to avoid schedule conflicts)
[#]: via: (https://opensource.com/article/20/10/calendar-ansible)
[#]: author: (Nicolas Leiva https://opensource.com/users/nicolas-leiva)
将你的日历与 Ansible 集成,以避免与日程冲突
======
> 通过将日历应用集成到 Ansible 中,确保你的自动化工作流计划不会与其他东西冲突。
![](https://img.linux.net.cn/data/attachment/album/202010/18/221110wk9kd9ewrde11zxx.jpg)
“随时”是执行自动化工作流的好时机吗?出于不同的原因,答案可能是否定的。
如果要避免同时进行更改,以最大限度地减少对关键业务流程的影响,并降低意外服务中断的风险,则在你的自动化运行的同时,其他任何人都不应该试图进行更改。
在某些情况下,可能存在一个正在进行的计划维护窗口。或者,可能有大型事件即将来临、一个关键的业务时间、或者假期(你或许不想在星期五晚上进行更改)。
![Street scene with a large calendar and people walking][2]
无论出于什么原因,你都希望将此信息发送到你的自动化平台,以防止在特定时间段内执行周期性或临时任务。用变更管理的行话,我说的是当变更活动不应该发生时,指定封锁窗口。
### Ansible 中的日历集成
如何在 [Ansible][5] 中实现这个功能?虽然它本身没有日历功能,但 Ansible 的可扩展性将允许它与任何具有 API 的日历应用集成。
目标是这样的:在执行任何自动化或变更活动之前,你要执行一个 `pre-task` ,它会检查日历中是否已经安排了某些事情(目前或最近),并确认你没有在一个阻塞的时间段中。
想象一下,你有一个名为 `calendar` 的虚构模块,它可以连接到一个远程日历,比如 Google 日历,以确定你指定的时间是否已经以其他方式被标记为繁忙。你可以写一个类似这样的剧本:
```
- name: Check if timeslot is taken
  calendar:
    time: "{{ ansible_date_time.iso8601 }}"
  register: output
```
Ansible 实际会给出 `ansible_date_time`,将其传递给 `calendar` 模块,以验证时间的可用性,以便它可以注册响应 `output`),用于后续任务。
如果你的日历是这样的:
![Google Calendar screenshot][6]
那么这个任务的输出就会指明这个时间段被占用的事实 `busy: true`
```
ok: [localhost] =&gt; {
   "output": {
       "busy": true,
       "changed": false,
       "failed": false,
       "msg": "The timeslot 2020-09-02T17:53:43Z is busy: true"
   }
}
```
### 阻止任务运行
接下来,[Ansible Conditionals][8] 将帮助阻止所有之后任务的执行。一个简单的例子,你可以在下一个任务上使用 `when` 语句来强制它只有当上一个输出中的 `busy` 字段不是 `true` 时,它才会运行:
```
tasks:
  - shell: echo "Run this only when not busy!"
    when: not output.busy
```
### 总结
在[上一篇文章][9]中,我说过 Ansible 是一个将事物连接在一起的框架,将不同的组成部分相互连接,以协调端到端自动化工作流。
这篇文章探讨了 Ansible 剧本如何与日历应用集成以检查可用性。然而,我只做了一些表面工作!例如,你的任务也可以阻止日历中的一个时间段,这里的发挥空间很大。
在我的下一篇文章中,我将深入 `calendar` 模块是如何构建的,以及其他编程语言如何与 Ansible 一起使用。如果你和我一样是 [Go][10] 的粉丝,请继续关注!
* * *
_这篇文章最初发表在 Medium 上,名为 [Ansible and Google Calendar integration for change management][11],采用 CC BY-SA 4.0 许可经许可后转载。_
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/calendar-ansible
作者:[Nicolas Leiva][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/nicolas-leiva
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/calendar.jpg?itok=jEKbhvDT (Calendar close up snapshot)
[2]: https://opensource.com/sites/default/files/uploads/street-calendar.jpg (Street scene with a large calendar and people walking)
[3]: https://www.flickr.com/photos/7841127@N02/4217116202
[4]: https://creativecommons.org/licenses/by-nd/2.0/
[5]: https://docs.ansible.com/ansible/latest/index.html
[6]: https://opensource.com/sites/default/files/uploads/googlecalendarexample.png (Google Calendar screenshot)
[7]: https://creativecommons.org/licenses/by-sa/4.0/
[8]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html
[9]: https://medium.com/swlh/python-and-ansible-to-automate-a-network-security-workflow-28b9a44660c6
[10]: https://golang.org/
[11]: https://medium.com/swlh/ansible-and-google-calendar-integration-for-change-management-7c00553b3d5a

View File

@ -0,0 +1,133 @@
[#]: collector: (lujun9972)
[#]: translator: (gxlct008)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12724-1.html)
[#]: subject: (How to Install Deepin Desktop on Ubuntu 20.04 LTS)
[#]: via: (https://itsfoss.com/install-deepin-ubuntu/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
如何在 Ubuntu 20.04 LTS 上安装深度Deepin桌面环境
======
![](https://img.linux.net.cn/data/attachment/album/202010/15/223607kqs5zguiq53fkkig.png)
> 本教程向你展示在 Ubuntu 上安装深度Deepin桌面环境的正确步骤。还提到了移除步骤。
毫无疑问深度操作系统Deepin OS是一个 [漂亮的 Linux 发行版][1]。最近发布的 [深度操作系统 V20][2] 就更加美观了。
[深度操作系统][3] 是基于 [Debian][4] 的,默认的存储库镜像太慢了。如果你更愿意使用 Ubuntu可以选择 [UbuntuDDE Linux 发行版][5] 形式的 Ubuntu 的深度操作系统的变体。它还不是 [官方的 Ubuntu 风格][6] 之一。
[重新安装新的发行版][7] 是一个麻烦,因为你会丢失数据,你将不得不在新安装的 UbuntuDDE 上重新安装你的应用程序。
一个更简单的选择是在现有的 Ubuntu 系统上安装深度桌面环境DDE。毕竟你可以轻松地在一个系统中安装多个[桌面环境][8]。
不要烦恼,这很容易做到,如果你不喜欢,也可以恢复这些更改。让我来告诉你怎么做。
### 在 Ubuntu 20.04 上安装深度桌面环境
UbuntuDDE 团队已为他们的发行版创建了一个 PPA你可以使用相同的 PPA 在 Ubuntu 20.04 上安装深度桌面环境。请记住,此 PPA 仅适用于 Ubuntu 20.04。请阅读有关 [在 Ubuntu 中使用 PPA][10]。
> 没有深度桌面环境 V20
>
> 你将在此处使用 PPA 安装的深度桌面环境还不是新的 V20。它可能会在 Ubuntu 20.10 发布后出现,但是我们不能担保。
以下是你需要遵循的步骤:
**步骤 1**:你需要首先在终端上输入以下内容,来添加 [Ubuntu DDE Remix 团队的官方 PPA][11]
```
sudo add-apt-repository ppa:ubuntudde-dev/stable
```
**步骤 2**:添加存储库以后,继而安装深度桌面环境。
```
sudo apt install ubuntudde-dde
```
![][12]
现在,安装将启动,一段时间后,将要求你选择<ruby>显示管理器<rt>display manager</rt></ruby>
![][13]
如果需要深度桌面主题的锁屏,则需要选择 “lightdm”。如果不需要你可以将其设置为 “gdm3”。
如果你看不到此选项,可以通过键入以下命令来获得它,然后选择你首选的显示管理器:
```
sudo dpkg-reconfigure lightdm
```
**步骤 3** 完成后,你必须退出并通过选择 “Deepin” 会话再次登录,或者重新启动系统。
![][14]
就是这样。马上在你的 Ubuntu 20.04 LTS 系统上享受深度桌面环境体验吧!
![][15]
### 从 Ubuntu 20.04 删除深度桌面
如果你不喜欢这种体验,或者由于某些原因它有 bug可以按照以下步骤将其删除。
**步骤 1** 如果你已将 “lightdm” 设置为显示管理器,则需要在卸载深度桌面环境之前将显示管理器设置为 “gdm3”。为此请键入以下命令
```
sudo dpkg-reconfigure lightdm
```
![Select gdm3 on this screen][13]
然后,选择 “gdm3” 继续。
完成此操作后,你只需输入以下命令即可完全删除深度桌面环境:
```
sudo apt remove startdde ubuntudde-dde
```
你只需重启即可回到原来的 Ubuntu 桌面环境。如果图标没有响应,只需打开终端(`CTRL + ALT + T`)并输入:
```
reboot
```
### 总结
有不同的 [桌面环境选择][16] 是件好事。如果你真的喜欢深度桌面环境的界面,那么这可能是在 Ubuntu 上体验深度操作系统的一种方式。
如果你有任何疑问或遇到任何问题,请在评论中告诉我。
--------------------------------------------------------------------------------
via: https://itsfoss.com/install-deepin-ubuntu/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[gxlct008](https://github.com/gxlct008)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/beautiful-linux-distributions/
[2]: https://itsfoss.com/deepin-20-review/
[3]: https://www.deepin.org/en/
[4]: https://www.debian.org/
[5]: https://itsfoss.com/ubuntudde/
[6]: https://itsfoss.com/which-ubuntu-install/
[7]: https://itsfoss.com/reinstall-ubuntu/
[8]: https://itsfoss.com/what-is-desktop-environment/
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/ubuntu-20-with-deepin.jpg?resize=800%2C386&ssl=1
[10]: https://itsfoss.com/ppa-guide/
[11]: https://launchpad.net/~ubuntudde-dev/+archive/ubuntu/stable
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/deepin-desktop-install.png?resize=800%2C534&ssl=1
[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/deepin-display-manager.jpg?resize=800%2C521&ssl=1
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/deepin-session-ubuntu.jpg?resize=800%2C414&ssl=1
[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/10/ubuntu-20-with-deepin-1.png?resize=800%2C589&ssl=1
[16]: https://itsfoss.com/best-linux-desktop-environments/

View File

@ -0,0 +1,181 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12750-1.html)
[#]: subject: (How to Remove Physical Volume from a Volume Group in LVM)
[#]: via: (https://www.2daygeek.com/linux-remove-delete-physical-volume-pv-from-volume-group-vg-in-lvm/)
[#]: author: (Magesh Maruthamuthu https://www.2daygeek.com/author/magesh/)
如何从 LVM 的卷组中删除物理卷?
======
![](https://img.linux.net.cn/data/attachment/album/202010/25/101355kav72t5iy5yj55tg.jpg)
如果你的 LVM 不再需要使用某个设备,你可以使用 `vgreduce` 命令从卷组中删除物理卷。
`vgreduce` 命令可以通过删除物理卷来缩小卷组的容量。但要确保该物理卷没有被任何逻辑卷使用,请使用 `pvdisplay` 命令查看。如果物理卷仍在使用,你必须使用 `pvmove` 命令将数据转移到另一个物理卷。
数据转移后,它就可以从卷组中删除。
最后使用 `pvremove` 命令删除空物理卷上的 LVM 标签和 LVM 元数据。
* **第一部分:[如何在 Linux 中创建/配置 LVM逻辑卷管理][1]**
* **第二部分:[如何在 Linux 中扩展/增加 LVM 大小(逻辑卷调整)][2]**
* **第三部分:[如何在 Linux 中减少/缩小 LVM 大小(逻辑卷调整)][3]**
![](https://img.linux.net.cn/data/attachment/album/202010/25/101424vgcio5fooi9uo5gh.jpeg)
### 将扩展块移动到现有物理卷上
使用 `pvs` 命令检查是否使用了所需的物理卷(我们计划删除 LVM 中的 `/dev/sdc` 磁盘)。
```
# pvs -o+pv_used
PV VG Fmt Attr PSize PFree Used
/dev/sda myvg lvm2 a- 75.00G 14.00G 61.00G
/dev/sdb myvg lvm2 a- 50.00G 45.00G 5.00G
/dev/sdc myvg lvm2 a- 17.15G 12.15G 5.00G
```
如果使用了,请检查卷组中的其他物理卷是否有足够的空闲<ruby>扩展块<rt>extent</rt></ruby>
如果有的话,你可以在需要删除的设备上运行 `pvmove` 命令。扩展块将被分配到其他设备上。
```
# pvmove /dev/sdc
/dev/sdc: Moved: 2.0%
/dev/sdc: Moved: 79.2%
/dev/sdc: Moved: 100.0%
```
`pvmove` 命令完成后。再次使用 `pvs` 命令检查物理卷是否有空闲。
```
# pvs -o+pv_used
PV VG Fmt Attr PSize PFree Used
/dev/sda myvg lvm2 a- 75.00G 1.85G 73.15G
/dev/sdb myvg lvm2 a- 50.00G 45.00G 5.00G
/dev/sdc myvg lvm2 a- 17.15G 17.15G 0
```
如果它是空闲的,使用 `vgreduce` 命令从卷组中删除物理卷 `/dev/sdc`
```
# vgreduce myvg /dev/sdc
Removed "/dev/sdc" from volume group "vg01"
```
最后,运行 `pvremove` 命令从 LVM 配置中删除磁盘。现在,磁盘已经完全从 LVM 中移除,可以用于其他用途。
```
# pvremove /dev/sdc
Labels on physical volume "/dev/sdc" successfully wiped.
```
### 移动扩展块到新磁盘
如果你在卷组中的其他物理卷上没有足够的可用扩展。使用以下步骤添加新的物理卷。
向存储组申请新的 LUN。分配完毕后运行以下命令来[在 Linux 中发现新添加的 LUN 或磁盘][5]。
```
# ls /sys/class/scsi_host
host0
```
```
# echo "- - -" > /sys/class/scsi_host/host0/scan
```
```
# fdisk -l
```
操作系统中检测到磁盘后,使用 `pvcreate` 命令创建物理卷。
```
# pvcreate /dev/sdd
Physical volume "/dev/sdd" successfully created
```
使用以下命令将新的物理卷 `/dev/sdd` 添加到现有卷组 `vg01` 中。
```
# vgextend vg01 /dev/sdd
Volume group "vg01" successfully extended
```
现在,使用 `pvs` 命令查看你添加的新磁盘 `/dev/sdd`
```
# pvs -o+pv_used
PV VG Fmt Attr PSize PFree Used
/dev/sda myvg lvm2 a- 75.00G 14.00G 61.00G
/dev/sdb myvg lvm2 a- 50.00G 45.00G 5.00G
/dev/sdc myvg lvm2 a- 17.15G 12.15G 5.00G
/dev/sdd myvg lvm2 a- 60.00G 60.00G 0
```
使用 `pvmove` 命令将数据从 `/dev/sdc` 移动到 `/dev/sdd`
```
# pvmove /dev/sdc /dev/sdd
/dev/sdc: Moved: 10.0%
/dev/sdc: Moved: 79.7%
/dev/sdc: Moved: 100.0%
```
数据移动到新磁盘后。再次使用 `pvs` 命令检查物理卷是否空闲。
```
# pvs -o+pv_used
PV VG Fmt Attr PSize PFree Used
/dev/sda myvg lvm2 a- 75.00G 14.00G 61.00G
/dev/sdb myvg lvm2 a- 50.00G 45.00G 5.00G
/dev/sdc myvg lvm2 a- 17.15G 17.15G 0
/dev/sdd myvg lvm2 a- 60.00G 47.85G 12.15G
```
如果空闲,使用 `vgreduce` 命令从卷组中删除物理卷 `/dev/sdc`
```
# vgreduce myvg /dev/sdc
Removed "/dev/sdc" from volume group "vg01"
```
最后,运行 `pvremove` 命令从 LVM 配置中删除磁盘。现在,磁盘已经完全从 LVM 中移除,可以用于其他用途。
```
# pvremove /dev/sdc
Labels on physical volume "/dev/sdc" successfully wiped.
```
--------------------------------------------------------------------------------
via: https://www.2daygeek.com/linux-remove-delete-physical-volume-pv-from-volume-group-vg-in-lvm/
作者:[Magesh Maruthamuthu][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.2daygeek.com/author/magesh/
[b]: https://github.com/lujun9972
[1]: https://linux.cn/article-12670-1.html
[2]: https://linux.cn/article-12673-1.html
[3]: https://linux.cn/article-12740-1.html
[4]: https://www.2daygeek.com/wp-content/uploads/2020/10/remove-delete-physical-volume-pv-from-volume-group-vg-lvm-linux-2.png
[5]: https://www.2daygeek.com/scan-detect-luns-scsi-disks-on-redhat-centos-oracle-linux/

View File

@ -1,18 +1,18 @@
[#]: collector: (lujun9972)
[#]: translator: (rakino)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12721-1.html)
[#]: subject: (6 Essential Things To Do After Installing Manjaro Linux)
[#]: via: (https://itsfoss.com/things-to-do-after-installing-manjaro/)
[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
安装 Manjaro Linux 后做的 6 件事
安装 Manjaro Linux 后做的 6 件事
======
所以,你刚刚[全新安装了 Manjaro Linux][1],那么现在该做什么呢?
你刚刚[全新安装了 Manjaro Linux][1],那么现在该做什么呢?
下面是我推荐你在安装后进行的一些步骤。
下面是我推荐你在安装后进行的一些必不可少的步骤。
不过说实话,这些都是我在安装 Manjaro 后喜欢做的事,根据你的需求,步骤可能会有所不同。
@ -24,7 +24,7 @@
#### 1、设置最快的镜像
在更新系统之前,我建议先整理一下镜像列表。在刷新 Manjaro 系统和从软件仓库下载软件包的时候,优化后的镜像列表会对系统的性能产生明显的影响。
在更新系统之前,我建议先整理一下镜像列表。在刷新 Manjaro 系统和从软件仓库下载软件包的时候,优化后的镜像列表会对系统的性能产生明显的影响。
打开终端模拟器并输入以下命令:
@ -36,7 +36,7 @@ sudo pacman-mirrors --fasttrack
#### 2、更新系统
保持系统更新可以降低安全漏洞的发生机率,在安装新的软件之前也建议刷新系统的软件仓库。
保持系统更新可以降低安全漏洞的发生机率,在安装新的软件之前也建议刷新一下系统的软件仓库。
你可以用下面的命令来[更新 Manjaro 系统][5]
@ -46,13 +46,13 @@ sudo pacman -Syu
![][6]
#### 3、启用 AURSnap 以及 Flatpak 支持
#### 3、启用 AURSnap 以及 Flatpak 支持
[<ruby>Arch 用户仓库<rt>Arch User Repository</rt></ruby>AUR][7]是用户选择[基于 Arch Linux 的系统][8]的一个主要理由。你可以在 AUR 中访问到大量的附加软件。
译注AUR 中的 PKGBUILD 均为用户上传且未经审核,使用者需要自负责任,在构建软件包前请注意检查其中内容是否合理。)
LCTT 译注AUR 中的 PKGBUILD 均为用户上传且未经审核,使用者需要自负责任,在构建软件包前请注意检查其中内容是否合理。)
作为可选项,你可以直接在 Pamac 图形化软件包管理器中启用对 [Snap][9] 以及 [Flatpak][10] 的支持。
作为可选项,你可以直接在 Pacman 图形化软件包管理器中启用对 [Snap][9] 以及 [Flatpak][10] 的支持。
![][11]
@ -80,7 +80,7 @@ sudo systemctl enable fstrim.timer
mhwd-kernel -li
```
**安装新内核**(以最新的 5.8 版本内核为例)**:**
安装新内核(以最新的 5.8 版本内核为例):
```
sudo mhwd-kernel -i linux58
@ -96,9 +96,9 @@ sudo mhwd-kernel -i linux58
![][18]
#### 结论
### 结论
如果你想在一个预配置、为桌面优化的发行版上享受 Arch Linux 的优点,[Manjaro是一个很好的发行版][19]。虽然它预置了很多东西,但由于每个人设置和需求的不同,有几个步骤是不能提前完成的。
如果你想在一个预配置、为桌面优化的发行版上享受 Arch Linux 的优点,[Manjaro 是一个很好的发行版][19]。虽然它预置了很多东西,但由于每个人设置和需求的不同,有几个步骤是不能提前完成的。
除开已经提到的步骤,还有哪一步对你来说是必不可少的?请在下面的评论中告诉我们。
@ -109,7 +109,7 @@ via: https://itsfoss.com/things-to-do-after-installing-manjaro/
作者:[Dimitrios Savvopoulos][a]
选题:[lujun9972][b]
译者:[rakino](https://github.com/rakino)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -0,0 +1,88 @@
[#]: collector: (wxy)
[#]: translator: (gxlct008)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12718-1.html)
[#]: subject: (Could Microsoft be en route to dumping Windows in favor of Linux?)
[#]: via: (https://www.techrepublic.com/article/could-microsoft-be-en-route-to-dumping-windows-in-favor-of-linux/)
[#]: author: (Jack Wallen https://www.techrepublic.com/meet-the-team/us/jack-wallen/)
微软能否放弃 Windows 转向 Linux
======
> Jack Wallen 认为Microsoft Linux 是 Microsoft 桌面操作系统的下一个演进方向。他解释了为什么这将是一个对 Microsoft、IT 专业人士、用户和 Linux 社区的双赢。
![](https://tr1.cbsistatic.com/hub/i/r/2014/08/20/123daeb8-d6ce-4f0b-986e-225d55bf12e3/resize/770x/a693d56694587dbe5d025db7b8d79c48/linux-and-windows.jpg)
我尊敬的同事 Steven J. Vaughan-Nichols 在姊妹网站 ZDNet 上发表了一篇出色的文章,名为《[基于 Linux 的 Windows 非常有意义][1]》,他在文中讨论了 Eric S. Raymond 的[观点](https://linux.cn/article-12664-1.html)即我们正接近桌面战争的最后阶段。Vaughan-Nichols 猜测,下一个合乎逻辑的步骤是在 Linux 内核上运行的 Windows 界面。
这是有道理的,尤其是考虑到微软在 [Windows 的 Linux 子系统WSL][2] 上的努力。然而,从我过去几年所目睹的一切来看,我认为可以得出一个对微软更有意义的结论。
### Microsoft Linux: 为什么它是最好的解决方案
一度,微软的最大摇钱树是软件,确切地说是 Windows 和 Microsoft Office。但是就像科技行业中的所有事物一样进化也在发生而拒绝进化的科技公司失败了。
微软明白这一点,并且它已经进化了。一个恰当的例子是:[Microsoft Azure][4]。微软的云计算服务,以及 [AWS][5] 和 [Google Cloud][6] 已经成为这个不断变化的行业的巨大推动力。Azure 已成为微软新世界的摇钱树 —— 多到以至于这家在桌面电脑市场上享有垄断地位的公司已经开始意识到,或许还有更好的方式来利用桌面计算机。
这种优势很容易通过 Linux 来实现,但不是你可能想到的 Linux。Vaughan-Nichols 所建议的 Microsoft Linux 对于微软来说可能是一个很好的垫脚石,但我相信该公司需要做出一个更大的飞跃。我说的是登月规模的飞跃 —— 这将使所有参与者的生活变得更加轻松。
我说的是深入 Linux 领域。忘掉在 Linux 内核上运行 [Windows 10][7] 界面的桌面版本吧,最后承认 Microsoft Linux 可能是当今世界的最佳解决方案。
微软发布一个完整的 Linux 发行版将对所有参与者来说意味着更少的挫败感。微软可以将其在 Windows 10 桌面系统上的开发工作转移到一个更稳定、更可靠、更灵活、更经考验的桌面系统上来。微软可以从任意数量的桌面系统中选择自己的官方风格GNOME、KDE、Pantheon、Xfce、Mint、Cinnamon... 不胜枚举。微软可以按原样使用桌面,也可以为它们做出贡献,创造一些更符合用户习惯的东西。
### 开发:微软并没有摆脱困境
这并不意味着微软在开发方面将摆脱困境。微软也希望对 Wine 做出重大贡献,以确保其所有产品均可在兼容层上顺畅运行,并且默认集成到操作系统中,这样最终用户就不必为安装 Windows 应用程序做任何额外的工作。
### Windows 用户需要 Defender
微软开发团队也希望将 Windows Defender 移植到这个新的发行版中。等一等。什么?我真的是在暗示 Microsoft Linux 需要 Windows Defender 吗?是的,我确定。为什么?
最终用户仍然需要防范 <ruby>[网络钓鱼][8] 诈骗<rt>phishing scams</rt></ruby>、恶意 URL 和其他类型的攻击。普通的 Windows 用户可能不会意识到Linux 和安全使用实践的结合远比 Windows 10 和 Windows Defender 要安全得多。所以,是的,将 Windows Defender 移植到 Microsoft Linux 将是保持用户基础舒适的一个很好的步骤。
这些用户将很快了解在台式计算机上工作的感觉,而不必处理 Windows 操作系统带来的日常困扰。更新更流畅、更值得信赖、更安全,桌面更有意义。
### 微软、用户和 IT 专业人士的双赢
微软一直在尽其所能将用户从标准的基于客户端的软件迁移到云和其他托管解决方案,并且其软件摇钱树已经变成了以网络为中心和基于订阅的软件。所有这些 Linux 用户仍然可以使用 [Microsoft 365][10] 和它必须提供的任何其他 <ruby>[软件即服务][11]<rt>Software as a Service</rt></ruby>SaaS解决方案——所有这些都来自于 Linux 操作系统的舒适性和安全性。
这对微软和消费者而言是双赢的,因为这样 Windows 没有那么多令人头疼的事情要处理(通过捕获漏洞和对其专有解决方案进行安全补丁),消费者可以得到一个更可靠的解决方案而不会错过任何东西。
如果微软打对了牌,他们可以对 KDE 或几乎任何 Linux 桌面环境重新设置主题,使其与 Windows 10 界面没有太大区别。
如果布局得当消费者甚至可能都不知道其中的区别——“Windows 11” 将仅仅是 Microsoft 桌面操作系统的下一个演进版本。
说到胜利IT 专业人员将花费更少的时间来处理病毒、恶意软件和操作系统问题,而把更多的时间用于保持网络(以及为该网络供动力的服务器)的运行和安全上。
### 大卖场怎么办?
这是个关键的地方。为了让这一做法真正发挥作用,微软将不得不完全放弃 Windows转而使用自己风格的 Linux。基于同样的思路微软需要确保大卖场里的 PC 都安装了 Microsoft Linux 系统。没有半途而废的余地——微软必须全力以赴,以确保这次转型的成功。
一旦大卖场开始销售安装了 Microsoft Linux 的 PC 和笔记本电脑我预测这一举措对所有相关人员来说将会是一个巨大的成功。微软会被视为终于推出了一款值得消费者信赖的操作系统消费者将拥有一个这样的桌面操作系统它不会带来太多令人头疼的事情而会带来真正的生产力和乐趣Linux 社区最终将主导桌面计算机。
### Microsoft Linux时机已到
你可能会认为这个想法很疯狂,但如果你真的仔细想想,微软 Windows 的演进就是朝着这个方向发展的。为什么不绕过这个时间线的中途部分,而直接跳到一个为所有参与者带来成功的终极游戏呢? Microsoft Linux 正当其时。
---
via: https://www.techrepublic.com/article/could-microsoft-be-en-route-to-dumping-windows-in-favor-of-linux/
作者:[jack-wallen][a]
选题:[wxy][b]
译者:[gxlct008](https://github.com/gxlct008)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.techrepublic.com/meet-the-team/us/jack-wallen/
[b]: https://github.com/wxy
[1]: https://www.zdnet.com/article/linux-based-windows-makes-perfect-sense/
[2]: https://www.techrepublic.com/article/microsoft-older-windows-10-versions-now-get-to-run-windows-subsystem-for-linux-2/
[3]: https://www.techrepublic.com/resource-library/whitepapers/microsoft-build-2020-highlights/
[4]: https://www.techrepublic.com/article/microsoft-azure-the-smart-persons-guide/
[5]: https://www.techrepublic.com/article/amazon-web-services-the-smart-persons-guide/
[6]: https://www.techrepublic.com/article/google-cloud-platform-the-smart-persons-guide/
[7]: https://www.techrepublic.com/article/windows-10-the-smart-persons-guide/
[8]: https://www.techrepublic.com/article/phishing-and-spearphishing-a-cheat-sheet/
[9]: https://www.techrepublic.com/article/everything-a-linux-admin-needs-to-know-about-working-from-the-command-line/
[10]: https://www.techrepublic.com/article/microsoft-365-a-cheat-sheet/
[11]: https://www.techrepublic.com/article/software-as-a-service-saas-a-cheat-sheet/

View File

@ -0,0 +1,101 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12773-1.html)
[#]: subject: (Linux Jargon Buster: What is Display Manager in Linux?)
[#]: via: (https://itsfoss.com/display-manager/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
Linux 黑话解释:什么是显示管理器?
======
> 在这篇 Linux 黑话解释中,你将了解 Linux 中的显示管理器。它是桌面环境的一部分吗?它的作用是什么?
### 什么是 Linux 中的显示管理器?
简单来说,<ruby>显示管理器<rt>display manager</rt></ruby>DM是一个为你的 Linux 发行版提供图形登录功能的程序。它控制用户会话并管理用户认证。显示管理器会在你输入用户名和密码后,立即启动[显示服务器][1]并加载[桌面环境][2]。
显示管理器通常是登录界面的代名词。毕竟它是可见的部分。然而,可见的登录屏幕,也叫<ruby>欢迎页<rt>greeter</rt></ruby>,只是显示管理器的一部分。
![登录屏幕是显示管理器的可见部分][3]
像[各种桌面环境][4]和显示服务器一样,也有各种显示管理器。我们来看看它们。
### 不同的显示管理器
有些人认为显示管理器是桌面环境的一部分,但事实并非如此。它是一个独立的程序。
桌面环境可能会推荐某个显示管理器,但这并不意味着它不能与其它一些显示管理器一起工作。如果你曾经在同一个系统中安装过不止一个桌面环境,你会记得,登录界面(即显示管理器)允许你切换桌面环境。
![显示管理器可以与各种桌面环境配合使用][5]
虽然显示管理器不是桌面环境本身的一部分,但它往往与桌面环境由同一个开发团队开发。它也成为桌面环境的代表。
例如GNOME 桌面环境开发了 GDMGNOME Display Manager光看登录界面就会想到 GNOME 桌面环境。
![GNOME登录屏幕与GDM][6]
一些流行的显示管理器有:
* [GDM][7]<ruby>GNOME 显示管理器<rt>GNOME Display Manager</rt></ruby>GNOME 的首选。
* [SDDM][8]<ruby>简单桌面显示管理器<rt>Simple Desktop Display Manager</rt></ruby>)KDE 首选。
* LightDM由 Ubuntu 为 Unity 桌面开发。
### 显示管理器可以定制
有这么多的桌面环境可供选择,它们都有自己的显示管理器吗?不,不是这样的。
正如我之前提到的,可见的登录屏幕被称为欢迎页。这个欢迎页可以进行自定义来改变登录屏幕的外观。
事实上,许多发行版和/或桌面环境都制作了自己的欢迎页,以给用户提供一个类似于他们品牌的登录屏幕。
例如Mint 的 Cinnamon 桌面使用了 LightDM但有自己的欢迎页来给它更多的 Mint 式(或者我应该说是 Cinnamon的外观。
![基于 LightDM 的 Linux Mint 登录屏幕][9]
来看看 Kali Linux 的登录界面:
![Kali Linux 登录界面][10]
如果你喜欢编码和调整,你可以根据自己的喜好修改或编码自己的欢迎页。
### 改变显示管理器
如果你愿意,可以[更改显示管理器][11]。你需要先安装显示管理器。安装时你会看到切换显示管理器的选项。
![][12]
如果当时没有做切换,那么以后可以通过手动配置来改变显示管理器。不同的发行版重新配置显示管理器的方法略有不同,这不在本文讨论范围内。
### 结语
希望大家对 Linux 中的显示管理器这个术语有一点了解。本黑话解释系列的目的是用非技术性的语言解释常见的 Linux 俗语和技术术语,而不涉及太多的细节。
欢迎大家提出意见和建议。
--------------------------------------------------------------------------------
via: https://itsfoss.com/display-manager/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/display-server/
[2]: https://itsfoss.com/what-is-desktop-environment/
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2018/05/login-screen-opensuse.jpg?resize=800%2C474&ssl=1
[4]: https://itsfoss.com/best-linux-desktop-environments/
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/deepin-session-ubuntu.jpg?resize=800%2C414&ssl=1
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/06/Login-screen-1.png?resize=800%2C450&ssl=1
[7]: https://wiki.gnome.org/Projects/GDM
[8]: https://github.com/sddm
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/linux-mint-login-screen.jpg?resize=800%2C418&ssl=1
[10]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/10/kali-linux-login-screen.jpg?resize=799%2C450&ssl=1
[11]: https://itsfoss.com/switch-gdm-and-lightdm-in-ubuntu-14-04/
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2014/06/Switch_between_gdm_and_lightgdm_Ubuntu.jpeg?resize=700%2C448&ssl=1

View File

@ -0,0 +1,112 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12743-1.html)
[#]: subject: (Install MariaDB or MySQL on Linux)
[#]: via: (https://opensource.com/article/20/10/mariadb-mysql-linux)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
在 Linux 上安装 MariaDB 或 MySQL
======
> 开始在 Linux 系统上使用开源的 SQL 数据库吧。
![](https://img.linux.net.cn/data/attachment/album/202010/22/144122hkkqrs2dhi9c7kif.jpg)
[MariaDB][2] 和 [MySQL][3] 都是使用 SQL 的开源数据库并且共享相同的初始代码库。MariaDB 是 MySQL 的替代品,你可以使用相同的命令(`mysql`)与 MySQL 和 MariaDB 数据库进行交互。因此,本文同时适用于 MariaDB 和 MySQL。
### 安装 MariaDB
你可以使用你的 Linux 发行版的包管理器安装 MariaDB。在大多数发行版上MariaDB 分为服务器包和客户端包。服务器包提供了数据库“引擎”,即 MariaDB 在后台运行(通常在物理服务器上)的部分,它监听数据输入或数据输出请求。客户端包提供了 `mysql` 命令,你可以用它来与服务器通信。
在 RHEL、Fedora、CentOS 或类似的发行版上:
```
$ sudo dnf install mariadb mariadb-server
```
在 Debian、Ubuntu、Elementary 或类似的发行版上:
```
$ sudo apt install mariadb-client mariadb-server
```
其他操作系统可能会以不同的打包系统封装 MariaDB所以你可能需要搜索你的软件仓库来了解你的发行版的维护者是如何提供它的。
### 启动 MariaDB
因为 MariaDB 被设计为部分作为数据库服务器,它可以在一台计算机上运行,并从另一台计算机上进行管理。只要你能访问运行它的计算机,你就可以使用 `mysql` 命令来管理数据库。在写这篇文章时,我在本地计算机上运行了 MariaDB但你同样可与远程系统上托管的 MariaDB 数据库进行交互。
在启动 MariaDB 之前,你必须创建一个初始数据库。在初始化其文件结构时,你应该定义你希望 MariaDB 使用的用户。默认情况下MariaDB 使用当前用户,但你可能希望它使用一个专用的用户帐户。你的包管理器可能为你配置了一个系统用户和组。使用 `grep` 查找是否有一个 `mysql` 组:
```
$ grep mysql /etc/group
mysql:x:27:
```
你也可以在 `/etc/passwd` 中寻找这个专门的用户,但通常情况下,有组就会有用户。如果没有专门的 `mysql` 用户和组,可以在 `/etc/group` 中寻找一个明显的替代品(比如 `mariadb`)。如果没有,请阅读你的发行版文档来了解 MariaDB 是如何运行的。
假设你的安装使用 `mysql`,初始化数据库环境:
```
$ sudo mysql_install_db --user=mysql
Installing MariaDB/MySQL system tables in '/var/lib/mysql'...
OK
[...]
```
这一步的结果显示了接下来你必须执行的配置 MariaDB 的任务:
```
PLEASE REMEMBER TO SET A PASSWORD FOR THE MariaDB root USER !
To do so, start the server, then issue the following commands:
'/usr/bin/mysqladmin' -u root password 'new-password'
'/usr/bin/mysqladmin' -u root -h $(hostname) password 'new-password'
Alternatively you can run:
'/usr/bin/mysql_secure_installation'
which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.
```
使用你的发行版的初始化系统启动 MariaDB
```
$ sudo systemctl start mariadb
```
在启动时启用 MariaDB 服务器:
```
$ sudo systemctl enable --now mariadb
```
现在你已经有了一个 MariaDB 服务器,为它设置一个密码:
```
mysqladmin -u root password 'myreallysecurepassphrase'
mysqladmin -u root -h $(hostname) password 'myreallysecurepassphrase'
```
最后,如果你打算在生产服务器上使用它,请在上线前运行 `mysql_secure_installation` 命令。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/mariadb-mysql-linux
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [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/data_metrics_analytics_desktop_laptop.png?itok=9QXd7AUr (Person standing in front of a giant computer screen with numbers, data)
[2]: https://mariadb.org/
[3]: https://www.mysql.com/

View File

@ -0,0 +1,190 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12752-1.html)
[#]: subject: (2 Ways to Download Files From Linux Terminal)
[#]: via: (https://itsfoss.com/download-files-from-linux-terminal/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
2 种从 Linux 终端下载文件的方法
======
如果你被困在 Linux 终端,比如说在服务器上,如何从终端下载文件?
在 Linux 中是没有 `download` 命令的,但是有几个 Linux 命令可用于下载文件。
在这篇终端技巧中,你将学习两种在 Linux 中使用命令行下载文件的方法。
我在这里使用的是 Ubuntu但除了安装其余的命令同样适用于所有其他 Linux 发行版。
### 使用 wget 命令从 Linux 终端下载文件
![][1]
[wget][2] 也许是 Linux 和类 UNIX 系统中使用最多的命令行下载管理器。你可以使用 `wget` 下载一个文件、多个文件、整个目录甚至整个网站。
`wget` 是非交互式的,可以轻松地在后台工作。这意味着你可以很容易地在脚本中使用它,甚至构建像 [uGet 下载管理器][3]这样的工具。
让我们看看如何使用 `wget` 从终端下载文件。
#### 安装 wget
大多数 Linux 发行版都预装了 `wget`。它也可以在大多数发行版的仓库中找到,你可以使用发行版的包管理器轻松安装它。
在基于 Ubuntu 和 Debian 的发行版上,你可以使用 [apt 包管理器][4]命令:
```
sudo apt install wget
```
#### 使用 wget 下载文件或网页
你只需要提供文件或网页的 URL。它将在你所在的目录下以原始名下载该文件。
```
wget URL
```
![][5]
要下载多个文件,你必须将它们的 URL 保存在一个文本文件中,并将该文件作为输入提供给 `wget`,就像这样:
```
wget -i download_files.txt
```
#### 用 wget 下载不同名字的文件
你会注意到,网页在 `wget` 中几乎总是以 `index.html` 的形式保存。为下载的文件提供自定义名称是个好主意。
你可以在下载时使用 `-O` (大写字母 `O` 选项来提供输出文件名:
```
wget -O filename URL
```
![][6]
#### 用 wget 下载一个文件夹
假设你正在浏览一个 FTP 服务器,你需要下载整个目录,你可以使用递归选项 `-r`
```
wget -r ftp://server-address.com/directory
```
#### 使用 wget 下载整个网站
是的,你完全可以做到这一点。你可以用 `wget` 镜像整个网站。我说的下载整个网站是指整个面向公众的网站结构。
虽然你可以直接使用镜像选项 `-m`,但最好加上:
* `convert-links`:链接将被转换,使内部链接指向下载的资源,而不是网站。
* `page-requisites`:下载额外的东西,如样式表,使页面在离线状态下看起来更好。
```
wget -m --convert-links --page-requisites website_address
```
![][7]
#### 额外提示:恢复未完成的下载
如果你因为某些原因按 `CTRL-C` 键中止了下载,你可以用选项 `-c` 恢复之前的下载:
```
wget -c
```
### 使用 curl 在 Linux 命令行中下载文件
`wget` 一样,[curl][8] 也是 Linux 终端中最常用的下载文件的命令之一。[使用 curl][9] 的方法有很多,但我在这里只关注简单的下载。
#### 安装 curl
虽然 `curl` 并不是预装的,但在大多数发行版的官方仓库中都有。你可以使用你的发行版的包管理器来安装它。
要[在 Ubuntu][10] 和其他基于 Debian 的发行版上安装 `curl`,请使用以下命令:
```
sudo apt install curl
```
#### 使用 curl 下载文件或网页
如果你在使用 `curl` 命令时没有在 URL 中带任何选项,它就会读取文件并打印在终端上。
要在 Linux 终端中使用 `curl` 命令下载文件,你必须使用 `-O`(大写字母 `O`)选项:
```
curl -O URL
```
![][11]
在 Linux 中,用 `curl` 下载多个文件是比较简单的。你只需要指定多个 URL 即可:
```
curl -O URL1 URL2 URL3
```
请记住,`curl` 不像 `wget` 那么简单。`wget` 可以将网页保存为 `index.html``curl` 却会抱怨远程文件没有网页的名字。你必须按照下一节的描述用一个自定义的名字来保存它。
#### 用不同的名字下载文件
这可能会让人感到困惑,但如果要为下载的文件提供一个自定义的名称(而不是原始名称),你必须使用 `-o`(小写 `O`)选项:
```
curl -o filename URL
```
![][12]
有些时候,`curl` 并不能像你期望的那样下载文件,你必须使用选项 `-L`(代表位置)来正确下载。这是因为有些时候,链接会重定向到其他链接,而使用选项 `-L`,它就会跟随最终的链接。
#### 用 curl 暂停和恢复下载
`wget` 一样,你也可以用 `curl``-c` 选项恢复暂停的下载:
```
curl -c URL
```
### 总结
和以往一样,在 Linux 中做同一件事有多种方法。从终端下载文件也不例外。
`wget``curl` 只是 Linux 中最流行的两个下载文件的命令。还有更多这样的命令行工具。基于终端的网络浏览器,如 [elinks][13]、[w3m][14] 等也可以用于在命令行下载文件。
就个人而言,对于一个简单的下载,我更喜欢使用 `wget` 而不是 `curl`。它更简单,也不会让你感到困惑,因为你可能很难理解为什么 `curl` 不能以预期的格式下载文件。
欢迎你的反馈和建议。
--------------------------------------------------------------------------------
via: https://itsfoss.com/download-files-from-linux-terminal/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/Download-Files-from-Linux-terminal.png?resize=800%2C450&ssl=1
[2]: https://www.gnu.org/software/wget/
[3]: https://itsfoss.com/install-latest-uget-ubuntu-linux-mint/
[4]: https://itsfoss.com/apt-command-guide/
[5]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/10/download-file-in-linux-terminal-using-wget.png?resize=795%2C418&ssl=1
[6]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/download-file-in-linux-terminal-using-wget-2.png?resize=795%2C418&ssl=1
[7]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/download-entire-website-using-wget.png?resize=795%2C418&ssl=1
[8]: https://curl.haxx.se/
[9]: https://linuxhandbook.com/curl-command-examples/
[10]: https://itsfoss.com/install-curl-ubuntu/
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/10/download-files-in-linux-using-curl.png?resize=795%2C418&ssl=1
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/download-files-in-linux-using-curl-1.png?resize=795%2C418&ssl=1
[13]: http://elinks.or.cz/
[14]: http://w3m.sourceforge.net/

View File

@ -0,0 +1,92 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12759-1.html)
[#]: subject: (MellowPlayer is a Desktop App for Various Streaming Music Services)
[#]: via: (https://itsfoss.com/mellow-player/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
MellowPlayer一款用于各种流媒体音乐服务的桌面应用
======
> MellowPlayer 是一个自由开源的桌面应用,可以让你在 Linux 和 Windows 上整合基于网络的音乐流媒体服务。
![][8]
毋庸置疑,很多用户都喜欢使用流媒体服务来收听自己喜欢的音乐,而不是从商店购买单首音乐或者下载收藏。
当然,流媒体服务可以让你探索新的音乐,帮助艺术家轻松传播到更多的听众。但是,由于有许多的音乐流媒体服务([Soundcloud][1]、[Spotify][2]、[YouTube Music][3]、[Amazon Music][4] 等),因此当在使用电脑时,要有效地使用它们往往会变得很麻烦。
你可以[在 Linux 上安装 Spotify][5],但没有 Amazon Music 的桌面应用,所以,有可能你无法从单一门户管理流媒体服务。
如果一个桌面应用可以让你同时在 Windows 和 Linux 上免费整合流媒体服务呢?在本文中,我将介绍这样一款应用:[MellowPlayer][6]。
### MellowPlayer: 集成各种流媒体音乐服务的开源应用
![][7]
MellowPlayer 是一款自由开源的跨平台桌面应用,它可以让你整合多个流媒体服务,并在一个界面上管理它们。
你可以整合多个支持的流媒体服务。你还可以从每个服务中获得一定程度的控制权,来调整你的体验。例如,你可以设置在 YouTube 上自动跳过或静音广告。
对 Windows 和 Linux 的跨平台支持绝对是一个加分项。
除了能够管理流媒体服务外,它还将播放器与系统托盘整合在一起来轻松控制音乐。这意味着你可以使用键盘上的媒体键来控制音乐播放器。
另外值得一提的是,你只要在应用内自己创建一个插件,就可以添加一个官方不支持的新服务。为了让你对它有更多的了解,下面就让我重点介绍一下所有的主要特点。
### MellowPlayer 的特点
* 跨平台 Windows 和 Linux
* 自由且开源
* 基于插件的应用,让你可以通过创建一个插件来添加新的服务
* 将服务作为本地桌面应用与系统托盘整合
* 支持热键
* 支持通知
* 收听历史
### 在 Linux 上安装 MellowPlayer
![][9]
MellowPlayer 是以 [Flatpak 包][10]的形式提供的。我知道这让一些人很失望,但它在 Linux 中只有 FlaptakWindows 中只有一个可执行文件。如果你不知道,请按照我们的[在 Linux 上使用 Flatpak][11] 指南来开始使用。
- [下载 MellowPlayer][12]
### 总结
MellowPlayer 是一款方便的桌面应用,适合经常涉猎多种流媒体音乐服务的用户使用。尽管根据我的测试,它在 SoundCloud、YouTube 和 Spotify 上都能正常工作,但我确实注意到,当我试图重新调整窗口大小时,应用会崩溃,只是在此提醒一下。你可以在它的 [GitLab 页面][13]上了解更多关于它的内容。
还有两个类似的应用,可以让你播放多个流媒体音乐服务。[Nuvola][14] 和 [Nuclear Music Player][15]。你可能会想看看它们。
你试过 MellowPlayer 吗?欢迎在下方评论中分享你的想法。
--------------------------------------------------------------------------------
via: https://itsfoss.com/mellow-player/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://soundcloud.com
[2]: https://www.spotify.com
[3]: https://music.youtube.com
[4]: https://music.amazon.com/home
[5]: https://itsfoss.com/install-spotify-ubuntu-linux/
[6]: https://colinduquesnoy.gitlab.io/MellowPlayer/
[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/mellowplayer-screenshot.jpg?resize=800%2C439&ssl=1
[8]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/mellowplayer.png?resize=800%2C442&ssl=1
[9]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/mellowplayer-system-integration.jpg?resize=800%2C438&ssl=1
[10]: https://flathub.org/apps/details/com.gitlab.ColinDuquesnoy.MellowPlayer
[11]: https://itsfoss.com/flatpak-guide/
[12]: https://colinduquesnoy.gitlab.io/MellowPlayer/#features
[13]: https://gitlab.com/ColinDuquesnoy/MellowPlayer
[14]: https://itsfoss.com/nuvola-music-player/
[15]: https://itsfoss.com/nuclear-music-player-linux/

View File

@ -0,0 +1,95 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12769-1.html)
[#]: subject: (Try Linux on any computer with this bootable USB tool)
[#]: via: (https://opensource.com/article/20/10/fedora-media-writer)
[#]: author: (Sumantro Mukherjee https://opensource.com/users/sumantro)
用这个创建可引导 USB 的工具在电脑上尝试 Linux
======
> Fedora Media Writer 是创建临场版 USB 以尝试 Linux 的方便方法。
![](https://img.linux.net.cn/data/attachment/album/202010/30/122142c1cmcv7cxgjmw5vw.jpg)
[Fedora Media Writer][2] 是一个小巧、轻量、全面的工具,它简化了 Linux 的入门体验。它可以下载 Fedora 的 Workstation 或 Server 版本并写入到一个可以在任何系统上引导的 USB 驱动器上,使你无需将其安装到硬盘上就可以试用 Fedora Linux。
Media Writer 工具可以用来创建一个<ruby>临场体验的<rt>Live</rt></ruby>、可引导的 USB 驱动器。在你的平台上安装 Fedora Media Writer 应用后,你可以下载并烧录最新的 Fedora Workstation 或 Server 稳定版,也可以选择烧录你下载的任何其他镜像。而且它并不局限于英特尔 64 位设备。它还可以用于 ARM 设备,如[树莓派][3],这些设备日益变得更加强大和有用。
![Fedora Media Writer main screen][4]
### 安装 Fedora Media Writer
[安装 Fedora Media Writer][6] 有几种方式。你可以通过 GitHub [从源码编译][7]、下载 MacOS 或 Windows 版本、使用 `dnf``yum` 安装 RPM 包,或者以 Flatpak 的形式获得。
在 Fedora 上:
```
$ sudo dnf install mediawriter
```
最新版本请参见 GitHub 仓库的[发布][8]部分。
### 准备好你的媒体介质
首先,你需要一个 USB 驱动器来安装你的 Linux 操作系统。这就是 Fedora Media Writer 要烧录的设备。这个驱动器必须是空白或可擦除的,因为 **该 USB 驱动器上的所有数据都会被删除**。如果有任何数据,哪怕只是一个文件,如果你不想丢失,那么你必须在继续之前备份它!
确认你的 USB 驱动器是可擦除的之后,将它插入你的电脑并启动 Fedora Media Writer。
### 使用 Fedora Media Writer
当你启动 Fedora Media Writer 时,你会看到一个页面,提示你从互联网上获取一个可引导的镜像,或者从你的硬盘上加载一个自定义镜像。第一个选择是 Fedora 的最新版本。Workstation 版本适用于台式机和笔记本电脑Server 版本适用于虚拟化、机架服务器或任何你想作为服务器运行的情况。
如果你选择了 Fedora 镜像Media Writer 会下载一个光盘镜像(通常称为 “iso”文件扩展名为 .iso并将其保存到你的下载文件夹中这样你就可以重复使用它来烧录另一个驱动器。
![Select your image][9]
另外还有 Fedora Spins这是来自 Fedora 社区的镜像,它旨在满足小众的兴趣。例如,如果你是 [MATE 桌面][10]的粉丝,那么你会很高兴地发现 Media Writer 提供了 MATE spin。它有很多所以请滚动查看所有的选择。如果你是 Linux 的新手,不要被吓到或感到困惑:这些额外的选项是为老用户准备的,这些用户除了默认的选项外,还发展出了自己的偏好,所以对你来说,只使用 Workstation 或 Server 选项就行,这取决于你是想把 Fedora 作为一个桌面还是作为一个服务器操作系统来运行。
如果你需要一个与你当前使用的 CPU 不同架构的镜像,从窗口右上角的下拉菜单中选择 CPU 架构。
如果你已经将镜像保存在硬盘上请选择“Custom Image”选项并选择你要烧录到 USB 的发行版的 .iso 文件。
### 写入 USB 驱动器
当你下载或选择了一个镜像,你必须确认你要将该镜像写入驱动器。
驱动器选择下拉菜单只显示了外部驱动器,所以你不会意外地覆盖自己的硬盘驱动器。这是 Fedora Media Writer 的一个重要功能,它比你在网上看到的许多手动说明要安全得多。然而,如果你的计算机上连接了多个外部驱动器,除了你想覆盖的那个,你应该将它们全部移除,以增加安全性。
选择你要安装镜像的驱动器然后单击“Write to Disk”按钮。
![Media write][11]
稍等一会儿,镜像就会被写入到你的驱动器,然后可以看看 Don Watkins 对[如何从 USB 驱动器启动到 Linux][12]的出色介绍。
### 开始使用 Linux
Fedora Media Writer 是一种将 Fedora Workstation 或 Server或任何 Linux 发行版烧录到 USB 驱动器的方法,因此你可以在安装它到设备上之前试用它。试试吧,并在评论中分享你的经验和问题。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/fedora-media-writer
作者:[Sumantro Mukherjee][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/sumantro
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/usb-hardware.png?itok=ROPtNZ5V (Multiple USB plugs in different colors)
[2]: https://github.com/FedoraQt/MediaWriter
[3]: https://fedoraproject.org/wiki/Architectures/ARM/Raspberry_Pi
[4]: https://opensource.com/sites/default/files/uploads/fmw_mainscreen.png (Fedora Media Writer main screen)
[5]: https://creativecommons.org/licenses/by-sa/4.0/
[6]: https://docs.fedoraproject.org/en-US/fedora/f32/install-guide/install/Preparing_for_Installation/#_fedora_media_writer
[7]: https://github.com/FedoraQt/MediaWriter#building
[8]: https://github.com/FedoraQt/MediaWriter/releases
[9]: https://opensource.com/sites/default/files/mediawriter-image.png
[10]: https://opensource.com/article/19/12/mate-linux-desktop
[11]: https://opensource.com/sites/default/files/mediawriter-write.png (Media write)
[12]: https://opensource.com/article/20/4/first-linux-computer

View File

@ -0,0 +1,122 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12754-1.html)
[#]: subject: (Set up ZFS on Linux with yum)
[#]: via: (https://opensource.com/article/20/10/zfs-dnf)
[#]: author: (Sheng Mao https://opensource.com/users/ivzhh)
在 Linux 上使用 yum 设置 ZFS
======
> 在 Fedora 上使用 yum 仓库来获取最新的 ZFS 特性。
![](https://img.linux.net.cn/data/attachment/album/202010/26/103028g9q3v3e391c9b62v.jpg)
我是一名 Fedora Linux 用户,我每天都会运行 `yum upgrade`。虽然这个习惯使我能够运行所有最新的软件([Fedora 的四个基础][2]之一的 “First” ,它也做到了),但它也会提醒 [ZFS][3] 存储平台和新内核之间的不兼容性。
作为一名开发者,有时我需要最新的 ZFS 分支的新特性。例如ZFS 2.0.0 包含了一个令人兴奋的新功能,它大大[提高了 ZVOL 同步性能][4],这对我这个 KVM 用户来说至关重要。但这意味着,如果我想使用 2.0.0 分支,我必须自己构建 ZFS。
起初,我只是在每次内核更新后从它的 Git 仓库中手动编译 ZFS。如果我忘记了ZFS 就会在下次启动时无法被识别。幸运的是,我很快就学会了如何为 ZFS 设置动态内核模块支持 [DKMS][5])。然而,这个解决方案并不完美。首先,它没有利用强大的 [yum][6] 系统,而这个系统可以帮助解决依赖关系和升级。此外,使用 `yum` 在你自己的包和上游包之间进行切换是非常容易的。
在本文中,我将演示如何设置 `yum` 仓库来打包 ZFS。这个方案有两个步骤
1. 从 ZFS 的 Git 仓库中创建 RPM 包。
2. 建立一个 `yum` 仓库来托管这些包。
### 创建 RPM 包
要创建 RPM 包,你需要安装 RPM 工具链。`yum` 提供了一个组来捆绑安装这些工具:
```
sudo dnf group install 'C Development Tools and Libraries' 'RPM Development Tools'
```
安装完这些之后,你必须从 ZFS Git 仓库中安装构建 ZFS 所需的所有包。这些包属于三个组:
1. [Autotools][7],用于从平台配置中生成构建文件。
2. 用于构建 ZFS 内核和用户态工具的库。
3. 构建 RPM 包的库。
```
sudo dnf install libtool autoconf automake gettext createrepo \
    libuuid-devel libblkid-devel openssl-devel libtirpc-devel \
    lz4-devel libzstd-devel zlib-devel \
    kernel-devel elfutils-libelf-devel \
    libaio-devel libattr-devel libudev-devel \
    python3-devel libffi-devel
```
现在你已经准备好创建你自己的包了。
### 构建 OpenZFS
[OpenZFS][8] 提供了优秀的基础设施。要构建它:
1. 用 `git` 克隆仓库,并切换到你希望使用的分支/标签。
2. 运行 Autotools 生成一个 makefile。
3. 运行 `make rpm`如果一切正常RPM 文件将被放置在 `build` 文件夹中。
```
$ git clone --branch=zfs-2.0.0-rc3 <https://github.com/openzfs/zfs.git> zfs
$ cd zfs
$ ./autogen.sh
$ ./configure
$ make rpm
```
### 建立一个 yum 仓库
`yum` 中,仓库是一个服务器或本地路径,包括元数据和 RPM 文件。用户设置一个 INI 配置文件,`yum` 命令会自动解析元数据并下载相应的软件包。
Fedora 提供了 `createrepo` 工具来设置 `yum` 仓库。首先,创建仓库,并将 ZFS 文件夹中的所有 RPM 文件复制到仓库中。然后运行 `createrepo --update` 将所有的包加入到元数据中。
```
$ sudo mkdir -p /var/lib/zfs.repo
$ sudo createrepo /var/lib/zfs.repo
$ sudo cp *.rpm /var/lib/zfs.repo/
$ sudo createrepo --update /var/lib/zfs.repo
```
`/etc/yum.repos.d` 中创建一个新的配置文件来包含仓库路径:
```
$ echo \
"[zfs-local]\\nname=ZFS Local\\nbaseurl=file:///var/lib/zfs.repo\\nenabled=1\\ngpgcheck=0" |\
sudo tee /etc/yum.repos.d/zfs-local.repo
$ sudo dnf --repo=zfs-local list available --refresh
```
终于完成了!你已经有了一个可以使用的 `yum` 仓库和 ZFS 包。现在你只需要安装它们。
```
$ sudo dnf install zfs
$ sudo /sbin/modprobe zfs
```
运行 `sudo zfs version` 来查看你的用户态和内核工具的版本。恭喜!你拥有了 [Fedora 中的 ZFS][9]。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/zfs-dnf
作者:[Sheng Mao][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/ivzhh
[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://docs.fedoraproject.org/en-US/project/#_what_is_fedora_all_about
[3]: https://zfsonlinux.org/
[4]: https://www.phoronix.com/scan.php?page=news_item&px=OpenZFS-3x-Boost-Sync-ZVOL
[5]: https://www.linuxjournal.com/article/6896
[6]: https://en.wikipedia.org/wiki/Yum_%28software%29
[7]: https://opensource.com/article/19/7/introduction-gnu-autotools
[8]: https://openzfs.org/wiki/Main_Page
[9]: https://openzfs.github.io/openzfs-docs/Getting%20Started/Fedora.html

View File

@ -0,0 +1,93 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12764-1.html)
[#]: subject: (Fedora 33 is officially here!)
[#]: via: (https://fedoramagazine.org/announcing-fedora-33/)
[#]: author: (Matthew Miller https://fedoramagazine.org/author/mattdm/)
Fedora 33 正式发布了
======
![][1]
> 本文译自 Fedora 官方发布公告。
今天,我很兴奋地与大家分享数千名 Fedora 项目贡献者辛勤工作的成果:我们的最新版本 Fedora 33 来了! 这是一个有着很多变化的大版本,但我相信所有这些工作也会让您感到舒适,实现我们的目标:即为您带来最新的稳定、强大、健壮的自由和开源软件,并提供许多易于使用的产品。 
如果您不想耽误时间,直接体验,现在就去 <https://getfedora.org/> 下载吧,欲了解详情请继续阅读!
### 找到适合您的 Fedora 风味!
Fedora Edition 是针对桌面、服务器和云环境中各种“体现”特定用途的目标产品,现在它也适用于物联网。
Fedora Workstation 专注于桌面,尤其是面向那些想要“只管去用”的 Linux 操作系统体验的软件开发者。这个版本的特点是 [GNOME 3.38][2],它一如既往地有很多很棒的改进。新增的 Tour 应用可以帮助新用户学习它们的操作方式。和我们所有其他面向桌面的变体一样Fedora Workstation 现在使用 [BTRFS 作为默认文件系统][3]。这些发布的版本中带来了很多伟大的增强功能这个先进的文件系统为之奠定了基础。为了您的视觉享受Fedora 33 Workstation 现在默认提供了一个动画背景(它会基于一天中的时间变化)。
Fedora CoreOS 是一个新兴的 Fedora 版本。它是一个自动更新的、最小化的操作系统,用于安全地、大规模地运行容器化工作负载。它提供了几个[更新流][4],可以遵循大致每两周一次的自动更新。目前 **next** 流是基于 Fedora 33 的,**testing** 和 **stable** 流后继也会跟进。您可以从[下载页面][5]中找到关于跟随 **next** 流发布的工件的信息,并在 [Fedora CoreOS 文档][6]中找到关于如何使用这些工件的信息。
新晋升为 Edition 状态的 [Fedora IoT][7]为物联网生态系统和边缘计算用例提供了坚实的基础。在许多功能之外Fedora 33 IoT 还引入了<ruby>平台抽象安全<rt>Platform AbstRaction for SECurity</rt></ruby>PARSEC这是一个开源倡议以平台无关的方式为硬件安全和加密服务提供了通用 API。
当然,我们制作的不仅仅是“官方版本”,还有 [Fedora Spin][8]和 [Lab][9]。[Fedora Spin][8] 和 [Lab][9] 针对不同的受众和用例,包括 [Fedora CompNeuro][10],它为神经科学带来了大量的开源计算建模工具,以及 [KDE Plasma][11] 和 [Xfce][12]等桌面环境。 
此外,别忘了我们还有备用架构:[ARM AArch64、Power 和 S390x][13]。在 Fedora 33 中提供的新功能AArch64 用户可以使用 .NET Core 语言进行跨平台开发。我们改进了对 Pine64 设备、NVidia Jetson 64 位平台以及 Rockchip 片上系统SoC设备的支持包括 Rock960、RockPro64 和 Rock64。不过有个最新的说明在其中一些设备上可能会出现启动问题。从现有的 Fedora 32 升级是没问题的。更多信息将在[常见错误][14]页面上公布。)
我们也很高兴地宣布Fedora 云镜像和 Fedora CoreOS 将首次与 Fedora 33 一起在亚马逊的 [AWS 市场][15] 中提供。Fedora 云镜像在亚马逊云中已经存在了十多年,您可以通过 AMI ID 或[点击一下][16]来启动我们的官方镜像。该市场提供了获得同样东西的另一种方式,显著扩大了 Fedora 的知名度。这也将使我们的云镜像可以更快地在新的 AWS 区域中可用。特别感谢 David Duncan 让这一切成为现实!
### 常规改进
无论您使用的是哪种版本的 Fedora您都会得到开源世界提供的最新版本。遵循我们的 [First][17] 原则,我们更新了关键的编程语言和系统库包,包括 Python 3.9、Ruby on Rails 6.0 和 Perl 5.32。在 Fedora KDE 中,我们沿用了 Fedora 32 Workstation 中的工作,默认启用了 EarlyOOM 服务,以改善低内存情况下的用户体验。
为了让 Fedora 的默认体验更好,我们将 nano 设置为默认编辑器。nano 是一个对新用户友好的编辑器。当然,那些想要像 vi 这样强大的编辑器的用户可以自己设置默认编辑器。
我们很高兴您能试用新版本! 前往 <https://getfedora.org/> 并立即下载它。或者如果您已经在运行 Fedora 操作系统,请按照这个简单的[升级说明][18]进行升级。关于 Fedora 33 新特性的更多信息,请参见[发布说明][19]。
### 关于安全启动的说明
<ruby>安全启动<rt>Secure Boot</rt></ruby>是一种安全标准,它确保只有官方签署的操作系统软件才能加载到您的计算机上。这对于防止持久恶意软件非常重要,因为这些恶意软件可能会隐藏在您的计算机固件中,甚至在重新安装操作系统时也能存活。然而,在 [Boot Hole][20] 漏洞发生后,用于签署 Fedora <ruby>引导加载器<rt>Bootloader</rt></ruby>软件的加密证书将被撤销,并被新的证书取代。由于这将产生大范围的影响,撤销应该要到 2021 年第二季度或更晚才会广泛推行。
然而一些用户可能已经从其他操作系统或固件更新中收到了这种撤销。在这种情况下Fedora 将不能在启用了安全启动时进行安装。要说明的是,这不会影响大多数用户。如果它确实影响到了您,您可以暂时禁用安全启动。我们会在大范围的证书撤销之前发布一个用新证书签署的更新,在所有支持的版本上都可以使用,到那时,安全启动应该可以重新启用。
### 万一出现问题时……
如果您遇到问题,请查看 [Fedora 33 常见错误][14]页面;如果您有疑问,请访问我们的 [Ask Fedora][21] 用户支持平台。
### 谢谢大家
感谢在这个发布周期中为 Fedora 项目做出贡献的成千上万的人尤其是那些在疫情大流行期间为使这个版本准时发布而付出额外努力的人。Fedora 是一个社区,很高兴看到我们如此互相支持。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/announcing-fedora-33/
作者:[Matthew Miller][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://fedoramagazine.org/author/mattdm/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2020/10/f33-final-816x345.jpg
[2]: https://www.gnome.org/news/2020/09/gnome-3-38-released/
[3]: https://fedoramagazine.org/btrfs-coming-to-fedora-33/
[4]: https://docs.fedoraproject.org/en-US/fedora-coreos/update-streams/
[5]: https://getfedora.org/en/coreos/download?stream=next
[6]: https://docs.fedoraproject.org/en-US/fedora-coreos/getting-started/
[7]: https://getfedora.org/iot
[8]: https://spins.fedoraproject.org/
[9]: https://labs.fedoraproject.org/
[10]: https://labs.fedoraproject.org/en/comp-neuro/
[11]: https://spins.fedoraproject.org/en/kde/
[12]: https://spins.fedoraproject.org/en/xfce/
[13]: https://alt.fedoraproject.org/alt/
[14]: https://fedoraproject.org/wiki/Common_F33_bugs
[15]: https://aws.amazon.com/marketplace
[16]: https://getfedora.org/en/coreos/download?tab=cloud_launchable&stream=stable
[17]: https://docs.fedoraproject.org/en-US/project/#_first
[18]: https://docs.fedoraproject.org/en-US/quick-docs/upgrading/
[19]: https://docs.fedoraproject.org/en-US/fedora/f33/release-notes/
[20]: https://access.redhat.com/security/vulnerabilities/grub2bootloader
[21]: http://ask.fedoraproject.org

View File

@ -0,0 +1,434 @@
[#]: collector: (lujun9972)
[#]: translator: (gxlct008)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12782-1.html)
[#]: subject: (Go on very small hardware Part 3)
[#]: via: (https://ziutek.github.io/2018/05/03/go_on_very_small_hardware3.html)
[#]: author: (Michał Derkacz )
Go 语言在极小硬件上的运用(三)
======
![](https://img.linux.net.cn/data/attachment/album/202010/24/090026to9c9sweyrw9ww37.png)
在本系列的 [第一][3] 和 [第二][4] 部分中讨论的大多数示例都是以某种方式闪烁的 LED。起初它可能很有趣但是一段时间后变得有些无聊。让我们做些更有趣的事情……
…让我们点亮更多的 LED
![STM32F030F4P6][1]
### WS281x LED
[WS281x][5] RGB LED及其克隆品非常受欢迎。你可以以单个元素购买、链成长条或组装成矩阵、环或其他形状。
![WS2812B][6]
它们可以串联连接,基于这个事实,你可以只用 MCU 的单个引脚就可以控制一个很长的 LED 灯条。不幸的是,它们的内部控制器使用的物理协议不能直接适用于你在 MCU 中可以找到的任何外围设备。你必须使用 <ruby>位脉冲<rt>bit-banging</rt></ruby>或以特殊方式使用可用的外设。
哪种可用的解决方案最有效取决于同时控制的 LED 灯条数量。如果你必须驱动 4 到 16 个灯条,那么最有效的方法是 [使用定时器和 DMA][7](请不要忽略这篇文章末尾的链接)。
如果只需要控制一个或两个灯条,请使用可用的 SPI 或 UART 外设。对于 SPI你只能在发送的一个字节中编码两个 WS281x 位。由于巧妙地使用了起始位和停止位UART 允许更密集的编码:每发送一个字节 3 位。
我在 [此站点][8] 上找到了有关 UART 协议如何适用于 WS281x 协议的最佳解释。如果你不懂波兰语,这里是 [英文翻译][9]。
基于 WS281x 的 LED 仍然是最受欢迎的,但市场上也有 SPI 控制的 LED[APA102][10]、[SK9822][11]。关于它们的三篇有趣的文章在这里:[1][12]、[2][13]、[3][14]。
### LED 环
市场上有许多基于 WS2812 的环。我有一个这样的:
![WS2812B][15]
它具有 24 个可单独寻址的 RGB LEDWS2812B并暴露出四个端子GND、5V、DI 和 DO。通过将 DI数据输入端子连接到上一个的 DO数据输出端子可以链接更多的环或其他基于 WS2812 的东西。
让我们将这个环连接到我们的 STM32F030 板上。我们将使用基于 UART 的驱动程序,因此 DI 应连接到 UART 接头连接器上的 TXD 引脚。 WS2812B LED 需要至少 3.5V 的电源。 24 个 LED 会消耗大量电流,因此在编程/调试期间,最好将环上的 GND 和 5V 端子直接连接到 ST-LINK 编程器上可用的 GND 和 5V 引脚:
![WS2812B][16]
我们的 STM32F030F4P6 MCU 和整个 STM32 F0、F3、F7、L4 系列具有 F1、F4、L1 MCU 不具备的一项重要功能:它可以反转 UART 信号,因此我们可以将环直接连接到 UART TXD 引脚。如果你不知道我们需要这种反转,那么你可能没有读过我上面提到的 [文章][9]。
因此,你不能以这种方式使用流行的 [Blue Pill][17] 或 [STM32F4-DISCOVERY][18]。使用其 SPI 外设或外部反相器。有关使用 SPI 的 NUCLEO-F411RE请参见 [圣诞树灯][19] 项目作为 UART + 逆变器的示例或 [WS2812示例][20]。
顺便说一下,大多数 DISCOVERY 板可能还有一个问题:它们在 VDD = 3V 而不是 3.3V 的情况下工作。 对于高 DIWS281x 至少要求电源电压 * 0.7。如果是 5V 电源,则为 3.5V;如果是 4.7V 电源,则为 3.3V;可在 DISCOVERY 的 5V 引脚上找到。如你所见,即使在我们的情况下,第一个 LED 的工作电压也低于规格 0.2V。对于 DISCOVERY 板,如果供电 4.7V,它将工作在低于规格的 0.3V 下;如果供电 5V它将工作在低于规格 0.5V 下。
让我们结束这段冗长的介绍并转到代码:
```
package main
import (
"delay"
"math/rand"
"rtos"
"led"
"led/ws281x/wsuart"
"stm32/hal/dma"
"stm32/hal/gpio"
"stm32/hal/irq"
"stm32/hal/system"
"stm32/hal/system/timer/systick"
"stm32/hal/usart"
)
var tts *usart.Driver
func init() {
system.SetupPLL(8, 1, 48/8)
systick.Setup(2e6)
gpio.A.EnableClock(true)
tx := gpio.A.Pin(9)
tx.Setup(&gpio.Config{Mode: gpio.Alt})
tx.SetAltFunc(gpio.USART1_AF1)
d := dma.DMA1
d.EnableClock(true)
tts = usart.NewDriver(usart.USART1, d.Channel(2, 0), nil, nil)
tts.Periph().EnableClock(true)
tts.Periph().SetBaudRate(3000000000 / 1390)
tts.Periph().SetConf2(usart.TxInv)
tts.Periph().Enable()
tts.EnableTx()
rtos.IRQ(irq.USART1).Enable()
rtos.IRQ(irq.DMA1_Channel2_3).Enable()
}
func main() {
var rnd rand.XorShift64
rnd.Seed(1)
rgb := wsuart.GRB
strip := wsuart.Make(24)
black := rgb.Pixel(0)
for {
c := led.Color(rnd.Uint32()).Scale(127)
pixel := rgb.Pixel(c)
for i := range strip {
strip[i] = pixel
tts.Write(strip.Bytes())
delay.Millisec(40)
}
for i := range strip {
strip[i] = black
tts.Write(strip.Bytes())
delay.Millisec(20)
}
}
}
func ttsISR() {
tts.ISR()
}
func ttsDMAISR() {
tts.TxDMAISR()
}
//c:__attribute__((section(".ISRs")))
var ISRs = [...]func(){
irq.USART1: ttsISR,
irq.DMA1_Channel2_3: ttsDMAISR,
}
```
#### 导入部分
与前面的示例相比,导入部分中的新内容是 `rand/math` 包和带有 `led/ws281x` 子树的 `led` 包。 `led` 包本身包含 `Color` 类型的定义。 `led/ws281x/wsuart` 定义了 `ColorOrder`、`Pixel` 和 `Strip` 类型。
我想知道如何使用 `image/color` 中的 `Color``RGBA` 类型,以及如何以它将实现 `image.Image` 接口的方式定义 `Strip`。 但是由于使用了 [gamma 校正][21] 和 大开销的 `color/draw` 包,我以简单的方式结束:
```
type Color uint32
type Strip []Pixel
```
使用一些有用的方法。然而,这种情况在未来可能会改变。
#### init 函数
`init` 函数没有太多新颖之处。 UART 波特率从 115200 更改为 3000000000/1390 ≈ 2158273相当于每个 WS2812 位 1390 纳秒。 CR2 寄存器中的 TxInv 位设置为反转 TXD 信号。
#### main 函数
`XorShift64` 伪随机数生成器用于生成随机颜色。 [XORSHIFT][22] 是目前由 `math/rand` 包实现的唯一算法。你必须使用带有非零参数的 `Seed` 方法显式初始化它。
`rgb` 变量的类型为 `wsuart.ColorOrder`,并设置为 WS2812 使用的 GRB 颜色顺序WS2811 使用 RGB 顺序)。然后用于将颜色转换为像素。
`wsuart.Make(24)` 创建 24 像素的初始化条带。它等效于:
```
strip := make(wsuart.Strip, 24)
strip.Clear()
```
其余代码使用随机颜色绘制类似于 “Please Wait…” 微调器的内容。
`strip` 切片充当帧缓冲区。 `tts.Write(strip.Bytes())` 将帧缓冲区的内容发送到环。
#### 中断
该程序由处理中断的代码组成,与先前的 [UART 示例][23] 中的代码相同。
让我们编译并运行:
```
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
14088 240 204 14532 38c4 cortexm0.elf
$ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; reset run; exit'
```
我跳过了 `openocd` 的输出。下面的视频显示了该程序的工作原理:
![video](https://ziutek.github.io/videos/rgbspinner.mp4)
### 让我们做些有用的事情...
在 [第一部分][3] 的开头我曾问过“Go 能深入到多低层,而还能做一些有用的事情?”。 我们的 MCU 实际上是一种低端设备8 比特的人可能会不同意我的看法),但到目前为止,我们还没有做任何有用的事情。
所以... 让我们做些有用的事情... 让我们做个时钟!
在互联网上有许多由 RGB LED 构成的时钟示例。让我们用我们的小板子和 RGB 环制作自己的时钟。我们按照下面的描述更改先前的代码。
#### 导入部分
删除 `math/rand` 包,然后添加 `stm32/hal/exti`
#### 全局变量
添加两个新的全局变量:`btn` 和 `btnev`
```
var (
tts *usart.Driver
btn gpio.Pin
btnev rtos.EventFlag
)
```
它们将用来处理那些用于设置时钟的 “按钮”。我们的板子除了重置之外没有其他按钮,但是如果没有它,我们仍然可以通过某种方式进行管理。
#### init 函数
将这段代码添加到 `init` 函数:
```
btn = gpio.A.Pin(4)
btn.Setup(&gpio.Config{Mode: gpio.In, Pull: gpio.PullUp})
ei := exti.Lines(btn.Mask())
ei.Connect(btn.Port())
ei.EnableFallTrig()
ei.EnableRiseTrig()
ei.EnableIRQ()
rtos.IRQ(irq.EXTI4_15).Enable()
```
在内部<ruby>上拉电阻<rt>pull-up resistor</rt></ruby>启用的情况下,将 PA4 引脚配置为输入。它已连接至板载 LED但这不会妨碍任何事情。更重要的是它位于 GND 引脚旁边,所以我们可以使用任何金属物体来模拟按钮并设置时钟。作为奖励,我们还有来自板载 LED 的其他反馈。
我们使用 EXTI 外设来跟踪 PA4 状态。它被配置为在发生任何更改时都会产生中断。
#### btnWait 函数
定义一个新的辅助函数:
```
func btnWait(state int, deadline int64) bool {
for btn.Load() != state {
if !btnev.Wait(1, deadline) {
return false // timeout
}
btnev.Reset(0)
}
delay.Millisec(50) // debouncing
return true
}
```
它等待 “按钮” 引脚上的指定状态,但只等到最后期限出现。这是稍微改进的轮询代码:
```
for btn.Load() != state {
if rtos.Nanosec() >= deadline {
// timeout
}
}
```
我们的 `btnWait` 函数不是忙于等待 `state``deadline`,而是使用 `rtos.EventFlag` 类型的 `btnev` 变量休眠,直到有事情发生。你当然可以使用通道而不是 `rtos.EventFlag`,但是后者便宜得多。
#### main 函数
我们需要全新的 `main` 函数:
```
func main() {
rgb := wsuart.GRB
strip := wsuart.Make(24)
ds := 4 * 60 / len(strip) // Interval between LEDs (quarter-seconds).
adjust := 0
adjspeed := ds
for {
qs := int(rtos.Nanosec() / 25e7) // Quarter-seconds since reset.
qa := qs + adjust
qa %= 12 * 3600 * 4 // Quarter-seconds since 0:00 or 12:00.
hi := len(strip) * qa / (12 * 3600 * 4)
qa %= 3600 * 4 // Quarter-seconds in the current hour.
mi := len(strip) * qa / (3600 * 4)
qa %= 60 * 4 // Quarter-seconds in the current minute.
si := len(strip) * qa / (60 * 4)
hc := led.Color(0x550000)
mc := led.Color(0x005500)
sc := led.Color(0x000055)
// Blend the colors if the hands of the clock overlap.
if hi == mi {
hc |= mc
mc = hc
}
if mi == si {
mc |= sc
sc = mc
}
if si == hi {
sc |= hc
hc = sc
}
// Draw the clock and write to the ring.
strip.Clear()
strip[hi] = rgb.Pixel(hc)
strip[mi] = rgb.Pixel(mc)
strip[si] = rgb.Pixel(sc)
tts.Write(strip.Bytes())
// Sleep until the button pressed or the second hand should be moved.
if btnWait(0, int64(qs+ds)*25e7) {
adjust += adjspeed
// Sleep until the button is released or timeout.
if !btnWait(1, rtos.Nanosec()+100e6) {
if adjspeed < 5*60*4 {
adjspeed += 2 * ds
}
continue
}
adjspeed = ds
}
}
}
```
我们使用 `rtos.Nanosec` 函数代替 `time.Now` 来获取当前时间。这样可以节省大量的闪存,但也使我们的时钟变成了不知道日、月、年的老式设备,最糟糕的是它无法处理夏令时的变化。
我们的环有 24 个 LED因此秒针的显示精度可以达到 2.5 秒。为了不牺牲这种精度并获得流畅的运行效果,我们使用 1/4 秒作为基准间隔。半秒就足够了,但四分之一秒更准确,而且与 16 和 48 个 LED 配合使用也很好。
红色、绿色和蓝色分别用于时针、分针和秒针。这允许我们使用简单的“逻辑或操作”进行颜色混合。我们 `Color.Blend` 方法可以混合任意颜色,但是我们闪存不多,所以我们选择最简单的解决方案。
我们只有在秒针移动时才重画时钟。
```
btnWait(0, int64(qs+ds)*25e7)
```
上面的这行代码等待的正是那一刻,或者是按钮的按下。
每按一下按钮就会把时钟向前调一调。按住按钮一段时间会加速调整。
#### 中断
定义新的中断处理程序:
```
func exti4_15ISR() {
pending := exti.Pending() & 0xFFF0
pending.ClearPending()
if pending&exti.Lines(btn.Mask()) != 0 {
btnev.Signal(1)
}
}
```
并将 `irq.EXTI4_15: exti4_15ISR` 条目添加到 ISR 数组。
该处理程序(或中断服务程序)处理 EXTI4_15 IRQ。 Cortex-M0 CPU 支持的 IRQ 明显少于其较大的同类兄弟处理器,因此你经常可以看到一个 IRQ 被多个中断源共享。在我们的例子中,一个 IRQ 由 12 个 EXTI 线共享。
exti4_15ISR 读取所有挂起的位,并从中选择 12 个更高的有效位。接下来,它清除 EXTI 中选中的位并开始处理它们。在我们的例子中,仅检查第 4 位。 `btnev.Signal(1)` 引发 `btnev.Wait(1, deadline)` 唤醒并返回 `true`
你可以在 [Github][24] 上找到完整的代码。让我们来编译它:
```
$ egc
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
15960 240 216 16416 4020 cortexm0.elf
```
这里所有的改进只得到 184 个字节。让我们再次重新构建所有内容,但这次在 typeinfo 中不使用任何类型和字段名:
```
$ cd $HOME/emgo
$ ./clean.sh
$ cd $HOME/firstemgo
$ egc -nf -nt
$ arm-none-eabi-size cortexm0.elf
text data bss dec hex filename
15120 240 216 15576 3cd8 cortexm0.elf
```
现在,有了千字节的空闲空间,你可以改进一些东西。让我们看看它是如何工作的:
![video](https://ziutek.github.io/videos/rgbclock.mp4)
我不知道我是怎么精确打到 3:00 的!?
以上就是所有内容!在第 4 部分(本系列的结束)中,我们将尝试在 LCD 上显示一些内容。LCTT 译注:然而烂尾了,第三篇写于 2018 年,整个博客当年就停更了。)
--------------------------------------------------------------------------------
via: https://ziutek.github.io/2018/05/03/go_on_very_small_hardware3.html
作者:[Michał Derkacz][a]
选题:[lujun9972][b]
译者:[gxlct008](https://github.com/gxlct008)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://ziutek.github.io
[b]: https://github.com/lujun9972
[1]: https://ziutek.github.io/images/mcu/f030-demo-board/board.jpg
[2]: https://ziutek.github.io/2018/05/03/go_on_very_small_hardware3.html
[3]: https://linux.cn/article-11383-1.html
[4]: https://linux.cn/article-12747-1.html
[5]: http://www.world-semi.com/solution/list-4-1.html
[6]: https://ziutek.github.io/images/led/ws2812b.jpg
[7]: http://www.martinhubacek.cz/arm/improved-stm32-ws2812b-library
[8]: http://mikrokontrolery.blogspot.com/2011/03/Diody-WS2812B-sterowanie-XMega-cz-2.html
[9]: https://translate.google.pl/translate?sl=pl&tl=en&u=http://mikrokontrolery.blogspot.com/2011/03/Diody-WS2812B-sterowanie-XMega-cz-2.html
[10]: http://neon-world.com/en/product.php
[11]: http://www.normandled.com/index.php/Product/view/id/800.html
[12]: https://cpldcpu.wordpress.com/2014/08/27/apa102/
[13]: https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
[14]: https://cpldcpu.wordpress.com/2016/12/13/sk9822-a-clone-of-the-apa102/
[15]: https://ziutek.github.io/images/led/rgbring.jpg
[16]: https://ziutek.github.io/images/led/ring-stlink-f030.jpg
[17]: https://jeelabs.org/article/1649a/
[18]: http://www.st.com/en/evaluation-tools/stm32f4discovery.html
[19]: https://github.com/ziutek/emgo/tree/master/egpath/src/stm32/examples/minidev/treelights
[20]: https://github.com/ziutek/emgo/tree/master/egpath/src/stm32/examples/nucleo-f411re/ws2812
[21]: https://en.wikipedia.org/wiki/Gamma_correction
[22]: https://en.wikipedia.org/wiki/Xorshift
[23]: https://ziutek.github.io/2018/04/14/go_on_very_small_hardware2.html#uart
[24]: https://github.com/ziutek/emgo/tree/master/egpath/src/stm32/examples/f030-demo-board/ws2812-clock

View File

@ -0,0 +1,75 @@
[#]: collector: (lujun9972)
[#]: translator: (chenmu-kk)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12817-1.html)
[#]: subject: (When Wi-Fi is mission-critical, a mixed-channel architecture is the best option)
[#]: via: (https://www.networkworld.com/article/3386376/when-wi-fi-is-mission-critical-a-mixed-channel-architecture-is-the-best-option.html#tk.rss_all)
[#]: author: (Zeus Kerravala https://www.networkworld.com/author/Zeus-Kerravala/)
当 Wi-Fi 成为关键业务时,混合信道架构是最好的多信道选择
======
> 混合信道架构是最好的多信道选择,但它并不总是最佳的选择。当需要可靠的 Wi-Fi 时,单信道和混合 AP 提供了令人信服的替代方案。
![Getty Images][1]
我曾与许多实施数字项目的公司合作过,结果却发现它们失败了。正确的想法,健全地施行,现存的市场机遇。哪里是薄弱的环节?是 Wi-Fi 网络。
例如,一家大型医院希望通过将遥测信息发送到移动设备,来提高临床医生对患者警报的响应时间。如果没有这个系统,护士了解病人警报的唯一途径就是通过声音警报。在所有嘈杂的背景音中,通常很难分辨噪音来自哪里。问题是这家医院中的 Wi-Fi 网络已经很多年未升级了,这导致信息传递严重延迟(通常需要 4~5 分钟)。过长的信息传递导致人们对该系统失去信心,因此许多临床医生停止使用该系统,转而使用手动警报。最终,人们认为这个项目是失败的。
我曾在制造业、K-12 教育、娱乐和其他行业中见过类似的案例。企业竞争的基础是客户体验,而竞争的动力来自不断扩展又无处不在的无线优势。好的 Wi-Fi 并不意味着市场领导地位,但是劣质的 Wi-Fi 将会对客户和员工产生负面影响。而在当今竞争激烈的环境下,这是灾难的根源。
### Wi-Fi 性能历来不一致
Wi-Fi 的问题在于它本身就很脆弱。我相信每个阅读这篇文章的人都经历过下载失败、连接中断、性能不一致以及连接公用热点的漫长等待时间等缺陷。
想象一下,你在一个会议上,在一个主题演讲之前,你可以随意地发推特、发电子邮件、浏览网页以及做其他事情。然后主讲人上台,所有观众开始拍照,上传并流传信息——然后网络崩溃了。我发现这不仅仅是一个例外,更是一种常态,强调了对[无损 Wi-Fi][3]的需求。
对于网络技术人员的问题是如何让一个地方的 Wi-Fi 达到全部时间都保持不间断。有人说只要加强现存的网络可以做到这也许可以但在某些情况下Wi-Fi 的类型可能并不合适。
最常见的 Wi-Fi 部署类型是多信道也称为微蜂窝每个客户端通过无线信道连接到接入点AP。高质量的通话体验基于两点良好的信号强度和最小的干扰。有几个因素会导致干扰例如接入点距离太近、布局问题或者来自其他设备的干扰。为了最大程度地减少干扰企业需要投入大量的时间和资金在[现场调查中规划最佳的信道地图][2]但即使这些做得很好Wi-Fi 故障仍然可能发生。
## 多通道 Wi-Fi 并非总是最佳选择
对于许多铺着地毯的办公室来说,多通道 Wi-Fi 可能是可靠的,但在某些环境中,外部环境会影响性能。一个很好的例子是多租户建筑,其中有多个 Wi-Fi 网络在同一信道上传输并相互干扰。另一个例子是医院,这里有许多工作人员在多个接入点间流动。客户端将试图连接到最佳接入点,导致客户端不断断开连接并重新连接,从而导致会话中断。还有一些环境,例如学校、机场和会议设施,那里存在大量的瞬态设备,而多通道则难以跟上。
## 单通道 Wi-Fi 提供更好的可靠性但与此同时性能会受到影响
网络管理器要做什么?不一致的 Wi-Fi 只是一个既成事实吗?多信道是一种标准,但它并非是为动态物理环境或那些需要可靠的连接环境而设计的。
几年前提出了一项解决这些问题的替代架构。顾名思义“单信道”Wi-Fi 在网络中为所有接入点使用单一的无线频道。可以把它想象成在一个信道上运行的单个 Wi-Fi 结构。这种架构中,接入点的位置无关紧要,因为它们都利用相同的通道,因此不会互相干扰。这有一个显而易见的简化优势,比如,如果覆盖率很低,那就没有理由再做一次昂贵的现场调查。相反,只需在需要的地方布置接入点就可以了。
单通道的缺点之一是总网络吞吐量低于多通道,因为只能使用一个通道。在可靠性高于性能的环境中,这可能会很好,但许多组织希望二者兼而有之。
## 混合接入点提供了两全其美的优势
单信道系统制造商最近进行了创新将信道架构混合在一起创造了一种“两全其美”的部署可提供多信道的吞吐量和单信道的可靠性。举个例子Allied Telesis 提供了混合接入点,可以同时在多信道和单信道模式下运行。这意味着可以分配一些 Web 客户端到多信道以获得最大的吞吐量,而其他的 Web 客户端则可使用单信道来获得无缝漫游体验。
这种混合的实际用例可能是物流设施,办公室工作人员使用多通道,但叉车操作员在整个仓库移动时使用单一通道持续连接。
Wi-Fi 曾是一个便利的网络但如今它或许是所有网络中最关键的任务。传统的多信道体系也许可以工作但应该做一些尽职调查来看看它在重负下如何运转。IT 领导者需要了解 Wi-Fi 对数字转型计划的重要性,并进行适当的测试,以确保它不是基础设施链中的薄弱环节,并为当今环境选择最佳技术。
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3386376/when-wi-fi-is-mission-critical-a-mixed-channel-architecture-is-the-best-option.html
作者:[Zeus Kerravala][a]
选题:[lujun9972][b]
译者:[chenmu-kk](https://github.com/chenmu-kk)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.networkworld.com/author/Zeus-Kerravala/
[b]: https://github.com/lujun9972
[1]: https://images.idgesg.net/images/article/2018/09/tablet_graph_wifi_analytics-100771638-large.jpg
[2]: https://www.networkworld.com/article/3315269/wi-fi-site-survey-tips-how-to-avoid-interference-dead-spots.html
[3]: https://www.alliedtelesis.com/blog/no-compromise-wi-fi
[4]: https://pluralsight.pxf.io/c/321564/424552/7490?u=https%3A%2F%2Fwww.pluralsight.com%2Fcourses%2Fmobile-device-management-big-picture
[5]: https://www.networkworld.com/article/3273439/review-icinga-enterprise-grade-open-source-network-monitoring-that-scales.html?nsdr=true#nww-fsb
[6]: https://www.networkworld.com/article/3304307/nagios-core-monitoring-software-lots-of-plugins-steep-learning-curve.html
[7]: https://www.networkworld.com/article/3269279/review-observium-open-source-network-monitoring-won-t-run-on-windows-but-has-a-great-user-interface.html?nsdr=true#nww-fsb
[8]: https://www.networkworld.com/article/3304253/zabbix-delivers-effective-no-frills-network-monitoring.html
[9]: https://www.facebook.com/NetworkWorld/
[10]: https://www.linkedin.com/company/network-world

View File

@ -0,0 +1,60 @@
[#]: collector: (lujun9972)
[#]: translator: (chenmu-kk)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12803-1.html)
[#]: subject: (Most enterprise networks can't handle big data loads)
[#]: via: (https://www.networkworld.com/article/3440519/most-enterprise-networks-cant-handle-big-data-loads.html)
[#]: author: (Andy Patrizio https://www.networkworld.com/author/Andy-Patrizio/)
大多数企业网络无法处理大数据负载
======
> 随着网络中流动着越来越多的数据,由于领导力和技术问题,网络正在滞后于数据的发展速度。
![](https://images.idgesg.net/images/article/2019/08/gettyimages-811109186-100808291-large.jpg)
又过了一周另一项调查发现IT 已经无法跟上不断膨胀的数据过载。这次的问题将主要是网络带宽和整体性能。
管理咨询公司埃森哲对 [300 名 IT 专业人士进行的一项调查][1] 发现,大多数人认为他们企业网络无法胜任处理大数据的任务和物联网部署的任务。只有 43% 的受访公司表示他们的网络已经准备好支持云服务、物联网和其他数字技术。
一个关键原因58%是“IT 与商业需求之间的错位”,这延缓了这些项目的进展。这是一个不同寻常的发现,因为 85% 的受访者还表示他们的网络已经完全或者大体上已经准备好支持企业的数字化计划。那么,究竟是哪一种情况呢?
第二和第三大时常提及的障碍是“业务需求和运营需求间固有的复杂性”以及“对带宽、性能等方面的需求超过交付能力”,各占 45%。
由于分析技术和其他大数据技术的推动,大量传输的数据持续涌入网络线路,网络瓶颈持续增长。调查发现,带宽需求并未得到满足,目前的网络性能依旧达不到要求。
其他原因还包括缺乏网络技术、设备扩展和设备老化。
### 网络性能问题的一个解决方案SDN
埃森哲发现,大多数公司表示 [软件定义网络SDN][5] 是应对带宽和性能挑战的解决方案77% 的受访企业在调查中表示正在部署 SDN 或者已完成部署。它指出,虽然 SDN 可能在组织的某部分中存在,它并不总是在整个企业范围内统一地推出。
如今看来,似乎从未有人有足够的预算来满足他们所有的 IT 雄心,但 31% 受访者认为为网络改善提供资金是“简单的”而且是在网络基础设施团队的控制范围内相较于直接下属13%)或基础设施/网络主管和副总裁19%),首席信息官/首席技术官更可能将融资过程报告为“轻松”40%)。
报告指出,“仅靠传统网络无法支持数字时代所需的创新和性能。”报告呼吁拥抱新技术,但没有提到 SDN 的名字。同时它还呼吁首席执行官和他们直接下属间加强合作,因为很明显,双方在看待问题的方式上存在分歧。
报告总结说,“我们认为需要一种新的网络范式来确保网络满足当前和未来的业务需求。然而,尽管有进步的迹象,但变革的步伐缓慢。公司必须承担起重担,才能实现统一和标准化企业能力,提供必要的带宽、性能和安全,以支持当前和未来的业务需求”。
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3440519/most-enterprise-networks-cant-handle-big-data-loads.html
作者:[Andy Patrizio][a]
选题:[lujun9972][b]
译者:[chenmu-kk](https://github.com/chenmu-kk)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.networkworld.com/author/Andy-Patrizio/
[b]: https://github.com/lujun9972
[1]: https://www.accenture.com/_acnmedia/pdf-107/accenture-network-readiness-survey.pdf#zoom=50
[2]: https://www.networkworld.com/article/3209131/lan-wan/what-sdn-is-and-where-its-going.html
[3]: https://www.networkworld.com/article/3206709/lan-wan/what-s-the-difference-between-sdn-and-nfv.html
[4]: https://www.networkworld.com/newsletters/signup.html
[5]: https://www.networkworld.com/article/3209131/what-sdn-is-and-where-its-going.html
[6]: https://www.networkworld.com/blog/itaas-and-the-corporate-storage-technology/
[7]: https://www.networkworld.com/article/3405522/how-network-pros-acquire-skills-for-sdn-programmable-networks.html
[8]: https://www.facebook.com/NetworkWorld/
[9]: https://www.linkedin.com/company/network-world

View File

@ -0,0 +1,153 @@
[#]: collector: (lujun9972)
[#]: translator: (chenmu-kk)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12826-1.html)
[#]: subject: (4 open source eBook readers for Android)
[#]: via: (https://opensource.com/article/19/10/open-source-ereaders-android)
[#]: author: (Scott Nesbitt https://opensource.com/users/scottnesbitt)
四款安卓开源电子书阅读器
======
> 你在寻找新的电子书阅读软件吗?来看看这四款适用于安卓的可靠的开源电子书阅读器吧。
![](https://img.linux.net.cn/data/attachment/album/202011/16/135728ayhh1aiqwrva50zy.jpg)
谁不想有一个好的阅读体验?与其将时间浪费在社交媒体或[即时消息软件][2]上,不如在自己的安卓手机或平板上阅读一本书、杂志或其他文档。
要做到这一点,你需要的是一个适合的电子书阅读软件。接下来让我们来看一看四款可靠的、开源安卓电子书阅读器。
### Book Reader
那我们先从我最喜欢的一款开源安卓电子书阅读器开始:[Book Reader][3]。它基于现在专有的 FBReader 应用的开源老版本。像 FBReader 的早期版本一样Book Reader 小而简单,但是好用。
**优点:**
* 易于操作。
* 该应用界面遵循安卓的 [Material Design 指南][4],因此非常干净。
* 你可以为电子书添加书签,并将文本分享至你设备上的其他应用。
* 不断提供除英语外的其他语言的支持。
**缺点**
* Book Reader 的自定义选项较少。
* 没有内置词典或支持外部词典的功能。
**支持的电子书格式:**
Book Reader 支持 EPUB、.mobi、PDF、[DjVu][5]、HTML、纯文本、 Word 文档、RTF 和 [FictionBook][6]。
![Book Reader Android app][7]
Book Reader 的源码在 GNU GPL 3.0 下授权,你可以在[GitLab][8]中找到它。
### Cool Reader
[Cool Reader][9] 是一个灵活易用的电子书软件。虽然我觉得该软件的图标会让想起 Windows vista 中的图标,但它确实有一些好用的功能。
**优点**
* 高度自定义,你可以更改字体、行宽、段间距、连字符、字体大小、页边距以及背景色。
* 你可以覆盖书中的样式表。我发现这对于两三本将所有文本设置为小写字母的书很有用。
* 它会在设备启动时自动搜寻设备中的新书资源。你也可以查阅[古腾堡计划][10]和[互联网档案馆][11]中的书籍。
**缺点**
* Cool Reader 的界面并不是极简或者说最现代化的。
* 虽然它开箱即用,但实际上你需要调整一些配置来更舒适地使用 Cool Reader。
* 应用的默认词典是专有的,尽管你可以用[开源的词典][12]来替换掉它。
**支持的电子书格式:**
你可以使用 Cool Reader 来浏览 EPUB、小说、纯文本、RTF、HTML、[CHM][13] 和 TCRPsion 系列掌上电脑的电子书格式)文件。
![Cool Reader Android app][14]
Cool Reader 的源码在 GNU GPL 2 下授权,你可以在 [Sourceforge][15] 中找到它。
### KOReader
[KOReader][16] 最初是为了 [E Ink][17] 电子书阅读器创建的,但后来发现它可用于安卓。在测试它时,我发现 KOReader 在同等程度下既有用又令人沮丧。很明显它绝不是一款不好的应用,但不会是我的首选。
**优点**
* 高度自定义。
* 支持多种语言。
* 它允许你使用[词典][18](若你已安装)或者 Wikipedia若你已连接至网络来查单词。
**缺点**
* 每一本书你都需要改变设置。在你打开一本新书时KOReader 不会记住相关设置
* 它的界面会让人觉得是一款专门的电子书阅读器。该应用没有安卓的外形和感受。
**支持的电子书格式:**
你可以查阅 PDF、DjVu、CBT、以及 [CBZ][5] 电子书。它也支持 EPUB、小说、.mobi、Word 文档、文本文件和 [CHM][13] 文件。
![KOReader Android app][19]
Cool Reader 的源码在 GNU Affero GPL 3.0 下授权,你可以在 [GitHub][20] 上找到它。
### Booky McBookface
是的,这确实是[这款电子书阅读器][21]的名字。它是这篇文章中最基础的电子书阅读器但不要因此或者这个傻乎乎的名字使你失望。Booky McBookface 易于使用,并且有一件事它做的很好。
**优点**
* 没有多余的装饰。只有你和你的电子书。
* 界面简洁。
* 在安卓启动栏中的长按软件图标会弹出一个菜单,你可以从中打开正在阅读的最后一本书、获得未读书籍的列表、或者查找并打开设备上的一本书。
**缺点**
* 软件中几乎没有配置选项——你可以更改字体大小和亮度,仅此而已。
* 你需要使用屏幕底部的按钮浏览电子书。点击屏幕边缘无法操作。
* 无法为电子书添加书签。
**支持的电子书格式**
你可以使用该软件阅读 EPUB 格式、HTML 文档,或纯文本格式的电子书。
![Booky McBookface Android app][22]
Booky McBookface 的源码在 GNU GPL 3.0 下授权,你可以在 [GitHub][23] 中找到它。
你有最喜欢的安卓开源电子书阅读器吗?在社区中留言分享一下吧。
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/10/open-source-ereaders-android
作者:[Scott Nesbitt][a]
选题:[lujun9972][b]
译者:[chenmu-kk](https://github.com/chenmu-kk)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/scottnesbitt
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/computer_browser_program_books_read.jpg?itok=iNMWe8Bu (Computer browser with books on the screen)
[2]: https://opensource.com/article/19/3/open-messenger-client
[3]: https://f-droid.org/en/packages/com.github.axet.bookreader/
[4]: https://material.io/design/
[5]: https://opensource.com/article/19/3/comic-book-archive-djvu
[6]: https://en.wikipedia.org/wiki/FictionBook
[7]: https://opensource.com/sites/default/files/uploads/book_reader-book-list.png (Book Reader Android app)
[8]: https://gitlab.com/axet/android-book-reader/tree/HEAD
[9]: https://f-droid.org/en/packages/org.coolreader/
[10]: https://www.gutenberg.org/
[11]: https://archive.org
[12]: http://aarddict.org/
[13]: https://fileinfo.com/extension/chm
[14]: https://opensource.com/sites/default/files/uploads/cool_reader-icons.png (Cool Reader Android app)
[15]: https://sourceforge.net/projects/crengine/
[16]: https://f-droid.org/en/packages/org.koreader.launcher/
[17]: https://en.wikipedia.org/wiki/E_Ink
[18]: https://github.com/koreader/koreader/wiki/Dictionary-support
[19]: https://opensource.com/sites/default/files/uploads/koreader-lookup.png (KOReader Android app)
[20]: https://github.com/koreader/koreader
[21]: https://f-droid.org/en/packages/com.quaap.bookymcbookface/
[22]: https://opensource.com/sites/default/files/uploads/booky_mcbookface-menu.png (Booky McBookface Android app)
[23]: https://github.com/quaap/BookyMcBookface

View File

@ -0,0 +1,177 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12868-1.html)
[#]: subject: (Getting started with Emacs)
[#]: via: (https://opensource.com/article/20/3/getting-started-emacs)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
10 个让你进入 Emacs 世界的技巧
======
> 10 个技巧,让你深入这个有用的开源文本编辑器的世界。
![](https://img.linux.net.cn/data/attachment/album/202011/29/103757lccy9ljxiowooyzy.jpg)
很多人都说想学 [Emacs][2],但很多人在短暂的接触后就退缩了。这并不是因为 Emacs 不好,也不是 Emacs 复杂。我相信,问题在于人们其实并不想“学习” Emacs而是他们想习惯 Emacs 的传统。他们想了解那些神秘的键盘快捷键和不熟悉的术语。他们想按照他们认为的“使用目的”来使用 Emacs。
我很同情这一点,因为我对 Emacs 的感觉就是这样。我以为真正的 Emacs 用户都只会在终端里面运行,从来不用方向键和菜单,更不会用鼠标。这是个阻止自己开始使用 Emacs 的好办法。有足够多的独特的 `.emacs` 配置文件证明,如果说 Emacs 用户有一个共同的变化,那就是每个人使用 Emacs 的方式不同。
学习 Emacs 很容易。爱上 Emacs 才是最难的。要爱上 Emacs你必须发现它所拥有的功能而这些功能是你一直在寻找的有时你并不知道你已经错过了它们。这需要经验。
获得这种经验的唯一方法就是从一开始就积极使用 Emacs。这里有十个小提示可以帮助你找出最适合你的方法。
### 从 GUI 开始
Emacs以及它的友好竞争者 [Vim][3])最伟大的事情之一是它可以在终端中运行,这在你 SSH 进入服务器时很有用,但在过去 15 年来制造的计算机上意义不大。Emacs 的 GUI 版本可以在极度[低功耗的设备][4]上运行,它有很多实用的功能,无论是新手还是有经验的用户都可以使用它。
例如,如果你不知道如何在 Emacs 中只用键盘快捷键复制一个单词,编辑菜单的复制、剪切和粘贴选择提供了最轻松的路径。没有理由因为选择了 Emacs 而惩罚自己。使用它的菜单,用鼠标选择区域,点击缓冲区内的按钮,不要让陌生感阻碍你的工作效率。
![Emacs slackware][5]
这些功能被内置到 Emacs 中,是因为用户在使用它们。你应该在你需要的时候使用它们,而当你最终在 VT100 终端上通过 SSH 使用 Emacs没有 `Alt` 或方向键的时候,你才应该使用这些晦涩的命令。
### 习惯术语
Emacs 的 UI 元素有着特殊的术语。个人计算的发展并不是建立在相同的术语上,所以很多术语对现代计算机用户来说比较陌生,还有一些术语虽然相同,但含义不同。下面是一些最常见的术语。
* <ruby>框架<rt>Frame</rt></ruby>。在 Emacs 中,“框架”就是现代计算机所说的“窗口”。
* <ruby>缓冲区<rt>Buffer</rt></ruby>:“缓冲区”是 Emacs 的一个通信通道。它可以作为 Emacs 进程的命令行,也可以作为 shell或者只是一个文件的内容。
* <ruby>窗口<rt>Window</rt></ruby>:“窗口”是你进入一个缓冲区的视角。
* <ruby>迷你缓冲区<rt>Mini-buffer</rt></ruby>。它是主要的命令行,位于 Emacs 窗口的底部。
![Emacs tutorial map][6]
### 让 Emacs 的修饰键变得更有意义
在 PC 键盘上,`Ctrl` 键被称为 `C``Alt` 键被称为 `M`,这些键并不是 `C``M` 键,由于它们总是与相应的字母或符号键配对,所以在文档中很容易识别。
例如,`C-x` 在现代键盘符号中的意思是 `Ctrl+X``M-x` 是 `Alt+X`。就像你从任何应用程序中剪切文本时一样,同时按下这两个键。
不过,还有另一个层次的键盘快捷键,与现代电脑上的任何东西都完全不同。有时,键盘快捷键并不只是一个键组合,而是由一系列的按键组成。
例如,`C-x C-f` 的意思是像往常一样按 `Ctrl+X`,然后再按 `Ctrl+C`
有时,一个键盘快捷键有混合的键型。组合键 `C-x 3` 意味着像往常一样按 `Ctrl+X`,然后按数字 `3` 键。
Emacs 之所以能做到这些花哨的强力组合,是因为某些键会让 Emacs 进入一种特殊的命令模式。如果你按 `C-X`(也就是 `Ctrl+X`),就是告诉 `Emacs` 进入空闲状态,等待第二个键或键盘快捷键。
Emacs 的文档,无论是官方的还是非官方的,都有很多键盘快捷键。在心里练习把 `C` 键翻译成 `Ctrl` 键,`M` 键翻译成 `Alt` 键,那么这些文档对你来说都会变得更有意义。
### 剪切、复制和粘贴的备用快捷方式
从规范上,复制文本是通过一系列的键盘快捷键进行的,这些快捷键取决于你想要复制或剪切的方式。
例如,你可以用 `M-d``Alt+d` 的 Emacs 行话)剪切一整个单词,或者用`C-k``Ctrl+K`)剪切一整行,或者用 `M-m``Alt+M`)剪切一个高亮区域。如果你想的话,你可以习惯这样,但如果你喜欢 `Ctrl+C``Ctrl+X``Ctrl-V`,那么你可以用这些来代替。
启用现代的“剪切-复制-粘贴”需要激活一个名为 CUA<ruby>通用用户访问<rt>Common User Access</rt></ruby>)的功能。要激活 CUA请单击“选项”菜单并选择“使用 CUA 键”。启用后,`C-c` 复制高亮显示的文本,`C-x` 剪切高亮显示的文本,`C-v` 粘贴文本。这个模式只有在你选择了文本之后才会实际激活,所以你仍然可以学习 Emacs 通常使用的 `C-x``C-c` 绑定。
### 用哪个都好
Emacs 是一个应用程序,它不会意识到你对它的感情或忠诚度。如果你想只用 Emacs 来完成那些“感觉”适合 Emacs 的任务,而用不同的编辑器(比如 Vim来完成其他任务你可以这样做。
你与一个应用程序的交互会影响你的工作方式,所以如果 Emacs 中所需要的按键模式与特定任务不一致,那么就不要强迫自己使用 Emacs 来完成该任务。Emacs 只是众多可供你使用的开源工具之一,没有理由让自己只限于一种工具。
### 探索新函数
Emacs 所做的大部分工作都是一个 elisp 函数它可以从菜单选择和键盘快捷键调用或者在某些情况下从特定事件中调用。所有的函数都可以从迷你缓冲区Emacs 框架底部的命令行)执行。理论上,你甚至可以通过键入 `forward-word``backward-word` 以及 `next-line``previous-line` 等函数来导航光标。这肯定是无比低效的但这就是一种直接访问你运行的代码的方式。在某种程度上Emacs 就是自己的 API。
你可以通过在社区博客上阅读有关 Emacs 的资料来了解新函数,或者你可以采取更直接的方法,使用描述函数(`describe-function`)。要获得任何函数的帮助,按 `M-x`(也就是 `Alt+X`),然后输入 `describe-function`,然后按回车键。系统会提示你输入一个函数名称,然后显示该函数的描述。
你可以通过键入`M-x`Alt+X`),然后键入 `?` 来获得所有可用函数的列表。
你也可以在输入函数时,通过按 `M-x` 键,然后输入 `auto-complete-mode`,再按回车键,获得弹出的函数描述。激活该模式后,当你在文档中键入任何 Emacs 函数时,都会向你提供自动补完选项,以及函数的描述。
![Emacs function][7]
当你找到一个有用的函数并使用它时Emacs 会告诉你它的键盘绑定,如果有的话。如果没有的话,你可以通过打开你的 `$HOME/.emacs` 配置文件并输入键盘快捷键来自己分配一个。语法是 ` global-set-key`,后面是你要使用的键盘快捷键,然后是你要调用的函数。
例如,要将 `screenwriter-slugline` 函数分配一个键盘绑定:
```
(global-set-key (kbd “C-c s”) 'screenwriter-slugline)
```
重新加载配置文件,键盘快捷键就可以使用了:
```
M-x load-file ~/.emacs
```
### 紧急按钮
当你使用 Emacs 并尝试新的函数时你一定会开始调用一些你并不想调用的东西。Emacs 中通用的紧急按钮是 `C-g`(就是 `Ctrl+G`)。
我通过将 G 与 GNU 联系起来来记住这一点,我想我是在呼吁 GNU 将我从一个错误的决定中拯救出来,但请随意编造你自己的记忆符号。
如果你按几下 `C-g`Emacs 的迷你缓冲区就会回到潜伏状态,弹出窗口被隐藏,你又回到了一个普通的、无聊的文本编辑器的安全状态。
### 忽略键盘快捷键
潜在的键盘快捷键太多在这里无法一一总结更不希望你能记住。这是设计好的。Emacs 的目的是为了定制,当人们为 Emacs 编写插件时,他们可以定义自己的特殊键盘快捷键。
我们的想法不是要马上记住所有的快捷键。相反,你的目标是让你在使用 Emacs 时感到舒适。你在 Emacs 中变得越舒适,你就越会厌倦总是求助于菜单栏,你就会开始记住对你重要的组合键。
根据自己在 Emacs 中通常做的事情,每个人都有自己喜欢的快捷方式。一个整天用 Emacs 写代码的人可能知道运行调试器或启动特定语言模式的所有键盘快捷键,但对 Org 模式或 Artist 模式一无所知。这很自然,也很好。
### 使用 Bash 时练习 Emacs
了解 Emacs 键盘快捷键的一个好处是,其中许多快捷键也适用于 Bash。
* `C-a`:到行首
* `C-e`:到行尾
* `C-k`:剪切整行
* `M-f`:向前一个字
* `M-b`:向后一个字
* `M-d`:剪切一个字
* `C-y`:贴回(粘贴)最近剪切的内容
* `M-Shift-U`:大写一个词
* `C-t`:交换两个字符(例如,`sl` 变成 `ls`
还有更多的例子,它能让你与 Bash 终端的交互速度超乎你的想象。
### 包
Emacs 有一个内置的包管理器来帮助你发现新的插件。它的包管理器包含了帮助你编辑特定类型文本的模式(例如,如果你经常编辑 JSON 文件,你可以尝试使用 ejson 模式、嵌入的应用程序、主题、拼写检查选项、linter 等。这就是 Emacs 有可能成为你日常计算的关键所在;一旦你找到一个优秀的 Emacs 包,你可能离不开它了。
![Emacs emoji][8]
你可以按 `M-x`(就是 `Alt+X`)键,然后输入 `package-list-packages` 命令再按回车键来浏览包。软件包管理器在每次启动时都会更新缓存所以第一次使用时要耐心等待它下载可用软件包的列表。一旦加载完毕你可以用键盘或鼠标进行导航记住Emacs 是一个 GUI 应用程序)。每一个软件包的名称都是一个按钮,所以你可以将光标移到它上面,然后按回车键,或者直接用鼠标点击它。你可以在 Emacs 框架中出现的新窗口中阅读有关软件包的信息,然后用安装按钮来安装它。
有些软件包需要特殊的配置,有时会在它的描述中列出,但有时需要你访问软件包的主页来阅读更多的信息。例如,自动完成包 `ac-emoji` 很容易安装,但需要你定义一个符号字体。无论哪种方式都可以使用,但你只有在安装了字体的情况下才能看到相应的表情符号,除非你访问它的主页,否则你可能不会知道。
### 俄罗斯方块
Emacs 有游戏,信不信由你。有数独、拼图、扫雷、一个好玩的心理治疗师,甚至还有俄罗斯方块。这些并不是特别有用,但在任何层面上与 Emacs 进行交互都是很好的练习,游戏是让你在 Emacs 中花费时间的好方法。
![Emacs tetris][9]
俄罗斯方块也是我最初接触 Emacs 的方式所以在该游戏的所有版本中Emacs 版本才是我真正的最爱。
### 使用 Emacs
GNU Emacs 之所以受欢迎,是因为它的灵活性和高度可扩展性。人们习惯了 Emacs 的键盘快捷键,以至于他们习惯性地尝试在其他所有的应用程序中使用这些快捷键,他们将应用程序构建到 Emacs 中,所以他们永远不需要离开。如果你想让 Emacs 在你的计算生活中扮演重要角色,最终的关键是拥抱未知,开始使用 Emacs。磕磕绊绊地直到你发现如何让它为你工作然后安下心来享受 40 年的舒适生活。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/3/getting-started-emacs
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/keyboaord_enter_writing_documentation.jpg?itok=kKrnXc5h (Computer keyboard typing)
[2]: https://opensource.com/downloads/emacs-cheat-sheet
[3]: https://opensource.com/downloads/cheat-sheet-vim
[4]: https://opensource.com/article/17/2/pocketchip-or-pi
[5]: https://opensource.com/sites/default/files/uploads/emacs-slackware.jpg (Emacs slackware)
[6]: https://opensource.com/sites/default/files/uploads/emacs-tutorial-map.png (Emacs tutorial map)
[7]: https://opensource.com/sites/default/files/uploads/emacs-function.jpg (Emacs function)
[8]: https://opensource.com/sites/default/files/uploads/emacs-emoji_0.jpg (Emacs emoji)
[9]: https://opensource.com/sites/default/files/uploads/emacs-tetris.jpg (Emacs tetris)

View File

@ -0,0 +1,155 @@
[#]: collector: (lujun9972)
[#]: translator: (MjSeven)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12871-1.html)
[#]: subject: (An introduction to mutation testing in Python)
[#]: via: (https://opensource.com/article/20/7/mutmut-python)
[#]: author: (Moshe Zadka https://opensource.com/users/moshez)
Python 突变测试介绍
======
> 通过突变测试来修复未知的 bug。
![](https://img.linux.net.cn/data/attachment/album/202011/29/230106ie9xc89dj3jx1yj9.jpg)
你一定对所有内容都进行了测试,也许你甚至在项目仓库中有一个徽章,标明有 100% 的测试覆盖率,但是这些测试真的帮到你了吗?你怎么知道的?
开发人员很清楚单元测试的*成本*。测试必须要编写。有时它们无法按照预期工作:存在假告警或者抖动测试。在不更改任何代码的情况下有时成功,有时失败。通过单元测试发现的小问题很有价值,但是通常它们悄无声息的出现在开发人员的机器上,并且在提交到版本控制之前就已得到修复。但真正令人担忧的问题大多是看不见的。最糟糕的是,*丢失的告警*是完全不可见的:你看不到没能捕获的错误,直到出现在用户手上 —— 有时甚至连用户都看不到。
有一种测试可以使不可见的错误变为可见:<ruby>[突变测试][2]<rt>mutation testing</rt></ruby>
变异测试通过算法修改源代码,并检查每次测试是否都有“变异体”存活。任何在单元测试中幸存下来的变异体都是问题:这意味着对代码的修改(可能会引入错误)没有被标准测试套件捕获。
[Python][3] 中用于突变测试的一个框架是 `mutmut`
假设你需要编写代码来计算钟表中时针和分针之间的角度,直到最接近的度数,代码可能会这样写:
```
def hours_hand(hour, minutes):
    base = (hour % 12 ) * (360 // 12)
    correction = int((minutes / 60) * (360 // 12))
    return base + correction
def minutes_hand(hour, minutes):
    return minutes * (360 // 60)
def between(hour, minutes):
    return abs(hours_hand(hour, minutes) - minutes_hand(hour, minutes))
```
首先,写一个简单的单元测试:
```
import angle
def test_twelve():
    assert angle.between(12, 00) == 0
```
足够了吗?代码没有 `if` 语句,所以如果你查看覆盖率:
```
$ coverage run `which pytest`
============================= test session starts ==============================
platform linux -- Python 3.8.3, pytest-5.4.3, py-1.8.2, pluggy-0.13.1
rootdir: /home/moshez/src/mut-mut-test
collected 1 item                                                              
tests/test_angle.py .                                                    [100%]
============================== 1 passed in 0.01s ===============================
```
完美!测试通过,覆盖率为 100%,你真的是一个测试专家。但是,当你使用突变测试时,覆盖率会变成多少?
```
$ mutmut run --paths-to-mutate angle.py
<snip>
Legend for output:
🎉 Killed mutants. The goal is for everything to end up in this bucket.
⏰ Timeout. Test suite took 10 times as long as the baseline so were killed.
🤔 Suspicious. Tests took a long time, but not long enough to be fatal.
🙁 Survived. This means your tests needs to be expanded.
🔇 Skipped. Skipped.
<snip>
⠋ 21/21 🎉 5 ⏰ 0 🤔 0 🙁 16 🔇 0
```
天啊,在 21 个突变体中,有 16 个存活。只有 5 个通过了突变测试,但是,这意味着什么呢?
对于每个突变测试,`mutmut` 会修改部分源代码,以模拟潜在的错误,修改的一个例子是将 `>` 比较更改为 `>=`,查看会发生什么。如果没有针对这个边界条件的单元测试,那么这个突变将会“存活”:这是一个没有任何测试用例能够检测到的潜在错误。
是时候编写更好的单元测试了。很容易检查使用 `results` 所做的更改:
```
$ mutmut results
<snip>
Survived 🙁 (16)
---- angle.py (16) ----
4-7, 9-14, 16-21
$ mutmut apply 4
$ git diff
diff --git a/angle.py b/angle.py
index b5dca41..3939353 100644
--- a/angle.py
+++ b/angle.py
@@ -1,6 +1,6 @@
def hours_hand(hour, minutes):
hour = hour % 12
- base = hour * (360 // 12)
+ base = hour / (360 // 12)
correction = int((minutes / 60) * (360 // 12))
return base + correction
```
这是 `mutmut` 执行突变的一个典型例子,它会分析源代码并将运算符更改为不同的运算符:减法变加法。在本例中由乘法变为除法。一般来说,单元测试应该在操作符更换时捕获错误。否则,它们将无法有效地测试行为。按照这种逻辑,`mutmut` 会遍历源代码仔细检查你的测试。
你可以使用 `mutmut apply` 来应用失败的突变体。事实证明你几乎没有检查过 `hour` 参数是否被正确使用。修复它:
```
$ git diff
diff --git a/tests/test_angle.py b/tests/test_angle.py
index f51d43a..1a2e4df 100644
--- a/tests/test_angle.py
+++ b/tests/test_angle.py
@@ -2,3 +2,6 @@ import angle
def test_twelve():
assert angle.between(12, 00) == 0
+
+def test_three():
+ assert angle.between(3, 00) == 90
```
以前,你只测试了 12 点钟,现在增加一个 3 点钟的测试就足够了吗?
```
$ mutmut run --paths-to-mutate angle.py
<snip>
⠋ 21/21 🎉 7 ⏰ 0 🤔 0 🙁 14 🔇 0
```
这项新测试成功杀死了两个突变体,比以前更好,当然还有很长的路要走。我不会一一解决剩下的 14 个测试用例,因为我认为模式已经很明确了。(你能将它们降低到零吗?)
变异测试和覆盖率一样,是一种工具,它允许你查看测试套件的全面程度。使用它使得测试用例需要改进:那些幸存的突变体中的任何一个都是人类在篡改代码时可能犯的错误,以及潜伏在程序中的隐藏错误。继续测试,愉快地搜寻 bug 吧。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/7/mutmut-python
作者:[Moshe Zadka][a]
选题:[lujun9972][b]
译者:[MjSeven](https://github.com/MjSeven)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/moshez
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/search_find_code_python_programming.png?itok=ynSL8XRV (Searching for code)
[2]: https://opensource.com/article/19/8/mutation-testing-evolution-tdd
[3]: https://opensource.com/resources/python

View File

@ -0,0 +1,452 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12862-1.html)
[#]: subject: (Use your favorite programming language to provision Infrastructure as Code)
[#]: via: (https://opensource.com/article/20/8/infrastructure-as-code-pulumi)
[#]: author: (Lee Briggs https://opensource.com/users/lbriggs)
使用你喜欢的编程语言,将基础设施作为代码进行配置
======
> 用 Node.js 或其他编程语言为你提供启动基础设施所需的一切服务。
![](https://img.linux.net.cn/data/attachment/album/202011/27/151108bnnggmxegfzwog46.jpg)
当你在 IT 和技术的世界里遨游时,你会反复遇到一些术语。其中有些术语很难量化,随着时间的推移,可能会有不同的含义。[“DevOps”][2] 就是一个例子,这个词似乎(在我看来)会根据使用它的人而改变;最初的 DevOps 先驱者可能甚至不认识我们今天所说的 DevOps。
如果你是一个软件开发者,“<ruby>基础架构即代码<rt>Infrastructure as Code</rt></ruby>IaC可能是其中一个术语。IaC 是使用与你编写面向用户的功能相同的软件开发实践来声明应用程序运行的基础设施。这通常意味着使用 [Git][3] 或 [Mercurial][4] 等工具进行版本控制,使用 Puppet、Chef 或 Ansible 进行[配置管理][5]。在基础设施供应层,最常见的技术是 CloudFormation专用于 AWS或开源替代品 [Terraform][6],用来创建供你的应用程序运行的混合云资源。
在配置管理领域有很好产品可供选择,可以将 IaC 写成配置文件或首选的编程语言,但这种选择在基础设施供应领域并不常见。
[Pulumi][7] 提供了一个使用标准编程语言来定义基础设施的方式。它支持一系列语言,包括 [JavaScript][8]、[TypeScript][9]、[Go][10]、[Python][11] 和 [C#][12]。就像 Terraform 一样Pulumi 对许多熟悉的云提供商有一流的支持,比如 [AWS][13]、[Azure][14]、[Google Cloud][15] 和[其他提供商][16]。
在本文中,我将向你展示如何使用 Pulumi 以 Node.js 编写基础设施。
### 先决条件
首先,确保你已经做好了使用 Pulumi 的准备。Pulumi 支持所有主流的操作系统,所以你安装其先决条件的方法取决于你使用的操作系统。
首先,安装你喜欢的编程语言的解释器。我将使用 TypeScript所以我需要安装 `node` 二进制。请查阅 Node 的[安装说明][17],了解你的操作系统的信息。你可以在 [Mac][19] 或 [Linux][20] 上使用 [Homebrew][18] 来安装:
```
brew install node
```
在 Linux 上,你可以使用你常用的软件包管理器,如 `apt``dnf`
```
$ sudo dnf install nodejs
```
无论哪种情况,结果都应该是 `node` 二进制文件在你的 `$PATH` 中可用。要确认它是可访问的,运行:
```
node --version
```
接下来,安装 Pulumi 命令行界面CLI。你可以在 Pulumi 的文档中找到针对不同操作系统的[安装说明][21]。在 Mac 或 Linux 上使用 `brew`
```
brew install pulumi
```
另外,你也可以使用安装脚本。首先下载并审查它,然后执行它:
```
$ curl -fsSL --output pulumi_installer.sh https://get.pulumi.com/
$ more  pulumi_installer.sh
$ sh ./pulumi_installer.sh
```
同样,我们所希望的结果是在你的路径上有 `pulumi` 二进制。检查版本以确保你已经准备好了:
```
pulumi version
v2.5.0
```
### 配置 Pulumi
在你开始配置任何基础设施之前,给 Pulumi 一个存储其[状态][22]的地方。
Pulumi 将其状态存储在后端。默认的后端是 Pulumi 的软件即服务(它有一个针对个人用户的免费计划),但在这个例子中,我使用替代的文件后端。文件后端将在你的本地文件系统上创建一个文件来存储状态:
```
pulumi login --local
```
如果你打算和别人分享这个项目文件后台可能不是一个好的起点。Pulumi 还可以将其状态存储在 AWS S3 等云对象存储中。要使用它,请创建一个 S3 bucket 并登录:
```
pulumi login --cloud-url s3://my-pulumi-state-bucket
```
现在你已经登录到了状态后端,你可以创建一个项目和一个堆栈了!
在你开始创建 Pulumi 项目之前,请先了解以下 Pulumi 术语,你将在本教程中看到这些术语。
#### 项目
<ruby>[项目][23]<rt>project</rt></ruby>是一个包含 `Pulumi.yaml` 文件的目录。这个文件包含了 Pulumi 需要知道的元数据,以便进行它的工作。在 `Pulumi.yaml` 文件中可以找到的示例字段有:
* 运行时例如Python、Node、Go、.Net
* 项目说明(如“我的第一个 Pulumi 项目”)
* 项目名称
项目是一个松散的概念,可以满足你的需求。一般来说,一个项目包含了一系列的*资源*,这些资源是你想要提供和控制的东西。你可以选择拥有资源很少的小型 Pulumi 项目,也可以选择包含所有你需要的资源的大型项目。随着你对 Pulumi 越来越熟悉,你想如何布局你的项目会变得更加清晰。
#### 堆栈
Pulumi <ruby>[堆栈][24]<rt>stack</rt></ruby>允许你根据可配置的值来区分你的 Pulumi 项目。一个常见的用途是将一个项目部署到不同的环境,如开发或生产环境,或不同的地区,如欧洲、中东和非洲以及美国。
在入门时,你不大需要一个复杂的堆栈设置,所以本演练使用默认的堆栈名称 `dev`
### 在 IaC 中使用 TypeScript
你可以使用方便的 `pulumi new` 命令来<ruby>初建<rt>bootstrap</rt></ruby>一个 Pulumi 项目。`new` 命令有一大堆标志和选项,可以帮助你入门 Pulumi所以请继续创建你的第一个项目
```
$ pulumi new typescript
This command will walk you through creating a new Pulumi project.
Enter a value or leave blank to accept the (default), and press <ENTER>.
Press ^C at any time to quit.
project name: (pulumi) my-first-project
project description: (A minimal TypeScript Pulumi program) My very first Pulumi program
Created project 'my-first-project'
Please enter your desired stack name.
To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`).
stack name: (dev) dev
Created stack 'dev'
Installing dependencies...
> node scripts/postinstall
added 82 packages from 126 contributors and audited 82 packages in 2.84s
13 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Finished installing dependencies
Your new project is ready to go! ✨
To perform an initial deployment, run 'pulumi up'
```
这里发生了很多事情,我将其展开来说:
第一部分是为你的 Pulumi 项目确定一个模板。我选择了通用的 `typescript` 选项,但是有[很多选项可供选择][25]。
这个 `new` 命令从你的模板库中抓取模板,并将这个文件复制到本地,包括运行时的依赖关系(在本例中是 `package.json`)。
`new` 命令通过在这个目录下运行 `npm install` 来安装这些依赖关系。然后 `npm install` 下载并安装运行 Pulumi 程序所需的一切,在这种情况下就是:`@pulumi/pulumi` NPM 包。
你已经准备好创建你的第一个资源了!
### 创建你的第一个云资源
资源是一个由你的基础设施供应软件生命周期进行管理的东西。资源一般是一个<ruby>云提供商对象<rt>cloud provider object</rt></ruby>,比如 S3 桶。Pulumi 的提供商处理 Pulumi 资源提供商是具体的云提供商。Pulumi 有大约 [40 个提供商][26]可供你使用,但对于你的第一个资源,使用一个最简单的:<ruby>[随机提供商][27]<rt>random provider</rt></ruby>
随机提供者顾名思义:它幂等地创建一个随机资源(例如,可以是一个字符串),并将其存储在 Pulumi 状态中。
使用 `npm` 将其添加到你的 Pulumi 项目中作为依赖关系:
```
npm install @pulumi/random
```
npm 包管理器下载并安装随机提供者包,并为你安装。现在你已经准备好编写你的 Pulumi 程序了。
当你之前生成你的项目时Pulumi 的初建过程创建了一个 `index.ts` TypeScript 文件。在你喜欢的集成开发环境IDE中打开它并添加你的第一个资源
```
import * as pulumi from "@pulumi/pulumi";
import * as random from "@pulumi/random";
const password = new random.RandomString(`password`, {
    length: 10
})
```
如果你对 TypeScript 或 JavaScript 非常熟悉,这看起来会非常熟悉,因为它是用你熟悉的编程语言编写的。如果你使用的是 Pulumi 支持的其他语言之一,也是一样的。这里是之前的那个随机资源,但这次是用 Python 写的:
```
import pulumi_random as random
password = random.RandomString("password", length=10)
```
一个 Pulumi 项目目前只支持单一一种语言,但每个项目都可以引用其他语言编写的项目,这对于多语言团队的成员来说是一个很有用的技巧。
你已经编写了第一个 Pulumi 资源。现在你需要部署它。
离开编辑器,回到命令行。在你的项目目录下,运行 `pulumi up`,然后看着神奇的事情发生:
```
pulumi up
Previewing update (dev):
     Type                          Name                  Plan
 +   pulumi:pulumi:Stack           my-first-project-dev  create
 +   └─ random:index:RandomString  password              create
Resources:
    + 2 to create
Do you want to perform this update? yes
Updating (dev):
     Type                          Name                  Status
 +   pulumi:pulumi:Stack           my-first-project-dev  created
 +   └─ random:index:RandomString  password              created
Resources:
    + 2 created
Duration: 2s
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
```
太好了,你有了第一个 Pulumi 资源! 虽然你可能很享受这种成就感,但不幸的是,这个随机资源并没有那么有用:它只是一个随机的字符串,你甚至看不到它是什么。先解决这部分问题。修改你之前的程序,在你创建的常量中加入 `export`
```
import * as pulumi from "@pulumi/pulumi";
import * as random from "@pulumi/random";
export const password = new random.RandomString(`password`, {
    length: 10
})
```
重新运行 `pulumi up`,看看输出:
```
pulumi up
Previewing update (dev):
Type Name Plan
pulumi:pulumi:Stack my-first-project-dev
Outputs:
+ password: {
+ id : "&+r?{}J$J7"
+ keepers : output<string>
+ length : 10
+ lower : true
+ minLower : 0
+ minNumeric : 0
+ minSpecial : 0
+ minUpper : 0
+ number : true
+ overrideSpecial: output<string>
+ result : "&+r?{}J$J7"
+ special : true
+ upper : true
+ urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
}
Resources:
2 unchanged
Do you want to perform this update? yes
Updating (dev):
Type Name Status
pulumi:pulumi:Stack my-first-project-dev
Outputs:
+ password: {
+ id : "&+r?{}J$J7"
+ length : 10
+ lower : true
+ minLower : 0
+ minNumeric: 0
+ minSpecial: 0
+ minUpper : 0
+ number : true
+ result : "&+r?{}J$J7"
+ special : true
+ upper : true
+ urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
}
Resources:
2 unchanged
Duration: 1s
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
```
现在你可以在 `Outputs``result` 部分下看到一个随机生成的字符串。你现在可以看到你创建的资源有很多属性。
这一切都很好,但如果你想享受 IaC你得提供一些随机字符串以外的东西。试试吧。
### 部署一个容器
到目前为止,你已经通过安装依赖关系和注册一个简单的随机资源来 体验了初建你的 Pulumi。现在部署一些实际的基础设施尽管是在你的本地机器上。
首先,将 `@pulumi/docker` 提供者添加到你的堆栈中。使用你选择的包管理器将其添加到项目中:
```
npm install @pulumi/docker
```
你已经从 `npm` 下拉了 Pulumi Docker 提供商包,这意味着你现在可以在你的项目中创建 Docker 镜像。
如果你的机器上还没有安装 Docker现在是一个极好的时机去安装它。说明将取决于你的操作系统所以看看 [Docker 的安装页面][28]了解信息。
再次打开你喜欢的 IDE运行一个 Docker 容器。修改你之前的 `index.ts` 文件,让它看起来像这样:
```
import * as pulumi from "@pulumi/pulumi";
import * as random from "@pulumi/random";
import * as docker from "@pulumi/docker";
const password = new random.RandomString(`password`, {
    length: 10
})
const container = new docker.Container(`my-password`, {
    image: 'hashicorp/http-echo',
    command: [ pulumi.interpolate`-text=Your super secret password is: ${password.result}` ],
    ports: [{
        internal: 5678,
        external: 5678,
    }]
})
export const id = container.id
```
这将创建一个容器,创建一个 Web 服务器。Web 服务器的输出是你随机生成的字符串,在本例中是一个密码。运行这个,看看会发生什么:
```
pulumi up
Previewing update (dev):
Type Name Plan
pulumi:pulumi:Stack my-first-project-dev
+ └─ docker:index:Container my-password create
Outputs:
+ id : output<string>
~ password: {
id : "&+r?{}J$J7"
length : 10
lower : true
minLower : 0
minNumeric: 0
minSpecial: 0
minUpper : 0
number : true
result : "&+r?{}J$J7"
special : true
upper : true
urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
}
Resources:
+ 1 to create
2 unchanged
Do you want to perform this update? yes
Updating (dev):
Type Name Status
pulumi:pulumi:Stack my-first-project-dev
+ └─ docker:index:Container my-password created
Outputs:
+ id : "e73b34aeca34a64b72b61b0b9b8438637ce28853937bc359a1528ca99f49ddda"
password: {
id : "&+r?{}J$J7"
length : 10
lower : true
minLower : 0
minNumeric: 0
minSpecial: 0
minUpper : 0
number : true
result : "&+r?{}J$J7"
special : true
upper : true
urn : "urn:pulumi:dev::my-first-project::random:index/randomString:RandomString::password"
}
Resources:
+ 1 created
2 unchanged
Duration: 2s
Permalink: file:///Users/lbriggs/.pulumi/stacks/dev.json
```
你会注意到在 `Outputs` 部分,你输出的值已经改变了,它只是一个 Docker 容器 ID。检查你的非常简单的密码生成器是否工作
```
curl http://localhost:5678
Your super secret password is: &+r?{}J$J7
```
就是这样! 你刚刚用 TypeScript 配置了你的第一个基础架构。
#### 关于 Pulumi 输出的快速说明
你会注意到在创建 Docker 容器的代码中,它使用了一个特殊的 `pulumi.interpolate` 调用。如果你熟悉 TypeScript你可能会好奇为什么需要这样做因为它是 Pulumi 特有的)。这有一个有趣的原因。
当 Pulumi 创建一个资源时,直到程序执行时有一些值是 Pulumi 不知道的。在 Pulumi 中,这些值被称为 `Outputs`。这些 `Outputs` 可以在上面的代码中看到,例如,在你的第一个随机资源中,你使用 `export` 关键字来输出随机资源的属性,你还输出了你创建的容器的容器 ID。
因为 Pulumi 直到执行时才知道这些 `Outputs` 的值,所以在操作字符串时,它需要特殊的助手来使用它们。如果你想了解更多关于这个特殊的编程模型,请观看[这个短视频][29]。
### 总结
随着混合云基础架构中出现的复杂性IaC 在很多方面都有了发展。在基础设施供应领域Pulumi 是一个很好的选择,它可以使用你最喜欢的编程语言来供应你所需要的一切基础设施,然后你可以在你最喜欢的配置管理工具中进行标记,以采取下一步措施。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/8/infrastructure-as-code-pulumi
作者:[Lee Briggs][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/lbriggs
[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://opensource.com/resources/devops
[3]: https://git-scm.com/
[4]: https://www.mercurial-scm.org/
[5]: https://opensource.com/article/18/12/configuration-management-tools
[6]: https://opensource.com/article/20/7/terraform-kubernetes
[7]: https://www.pulumi.com/
[8]: https://developer.mozilla.org/en-US/docs/Web/JavaScript
[9]: https://www.typescriptlang.org/
[10]: https://golang.org/
[11]: https://www.python.org/
[12]: https://en.wikipedia.org/wiki/C_Sharp_(programming_language)
[13]: https://www.pulumi.com/docs/intro/cloud-providers/aws/
[14]: https://www.pulumi.com/docs/intro/cloud-providers/azure/
[15]: https://www.pulumi.com/docs/intro/cloud-providers/gcp/
[16]: https://www.pulumi.com/docs/reference/pkg/
[17]: https://nodejs.org/en/download/
[18]: https://brew.sh/
[19]: https://opensource.com/article/20/6/homebrew-mac
[20]: https://opensource.com/article/20/6/homebrew-linux
[21]: https://www.pulumi.com/docs/get-started/install/
[22]: https://www.pulumi.com/docs/intro/concepts/state/
[23]: https://www.pulumi.com/docs/intro/concepts/project/
[24]: https://www.pulumi.com/docs/intro/concepts/stack/
[25]: https://github.com/pulumi/templates
[26]: https://www.pulumi.com/docs/intro/cloud-providers/
[27]: https://www.pulumi.com/docs/intro/cloud-providers/random/
[28]: https://docs.docker.com/get-docker/
[29]: https://www.youtube.com/watch?v=lybOxul2otM

View File

@ -0,0 +1,202 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12783-1.html)
[#]: subject: (How to Install Ubuntu Server on a Raspberry Pi)
[#]: via: (https://itsfoss.com/install-ubuntu-server-raspberry-pi/)
[#]: author: (Dimitrios Savvopoulos https://itsfoss.com/author/dimitrios/)
如何在树莓派上安装 Ubuntu 服务器?
======
![][6]
[树莓派][1]是最著名的[单板计算机][2]。最初,树莓派项目的范围旨在促进学校和发展中国家的计算机基础科学的教学。
它的低成本、便携性和极低的功耗,使得它的受欢迎程度远远超过预期。从气象站到家庭自动化,玩家们用树莓派搭建了许多[酷炫的项目][3]。
[第四代树莓派][4]具备了普通台式电脑的功能和处理能力。但本文并不是要介绍如何使用树莓派作为桌面。相反,我会告诉你如何在树莓派上安装 Ubuntu 服务器。
在本教程中,我将使用树莓派 4以下是我将介绍的内容
* 在 microSD 卡上安装 Ubuntu 服务器
* 在树莓派上设置无线网络连接
* 通过 SSH 访问你的树莓派
![][5]
**本教程需要以下设备**
* 一张 micro SD 卡(建议使用 8GB 或更大的卡)
* 一台带有 micro SD 卡读卡器的计算机(运行 Linux、Windows 或 macOS
* 树莓派 2、3 或 4
* 良好的互联网连接
* 用于树莓派 2 和 3 的 HDMI 线和用于树莓派 4 的 micro HDMI 线(可选)
* 一套 USB 键盘(可选)
### 在树莓派上安装 Ubuntu 服务器
在本教程中,我使用 Ubuntu 来创建树莓派 SD 卡,但你可以在其他 Linux 发行版、macOS 和 Windows 上创建它。这是因为准备 SD 卡的步骤对 Raspberry Pi Imager 工具而言是一样的。
Raspberry Pi Imager 工具会自动下载你[选择的树莓派系统][7]镜像。这意味着你需要一个良好的网络连接来下载 1GB 左右的数据。
#### 步骤 1用 Raspberry Pi Imager 准备 SD 卡
确保你已将 microSD 卡插入电脑,并在电脑上安装 Raspberry Pi Imager。
你可以从这些链接中下载适合你操作系统的 Imager 工具:
* [用于 Ubuntu/Debian 的 Raspberry Pi Imager][8]
* [用于 Windows 的 Raspberry Pi Imager][9]
* [用于 MacOS 的 Raspberry Pi Imager][10]
尽管我使用的是 Ubuntu但我不会使用上面列出的 Debian 软件包,而是使用命令行安装 snap 包。这个方法可以适用于更广泛的 Linux 发行版。
```
sudo snap install rpi-imager
```
安装好 Raspberry Pi Imager 工具后,找到并打开它,点击 “CHOOSE OS” 菜单。
![][11]
滚动菜单并点击 “Ubuntu” (“核心”和“服务器”镜像)。
![][12]
从可用的镜像中,我选择了 Ubuntu 20.04 LTS 64 位。如果你有一个树莓派 2那你只能选择 32 位镜像。
**重要提示:如果你使用的是最新的树莓派 4 - 8 GB 内存型号,你应该选择 64 位操作系统,否则只能使用 4 GB 内存。**
![][13]
从 “SD Card” 菜单中选择你的 microSD 卡,然后点击 “WRITE”。
![][14]
如果它显示一些错误,请尝试再次写入它。现在它将下载 Ubuntu 服务器镜像并将其写入 micro SD 卡。
当这个过程完成时,它将通知你。
![][15]
#### 步骤 2在 Ubuntu 服务器上添加 WiFi 支持
烧录完 micro SD 卡后,你就差不多可以使用它了。在使用它之前,有一件事情你可能想做,那就是添加 Wi-Fi 支持。
SD 卡仍然插入读卡器中,打开文件管理器,找到卡上的 “system-boot” 分区。
你要找的和需要编辑的文件名为 `network-config`
![][16]
这个过程也可以在 Windows 和 MacOS 上完成。如前所述,编辑 `network-config` 文件,添加你的 Wi-Fi 凭证。
首先,取消矩形框内的行的注释(删除开头的标签 `#`)。
之后,将 `myhomewifi` 替换为你的 Wi-Fi 网络名,比如 `"itsfoss"`,将 `"S3kr1t"` 替换为 Wi-Fi 密码,用引号括起来,比如 `"12345679"`
![][17]
它可能看上去像这样:
```
wifis:
wlan0:
dhcp4: true
optional: true
access-points:
"your wifi name":
password: "your_wifi_password"
```
保存文件并将 micro SD 卡插入到你的树莓派中。在第一次启动时,如果你的树莓派无法连接到 Wi-Fi 网络,只需重启你的设备。
#### 步骤 3在树莓派上使用 Ubuntu 服务器(如果你有专门的显示器、键盘和鼠标的话)
如果你有一套额外的鼠标,键盘和显示器,你可以很容易地像其他电脑一样使用树莓派(但没有 GUI
只需将 micro SD 卡插入树莓派,连接显示器、键盘和鼠标。现在[打开你的树莓派][18]。它将出现 TTY 登录屏幕(黑色终端屏幕)并询问用户名和密码。
* 默认用户名:`ubuntu`
* 默认密码:`ubuntu`
看到提示符时,用 `ubuntu` 作为密码。登录成功后,[Ubuntu 会要求你更改默认密码][19]。
享受你的 Ubuntu 服务器吧!
#### 步骤 3通过 SSH 远程连接到你的树莓派(如果你没有树莓派的显示器、键盘和鼠标的话)
如果你没有专门与树莓派一起使用的显示器也没关系。当你可以直接通过 SSH 进入它并按照你的方式使用它时,谁还需要一个带有显示器的服务器呢?
**在 Ubuntu 和 Mac OS**上,通常已经安装了一个 SSH 客户端。要远程连接到你的树莓派,你需要找到它的 IP 地址。检查[连接到你的网络的设备][20],看看哪个是树莓派。
由于我没有 Windows 机器,你可以访问[微软][21]提供的综合指南。
打开终端,运行以下命令:
```
ssh ubuntu@raspberry_pi_ip_address
```
你可能会看到以下信息确认连接:
```
Are you sure you want to continue connecting (yes/no/[fingerprint])?
```
输入 `yes`,然后点击回车键。
![][22]
当提示时,用前面提到的 `ubuntu` 作为密码。当然,你会被要求更改密码。
完成后,你将自动注销,你必须使用新密码重新连接。
你的 Ubuntu 服务器就可以在树莓派上运行了!
### 总结
在树莓派上安装 Ubuntu 服务器是一个简单的过程,而且它的预配置程度很高,使用起来很愉快。
我不得不说,在所有[我在树莓派上尝试的操作系统][7]中Ubuntu 服务器是最容易安装的。我并没有夸大其词。请查看我的[在树莓派上安装 Arch Linux][23] 的指南,以供参考。
希望这篇指南也能帮助你在树莓派上安装 Ubuntu 服务器。如果你有问题或建议,请在评论区告诉我。
--------------------------------------------------------------------------------
via: https://itsfoss.com/install-ubuntu-server-raspberry-pi/
作者:[Dimitrios Savvopoulos][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/dimitrios/
[b]: https://github.com/lujun9972
[1]: https://www.raspberrypi.org/
[2]: https://itsfoss.com/raspberry-pi-alternatives/
[3]: https://itsfoss.com/raspberry-pi-projects/
[4]: https://itsfoss.com/raspberry-pi-4/
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/Ubuntu-Server-20.04.1-LTS-aarch64.png?resize=800%2C600&ssl=1
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/ubuntu-server-raspberry-pi.png?resize=800%2C450&ssl=1
[7]: https://itsfoss.com/raspberry-pi-os/
[8]: https://downloads.raspberrypi.org/imager/imager_amd64.deb
[9]: https://downloads.raspberrypi.org/imager/imager.exe
[10]: https://downloads.raspberrypi.org/imager/imager.dmg
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/raspberry-pi-imager.png?resize=800%2C600&ssl=1
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/raspberry-pi-imager-choose-ubuntu.png?resize=800%2C600&ssl=1
[13]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/raspberry-pi-imager-ubuntu-server.png?resize=800%2C600&ssl=1
[14]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/raspberry-pi-imager-sd-card.png?resize=800%2C600&ssl=1
[15]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/ubuntu-server-installed-raspberry-pi.png?resize=799%2C506&ssl=1
[16]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/ubuntu-server-pi-network-config.png?resize=800%2C565&ssl=1
[17]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/Ubuntu-server-wifi.png?resize=800%2C600&ssl=1
[18]: https://itsfoss.com/turn-on-raspberry-pi/
[19]: https://itsfoss.com/change-password-ubuntu/
[20]: https://itsfoss.com/how-to-find-what-devices-are-connected-to-network-in-ubuntu/
[21]: https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse
[22]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/ubuntu-server-change-password.png?resize=800%2C600&ssl=1
[23]: https://itsfoss.com/install-arch-raspberry-pi/

View File

@ -0,0 +1,665 @@
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12872-1.html)
[#]: subject: (Add throwing mechanics to your Python game)
[#]: via: (https://opensource.com/article/20/9/add-throwing-python-game)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
在你的 Python 游戏中添加投掷机制
======
> 四处奔跑躲避敌人是一回事,反击敌人是另一回事。学习如何在这系列的第十二篇文章中在 Pygame 中创建平台游戏。
![](https://img.linux.net.cn/data/attachment/album/202011/30/124457xcj9mztw9kx9c7zj.jpg)
这是仍在进行中的关于使用 [Pygame][3] 模块在 [Python 3][2] 中创建电脑游戏的第十二部分。先前的文章是:
1. [通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程][4]
2. [使用 Python 和 Pygame 模块构建一个游戏框架][5]
3. [如何在你的 Python 游戏中添加一个玩家][6]
4. [用 Pygame 使你的游戏角色移动起来][7]
5. [如何向你的 Python 游戏中添加一个敌人][8]
6. [在 Pygame 游戏中放置平台][9]
7. [在你的 Python 游戏中模拟引力][10]
8. [为你的 Python 平台类游戏添加跳跃功能][11]
9. [使你的 Python 游戏玩家能够向前和向后跑][12]
10. [在你的 Python 平台类游戏中放一些奖励][13]
11. [添加计分到你的 Python 游戏][14]
我的上一篇文章本来是这一系列文章的最后一篇,它鼓励你为这个游戏编写自己的附加程序。你们很多人都这么做了!我收到了一些电子邮件,要求帮助我还没有涵盖的常用机制:战斗。毕竟,跳起来躲避坏人是一回事,但是有时候让他们走开是一件非常令人满意的事。在电脑游戏中向你的敌人投掷一些物品是很常见的,不管是一个火球、一支箭、一道闪电,还是其它适合游戏的东西。
与迄今为止你在这个系列中为你的平台游戏编程的任何东西不同,可投掷物品有一个*生存时间*。在你投掷一个物品后,它会如期在移动一段距离后消失。如果它是一支箭或其它类似的东西,它可能会在通过屏幕的边缘时而消失。如果它是一个火球或一道闪电,它可能会在一段时间后熄灭。
这意味着每次生成一个可投掷的物品时,也必须生成一个独特的衡量其生存时间的标准。为了介绍这个概念,这篇文章演示如何一次只投掷一个物品。(换句话说,每次仅存在一个投掷物品)。 一方面,这是一个游戏的限制条件,但另一方面,它却是游戏本身的运行机制。你的玩家不能每次同时投掷 50 个火球,因为每次仅允许一个投掷物品,所以当你的玩家释放一个火球来尝试击中一名敌人就成为了一项挑战。而在幕后,这也使你的代码保持简单。
如果你想启用每次投掷多个项目,在完成这篇教程后,通过学习这篇教程所获取的知识来挑战你自己。
### 创建 Throwable 类
如果你跟随学习这系列的其它文章,那么你应该熟悉在屏幕上生成一个新的对象基础的 `__init__` 函数。这和你用来生成你的 [玩家][6] 和 [敌人][8] 的函数是一样的。这里是生成一个 `throwable` 对象的 `__init__` 函数来:
```
class Throwable(pygame.sprite.Sprite):
"""
生成一个 throwable 对象
"""
def __init__(self, x, y, img, throw):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images',img))
self.image.convert_alpha()
self.image.set_colorkey(ALPHA)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.firing = throw
```
同你的 `Player` 类或 `Enemy` 类的 `__init__` 函数相比,这个函数的主要区别是,它有一个 `self.firing` 变量。这个变量保持跟踪一个投掷的物品是否在当前屏幕上活动,因此当一个 `throwable` 对象创建时,将变量设置为 `1` 的合乎情理的。
### 判断存活时间
接下来,就像使用 `Player``Enemy` 一样,你需要一个 `update` 函数,以便投掷的物品在瞄准敌人抛向空中时,它会自己移动。
测定一个投掷的物品存活时间的最简单方法是侦测它何时离开屏幕。你需要监视的屏幕边缘取决于你投掷的物品的物理特性。
* 如果你的玩家正在投掷的物品是沿着水平轴快速移动的,像一只弩箭或箭或一股非常快的魔法力量,而你想监视你游戏屏幕的水平轴极限。这可以通过 `worldx` 定义。
* 如果你的玩家正在投掷的物品是沿着垂直方向或同时沿着水平方向和垂直方向移动的,那么你必须监视你游戏屏幕的垂直轴极限。这可以通过 `worldy` 定义。
这个示例假设你投掷的物品向前移动一点并最终落到地面上。不过,投掷的物品不会从地面上反弹起来,而是继续掉落出屏幕。你可以尝试不同的设置来看看什么最适合你的游戏:
```
def update(self,worldy):
'''
投掷物理学
'''
if self.rect.y < worldy: #垂直轴
self.rect.x += 15 #它向前移动的速度有多快
self.rect.y += 5 #它掉落的速度有多快
else:
self.kill() #移除投掷对象
self.firing = 0 #解除火力发射
```
为使你的投掷物品移动地更快,增加 `self.rect` 的动量值。
如果投掷物品不在屏幕上,那么该物品将被销毁,以及释放其所占用的寄存器。另外,`self.firing` 将被设置回 `0` 以允许你的玩家来进行另一次射击。
### 设置你的投掷对象
就像使用你的玩家和敌人一样,你必须在你的设置部分中创建一个精灵组来保持投掷对象。
此外,你必须创建一个非活动的投掷对象来供开始的游戏使用。如果在游戏开始时却没有一个投掷对象,那么玩家在第一次尝试投掷一柄武器时,投掷将失败。
这个示例假设你的玩家使用一个火球作为开始的武器,因此,每一个投掷实例都是由 `fire` 变量指派的。在后面的关卡中,当玩家获取新的技能时,你可以使用相同的 `Throwable` 类来引入一个新的变量以使用一张不同的图像。
在这代码块中,前两行已经在你的代码中,因此不要重新键入它们:
```
player_list = pygame.sprite.Group() #上下文
player_list.add(player) #上下文
fire = Throwable(player.rect.x,player.rect.y,'fire.png',0)
firepower = pygame.sprite.Group()
```
注意,每一个投掷对象的起始位置都是和玩家所在的位置相同。这使得它看起来像是投掷对象来自玩家。在第一个火球生成时,使用 `0` 来显示 `self.firing` 是可用的。
### 在主循环中获取投掷行为
没有在主循环中出现的代码不会在游戏中使用,因此你需要在你的主循环中添加一些东西,以便能在你的游戏世界中获取投掷对象。
首先,添加玩家控制。当前,你没有火力触发器。在键盘上的按键是有两种状态的:释放的按键,按下的按键。为了移动,你要使用这两种状态:按下按键来启动玩家移动,释放按键来停止玩家移动。开火仅需要一个信号。你使用哪个按键事件(按键按下或按键释放)来触发你的投掷对象取决于你的品味。
在这个代码语句块中,前两行是用于上下文的:
```
if event.key == pygame.K_UP or event.key == ord('w'):
player.jump(platform_list)
if event.key == pygame.K_SPACE:
if not fire.firing:
fire = Throwable(player.rect.x,player.rect.y,'fire.png',1)
firepower.add(fire)
```
与你在设置部分创建的火球不同,你使用一个 `1` 来设置 `self.firing` 为不可用。
最后,你必须更新和绘制你的投掷物品。这个顺序很重要,因此把这段代码放置到你现有的 `enemy.move``player_list.draw` 的代码行之间:
```
enemy.move() # 上下文
if fire.firing:
fire.update(worldy)
firepower.draw(world)
player_list.draw(screen) # 上下文
enemy_list.draw(screen) # 上下文
```
注意,这些更新仅在 `self.firing` 变量被设置为 1 时执行。如果它被设置为 0 ,那么 `fire.firing` 就不为 `true`,接下来就跳过更新。如果你尝试做上述这些更新,不管怎样,你的游戏都会崩溃,因为在游戏中将不会更新或绘制一个 `fire` 对象。
启动你的游戏,尝试挑战你的武器。
### 检测碰撞
如果你玩使用了新投掷技巧的游戏,你可能会注意到,你可以投掷对象,但是它却不会对你的敌人有任何影响。
原因是你的敌人没有被查到碰撞事故。一名敌人可能会被你的投掷物品所击中,但是敌人却从来不知道被击中了。
你已经在你的 `Player` 类中完成了碰撞检测,这非常类似。在你的 `Enemy` 类中,添加一个新的 `update` 函数:
```
def update(self,firepower, enemy_list):
"""
检测火力碰撞
"""
fire_hit_list = pygame.sprite.spritecollide(self,firepower,False)
for fire in fire_hit_list:
enemy_list.remove(self)
```
代码很简单。每个敌人对象都检查并看看它自己是否被 `firepower` 精灵组的成员所击中。如果它被击中,那么敌人就会从敌人组中移除和消失。
为集成这些功能到你的游戏之中,在主循环中调用位于新触发语句块中的函数:
```
if fire.firing: # 上下文
fire.update(worldy) # 上下文
firepower.draw(screen) # 上下文
enemy_list.update(firepower,enemy_list) # 更新敌人
```
你现在可以尝试一下你的游戏了,大多数的事情都如预期般的那样工作。不过,这里仍然有一个问题,那就是投掷的方向。
### 更改投掷机制的方向
当前,你英雄的火球只会向右移动。这是因为 `Throwable` 类的 `update` 函数将像素添加到火球的位置,在 Pygame 中,在 X 轴上一个较大的数字意味着向屏幕的右侧移动。当你的英雄转向另一个方向时,你可能希望它投掷的火球也抛向左侧。
到目前为止,你已经知道如何实现这一点,至少在技术上是这样的。然而,最简单的解决方案却是使用一个变量,在一定程度上对你来说可能是一种新的方法。一般来说,你可以“设置一个标记”(有时也被称为“翻转一个位”)来标明你的英雄所面向的方向。在你做完后,你就可以检查这个变量来得知火球是向左移动还是向右移动。
首先,在你的 `Player` 类中创建一个新的变量来代表你的游戏所面向的方向。因为我的游戏天然地面向右侧,由此我把面向右侧作为默认值:
```
self.score = 0
self.facing_right = True # 添加这行
self.is_jumping = True
```
当这个变量是 `True` 时,你的英雄精灵是面向右侧的。当玩家每次更改英雄的方向时,变量也必须重新设置,因此,在你的主循环中相关的 `keyup` 事件中这样做:
```
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(steps, 0)
player.facing_right = False # 添加这行
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(-steps, 0)
player.facing_right = True # 添加这行
```
最后,更改你的 `Throwable` 类的 `update` 函数,以检测英雄是否面向右侧,并恰当地添加或减去来自火球位置的像素:
```
if self.rect.y < worldy:
if player.facing_right:
self.rect.x += 15
else:
self.rect.x -= 15
self.rect.y += 5
```
再次尝试你的游戏,清除掉你游戏世界中的一些坏人。
![Python 平台类使用投掷能力][15]
作为一项额外的挑战,当彻底打败敌人时,尝试增加你玩家的得分。
### 完整的代码
```
#!/usr/bin/env python3
# 作者: Seth Kenlon
# GPLv3
# 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/>][17].
import pygame
import pygame.freetype
import sys
import os
'''
变量
'''
worldx = 960
worldy = 720
fps = 40
ani = 4
world = pygame.display.set_mode([worldx, worldy])
forwardx = 600
backwardx = 120
BLUE = (80, 80, 155)
BLACK = (23, 23, 23)
WHITE = (254, 254, 254)
ALPHA = (0, 255, 0)
tx = 64
ty = 64
font_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "fonts", "amazdoom.ttf")
font_size = tx
pygame.freetype.init()
myfont = pygame.freetype.Font(font_path, font_size)
'''
对象
'''
def stats(score, health):
myfont.render_to(world, (4, 4), "Score:"+str(score), BLUE, None, size=64)
myfont.render_to(world, (4, 72), "Health:"+str(health), BLUE, None, size=64)
class Throwable(pygame.sprite.Sprite):
"""
生成一个投掷的对象
"""
def __init__(self, x, y, img, throw):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images', img))
self.image.convert_alpha()
self.image.set_colorkey(ALPHA)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.firing = throw
def update(self, worldy):
'''
投掷物理学
'''
if self.rect.y < worldy:
if player.facing_right:
self.rect.x += 15
else:
self.rect.x -= 15
self.rect.y += 5
else:
self.kill()
self.firing = 0
# x 位置, y 位置, img 宽度, img 高度, img 文件
class Platform(pygame.sprite.Sprite):
def __init__(self, xloc, yloc, imgw, imgh, img):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images', img)).convert()
self.image.convert_alpha()
self.image.set_colorkey(ALPHA)
self.rect = self.image.get_rect()
self.rect.y = yloc
self.rect.x = xloc
class Player(pygame.sprite.Sprite):
"""
生成一名玩家
"""
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.movex = 0
self.movey = 0
self.frame = 0
self.health = 10
self.damage = 0
self.score = 0
self.facing_right = True
self.is_jumping = True
self.is_falling = True
self.images = []
for i in range(1, 5):
img = pygame.image.load(os.path.join('images', 'walk' + str(i) + '.png')).convert()
img.convert_alpha()
img.set_colorkey(ALPHA)
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
def gravity(self):
if self.is_jumping:
self.movey += 3.2
def control(self, x, y):
"""
控制玩家移动
"""
self.movex += x
def jump(self):
if self.is_jumping is False:
self.is_falling = False
self.is_jumping = True
def update(self):
"""
更新精灵位置
"""
# 向左移动
if self.movex < 0:
self.is_jumping = True
self.frame += 1
if self.frame > 3 * ani:
self.frame = 0
self.image = pygame.transform.flip(self.images[self.frame // ani], True, False)
# 向右移动
if self.movex > 0:
self.is_jumping = True
self.frame += 1
if self.frame > 3 * ani:
self.frame = 0
self.image = self.images[self.frame // ani]
# 碰撞
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
if self.damage == 0:
for enemy in enemy_hit_list:
if not self.rect.contains(enemy):
self.damage = self.rect.colliderect(enemy)
if self.damage == 1:
idx = self.rect.collidelist(enemy_hit_list)
if idx == -1:
self.damage = 0 # 设置伤害回 0
self.health -= 1 # 减去 1 单位健康度
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
for g in ground_hit_list:
self.movey = 0
self.rect.bottom = g.rect.top
self.is_jumping = False # 停止跳跃
# 掉落世界
if self.rect.y > worldy:
self.health -=1
print(self.health)
self.rect.x = tx
self.rect.y = ty
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
self.is_jumping = False # 停止跳跃
self.movey = 0
if self.rect.bottom <= p.rect.bottom:
self.rect.bottom = p.rect.top
else:
self.movey += 3.2
if self.is_jumping and self.is_falling is False:
self.is_falling = True
self.movey -= 33 # 跳跃多高
loot_hit_list = pygame.sprite.spritecollide(self, loot_list, False)
for loot in loot_hit_list:
loot_list.remove(loot)
self.score += 1
print(self.score)
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
self.rect.x += self.movex
self.rect.y += self.movey
class Enemy(pygame.sprite.Sprite):
"""
生成一名敌人
"""
def __init__(self, x, y, img):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images', img))
self.image.convert_alpha()
self.image.set_colorkey(ALPHA)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.counter = 0
def move(self):
"""
敌人移动
"""
distance = 80
speed = 8
if self.counter >= 0 and self.counter <= distance:
self.rect.x += speed
elif self.counter >= distance and self.counter <= distance * 2:
self.rect.x -= speed
else:
self.counter = 0
self.counter += 1
def update(self, firepower, enemy_list):
"""
检测火力碰撞
"""
fire_hit_list = pygame.sprite.spritecollide(self, firepower, False)
for fire in fire_hit_list:
enemy_list.remove(self)
class Level:
def ground(lvl, gloc, tx, ty):
ground_list = pygame.sprite.Group()
i = 0
if lvl == 1:
while i < len(gloc):
ground = Platform(gloc[i], worldy - ty, tx, ty, 'tile-ground.png')
ground_list.add(ground)
i = i + 1
if lvl == 2:
print("Level " + str(lvl))
return ground_list
def bad(lvl, eloc):
if lvl == 1:
enemy = Enemy(eloc[0], eloc[1], 'enemy.png')
enemy_list = pygame.sprite.Group()
enemy_list.add(enemy)
if lvl == 2:
print("Level " + str(lvl))
return enemy_list
# x 位置, y 位置, img 宽度, img 高度, img 文件
def platform(lvl, tx, ty):
plat_list = pygame.sprite.Group()
ploc = []
i = 0
if lvl == 1:
ploc.append((200, worldy - ty - 128, 3))
ploc.append((300, worldy - ty - 256, 3))
ploc.append((550, worldy - ty - 128, 4))
while i &lt; len(ploc):
j = 0
while j <= ploc[i][2]:
plat = Platform((ploc[i][0] + (j * tx)), ploc[i][1], tx, ty, 'tile.png')
plat_list.add(plat)
j = j + 1
print('run' + str(i) + str(ploc[i]))
i = i + 1
if lvl == 2:
print("Level " + str(lvl))
return plat_list
def loot(lvl):
if lvl == 1:
loot_list = pygame.sprite.Group()
loot = Platform(tx*5, ty*5, tx, ty, 'loot_1.png')
loot_list.add(loot)
if lvl == 2:
print(lvl)
return loot_list
'''
Setup 部分
'''
backdrop = pygame.image.load(os.path.join('images', 'stage.png'))
clock = pygame.time.Clock()
pygame.init()
backdropbox = world.get_rect()
main = True
player = Player() # 生成玩家
player.rect.x = 0 # 转到 x
player.rect.y = 30 # 转到 y
player_list = pygame.sprite.Group()
player_list.add(player)
steps = 10
fire = Throwable(player.rect.x, player.rect.y, 'fire.png', 0)
firepower = pygame.sprite.Group()
eloc = []
eloc = [300, worldy-ty-80]
enemy_list = Level.bad(1, eloc)
gloc = []
i = 0
while i &lt;= (worldx / tx) + tx:
gloc.append(i * tx)
i = i + 1
ground_list = Level.ground(1, gloc, tx, ty)
plat_list = Level.platform(1, tx, ty)
enemy_list = Level.bad( 1, eloc )
loot_list = Level.loot(1)
'''
主循环
'''
while main:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
try:
sys.exit()
finally:
main = False
if event.type == pygame.KEYDOWN:
if event.key == ord('q'):
pygame.quit()
try:
sys.exit()
finally:
main = False
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(-steps, 0)
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(steps, 0)
if event.key == pygame.K_UP or event.key == ord('w'):
player.jump()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(steps, 0)
player.facing_right = False
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(-steps, 0)
player.facing_right = True
if event.key == pygame.K_SPACE:
if not fire.firing:
fire = Throwable(player.rect.x, player.rect.y, 'fire.png', 1)
firepower.add(fire)
# 向向滚动世界
if player.rect.x >= forwardx:
scroll = player.rect.x - forwardx
player.rect.x = forwardx
for p in plat_list:
p.rect.x -= scroll
for e in enemy_list:
e.rect.x -= scroll
for l in loot_list:
l.rect.x -= scroll
# 向后滚动世界
if player.rect.x <= backwardx:
scroll = backwardx - player.rect.x
player.rect.x = backwardx
for p in plat_list:
p.rect.x += scroll
for e in enemy_list:
e.rect.x += scroll
for l in loot_list:
l.rect.x += scroll
world.blit(backdrop, backdropbox)
player.update()
player.gravity()
player_list.draw(world)
if fire.firing:
fire.update(worldy)
firepower.draw(world)
enemy_list.draw(world)
enemy_list.update(firepower, enemy_list)
loot_list.draw(world)
ground_list.draw(world)
plat_list.draw(world)
for e in enemy_list:
e.move()
stats(player.score, player.health)
pygame.display.flip()
clock.tick(fps)
```
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/add-throwing-python-game
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean)
校对:[wxy](https://github.com/wxy)
本文由 [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/game_pawn_grid_linux.png?itok=4gERzRkg (Gaming on a grid with penguin pawns)
[2]: https://www.python.org/
[3]: https://www.pygame.org/news
[4]: https://linux.cn/article-9071-1.html
[5]: https://linux.cn/article-10850-1.html
[6]: https://linux.cn/article-10858-1.html
[7]: https://linux.cn/article-10874-1.html
[8]: https://linux.cn/article-10883-1.html
[9]: https://linux.cn/article-10902-1.html
[10]: https://linux.cn/article-11780-1.html
[11]: https://linux.cn/article-11790-1.html
[12]: https://linux.cn/article-11819-1.html
[13]: https://linux.cn/article-11828-1.html
[14]: https://linux.cn/article-11839-1.html
[15]: https://opensource.com/sites/default/files/uploads/pygame-throw.jpg (Python platformer with throwing capability)
[16]: https://creativecommons.org/licenses/by-sa/4.0/
[17]: http://www.gnu.org/licenses/\>

View File

@ -0,0 +1,136 @@
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12874-1.html)
[#]: subject: (Easily set image transparency using GIMP)
[#]: via: (https://opensource.com/article/20/9/chroma-key-gimp)
[#]: author: (Seth Kenlon https://opensource.com/users/seth)
使用 GIMP 轻松地设置图片透明度
======
> 使用色键(绿屏)技巧来设置你电脑游戏中图片的透明度。
![](https://img.linux.net.cn/data/attachment/album/202011/30/223815rdmrgx1109ngng0g.jpg)
不管你是否正在使用 [Python][2] 或 [Lua][3] 编程一个游戏或一个 APP你都有可能在你的游戏资源中使用 PNG 图像。PNG 格式图像的一个优点是能够存储一个 **alpha 通道**,这在一个 JPEG 格式的图像中是不可能获得的。alpha 在本质上是不可见的或透明的“颜色”。alpha 是你图像 _不可见_ 的一部分。例如,你要绘制一个甜甜圈,甜甜圈的空洞将使用 alpha 填充,你就可以看到它后面的任何东西。
一个常见的问题是如何找到一幅图像的 alpha 部分。有时你的编程框架,不管它是 [Python Arcade][4]、[Pygame][5]、LÖVE或者其它的任何东西都会检测出 alpha 通道,(在适当地调用函数后)将其作为透明处理。这意味着它将不会在 alpha 部分来渲染新的像素而留下甜甜圈的空洞。100% 是透明的0% 是不透明的,在功能上起到“不可见”的作用。
有些时候,你的框架与你的图像资源在 alpha 通道的位置上是不一致的或者alpha 通道根本就不存在),你在你想要透明度的地方却得到像素。
这篇文章描述了我所知道的最可靠的方法来解决透明度的问题。
### 色键
在计算机图形学中,有一些有助于确定每一个像素是如何渲染的值。<ruby>色度<rt>Chrominance</rt></ruby>(或者 chroma描述一个像素的饱和度或强度。<ruby>色键<rt>chroma key</rt></ruby>技术(也称为<ruby>绿屏<rt>green screening</rt></ruby>)最初是作为一种化学工艺而发展起来的,在复印一张底片时,使用一种特定的 **无光泽** 的颜色(最初是蓝色,后来是绿色)来故意遮掩,以允许使用另一幅图像来取代曾经有蓝色或绿色屏幕的地方。这是一种简化的解释,但是它说明了计算机图形学中被称为 alpha 通道的起源。
alpha 通道是保存在图像中的信息用以标识要透明的像素。例如RGB 图像有红、绿、蓝通道。RGBA 图像包含红、绿、蓝通道,以及 alpha 通道。alpha 值的范围可以从 0 到 1 ,使用小数是也有效的。
因为一个 alpha 通道可以用几种不同的方法表达,因此依赖于嵌入的 alpha 通道可能是有问题的。作为替代方案,你可以在你的游戏框架中选择一种颜色并将其转化为一个 0 的 alpha 值。要做到这一点,你必须知道在你图像中的颜色值。
### 准备你的图片
要准备一个专门为色度键保留明确颜色的图形,在你最喜欢的图片编辑器中打开图片。我建议使用 [GIMP][6] 或 [Glimpse][7],但是 [mtPaint][8] 或 [Pinta][9],甚至 [Inkscape][10] 也能很好地工作,这取决于你的图像的性质,以及你将这些操作指南转换到一种不同图片编辑器工具的能力。
首先打开这幅 Tux 企鹅的图像:
![Tux 企鹅][11]
### 选择图片
在图片打开后,转到 **窗口** 菜单,选择 **可停靠对话框** ,接下来选择 **图层**。在 **图层** 面板中 Tux 图层上右击。从弹出菜单中,选择 **Alpha 到选区** 。如果你的图像没有内置的 alpha 通道,那么你必须手动创建你自己的选区。
![Alpha 到选区][13]
为手动创建一个选区,单击来自工具箱的 **路径** 工具。
![GIMP 的路径工具][14]
使用 **路径** 工具,在图像周围移动鼠标,在其轮廓的每个主要交叉点处都单击和释放(不要拖动)。 不要担心沿着曲线走;只需要找到主要的交叉点和拐角。这将在每个点处创建一个节点,并在节点中间绘制一条条线段。你不需要闭合你的路径,因此当你最后到达你开始时的交叉点时,你就完成了。
![在 GIMP 中创建一个路径][15]
在你创建你的轮廓路径后,转到 **窗口** 菜单,选择 **可停靠对话框** ,接下来选择 **工具选项** 。在 **工具选项** 面板中,选择 **编辑 (Ctrl)** 。随着这项操作的激活,你可以编辑你刚刚通过单击线或单击节点绘制的路径,并通过调整它们来更好地适应你的图像。你甚至能够将直线弯曲。
![编辑路径][16]
现在从 **窗口 > 可停靠对话框** 菜单中选择 **路径** 面板。在 **路径** 面板中,单击 **路径到选区** 按钮。你的绘图现在已经被选中了。
### 扩大选区
如果你觉得你的选区太紧贴了,你可以通过扩大来给予你自己的选区一些富余。当我想在一张图像周围采用或加厚一个边框时,我有时会这么扩大选区。
为扩大一个选区,单击 **选择** 菜单,选择 **扩大** 。输入一个像素值并单击 **确定**
### 反转选区
你已经选择了你的图形,但是你真正想选择的东西却 _不包括_ 你所选择的图像。这是因为你要创建一个 alpha 蒙版来定义图像中的一些内容的来被其它一些内容所替换。换句话说,你需要标记那些将被转变为不可见的像素。
为了反转选择区,单击 **选择** 菜单,选择 **反转** 。现在除你的图像以外的一切东西都是被选择的。
### 使用 alpha 填充
随着选择了除了你的图像以外的一切东西,再选择你想使用的颜色来指定你的 alpha 蒙版。最常用的颜色是绿色(正如你可能从术语“绿屏”中所猜到的一样)。绿色不是什么神奇的颜色,甚至也不是特定的绿色色调。之所以使用它是因为人们经常处理不包含绿色色素的图像,这样人们能够很容易分离出绿色,而不会意外地分离出图像中重要的部分。当然,如果你的图像是一位绿色的外星人或一枚绿宝石或一些 _确实_ 包含绿色的东西,那么你应该使用一种不同的颜色。只要你所选择的颜色是单一的单色,那么你就可以使用你所希望的任意颜色。如果你正在处理很多图像,你的选择应该在所有图像中保持一致。
![在工具箱中的前景色][17]
使用你选择的颜色值来设置你的前景色。为确保你的选择是精确的,使用 [HTML][18] 或 [HSV][19] 表示的颜色。例如,如果你正在使用纯绿色,它可以在 GIMP以及大多数的开放源码图像应用程序中表示为 `00ff00``00` 是红色,`FF` 是绿色,`00` 是蓝色,`F` 是最大值)。
![设置颜色值][20]
不管你选择什么颜色,务必记录下 HTML 或 HSV 的值,以便你可以为每一张图像使用完全相同的颜色。
为填充你的 alpha 蒙版,单击 **编辑** 菜单,选择 **使用前景色填充**
### 平整和导出
如果你在你的图像周围留下边框,设置背景颜色来着色你想使用的边界笔刷。这通常是黑色或白色,但是它也可以是任何适宜你游戏审美观的颜色。
在你设置背景颜色后,单击 **图像** 菜单,选择 **平整图像**。不管你是否添加了边框,这样做都是安全的。这个过程将从图像中移除 alpha 通道,并使用背景色填充任何“透明的”像素。
![平整图像][21]
你现在已经为你的游戏引擎准备好了一张图像。导出图像为你的游戏引擎喜欢的任何格式,接下来使用游戏引擎所需要的每一个函数来将图像导入的你的游戏中。在的代码中,设置 alpha 值为 `00ff00`(或你使用的任何颜色),接下来使用游戏引擎的图像转换器来将该颜色作为 alpha 通道处理。
### 其它的方法
这不是唯一能在你游戏图像中获取透明度的方法。查看你游戏引擎的文档来找出它是如何默认尝试处理 alpha 通道的,在你不确定的时候,尝试让你的游戏引擎来自动侦测图像中透明度,然后再去编辑它。有时,你游戏引擎的预期值和你图像的预设值恰巧匹配,那么你就可以直接获取透明度,而不需要做任何额外的工作。
不过,当这些尝试都失败时,尝试一下色键。它为电影业工作了将近 100 年,它也可以为你工作。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/chroma-key-gimp
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean)
校对:[wxy](https://github.com/wxy)
本文由 [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/gaming_grid_penguin.png?itok=7Fv83mHR (Gaming with penguin pawns)
[2]: https://opensource.com/article/17/10/python-101
[3]: https://opensource.com/article/17/4/how-program-games-raspberry-pi
[4]: https://opensource.com/article/18/4/easy-2d-game-creation-python-and-arcade
[5]: https://opensource.com/article/17/12/game-framework-python
[6]: http://gimp.org
[7]: https://glimpse-editor.github.io
[8]: https://opensource.com/article/17/2/mtpaint-pixel-art-animated-gifs
[9]: https://www.pinta-project.com/
[10]: http://inkscape.org
[11]: https://opensource.com/sites/default/files/uploads/tux.png (Tux the penguin)
[12]: https://creativecommons.org/licenses/by-sa/4.0/
[13]: https://opensource.com/sites/default/files/uploads/gimp_alpha-to-selection.jpg (Alpha to selection)
[14]: https://opensource.com/sites/default/files/uploads/gimp_path-tool.jpg (GIMP Paths tool)
[15]: https://opensource.com/sites/default/files/uploads/gimp_path-create.jpg (Create a path in GIMP)
[16]: https://opensource.com/sites/default/files/uploads/gimp_path-edit.jpg (Edit path)
[17]: https://opensource.com/sites/default/files/uploads/gimp_foreground-colour.jpg (Foreground color in toolbox)
[18]: https://www.w3schools.com/colors/colors_picker.asp
[19]: https://en.wikipedia.org/wiki/HSL_and_HSV
[20]: https://opensource.com/sites/default/files/uploads/gimp_colour.jpg (Setting color values)
[21]: https://opensource.com/sites/default/files/uploads/gimp_matte.jpg (Flattening image)

View File

@ -0,0 +1,88 @@
[#]: collector: "lujun9972"
[#]: translator: "xiao-song-123"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-12776-1.html"
[#]: subject: "How open source underpins blockchain technology"
[#]: via: "https://opensource.com/article/20/10/open-source-blockchain"
[#]: author: "Matt Shealy https://opensource.com/users/mshealy"
开源是如何支撑区块链技术发展的
======
> 创造出区块链安全性和可靠性的原因:是开放,而非监管。
![](https://img.linux.net.cn/data/attachment/album/202011/01/155124l5c81g86mfwgjxfx.jpg)
当人们发现以安全性而闻名的区块链技术居然是建立在开源软件代码之上时,通常会感到非常惊讶。事实上,正是这种开放性才赋予了区块链技术的安全性和可靠性。
以开源方式构建的任何事物,其核心价值之一就是为了提高效率。建立起一个有着不同观点和技能的开发人员社区,这些开发人员工作在同一个代码库的时候,可以成倍增加构建出来的应用程序数量以及复杂性。
### 开源比人们想象中的要更加普遍
开源的 Linux就是一种比较流行的操作系统。Linux 为服务器提供了许多服务,这些服务让我们可以轻松地共享个人信息。其中包括 Google、Facebook 和数千个主要网站。当我们使用这些服务时,就是在和这些在网络上运行着 Linux 系统的计算机进行交互。Chromebook 也使用 LinuxAndroid 手机使用的操作系统也是基于 Linux 的。
Linux 不属于任何一家公司,人们可以免费使用并且可以共同协作来完善创造它。自 2005 年推出以来,已经有来自 1,700 多家公司的 20,000 多名开发人员 [为其中的代码做出了贡献][2] 。
这就是开源软件的运作方式。大量的人为此贡献,并不断添加、修改或构建开源代码库来创建新的应用程序和平台。区块链和加密货币的大部分代码都是使用开源软件开发的。开源软件是由充满热情的用户构建的,这些用户对错误、故障或缺陷时刻保持警惕。当发现问题时,开源社区中的开发人员将一起努力来解决问题。
### 区块链和开源
整个开源区块链开发者社区都在不断地添加和完善代码库。
以下是区块链的基本表现方式:
* 区块链平台具有一个交易数据库,该交易数据库允许对等方在任何时候彼此进行交易。
* 附有用户识别标签,以方便交易。
* 平台一定有一种安全的方式来在交易批准前对交易进行验证。
* 无法被验证的交易不会进行。
开源软件允许开发者在 [去中心化应用程序Dapp][3]中创建这些平台,这是区块链中交易的安全、保障和可变性的关键。
这种去中心化的方式意味着没有中央权威机构来调解交易,没有人能控制发生的事情。直接的点对点的交易可以更快速、安全的进行。由于交易被记录在分类账簿中,它们也会分发到整个生态系统中。
区块链使用密码学来保证安全。每一笔交易都携带着与前一笔交易相关联的信息,以验证其真实性。这可以防止威胁者篡改数据,因为一旦数据被添加到公共分类账中,其他用户就不能更改。
### 区块链是开源的吗?
虽然区块链本身在技术上可以是不开源的,但区块链系统通常是使用开源软件实现的,因为没有政府机构对其进行监管,所以这些开源软件使用的概念体现了一种开放文化。私人公司开发的用于处理金融交易的专有软件很可能受到 [政府机构][4] 的监管。在美国这可能包括美国证券交易委员会SEC、联邦储备委员会和联邦存款保险公司FDIC。区块链技术在开放环境下使用不需要政府监管实际上用来验证交易的是用户社区。
你可以称它为一种极端的众包形式,既用于开发构建区块链平台的开源软件,也用于验证交易。这就是区块链得到如此多关注的原因之一:它有可能颠覆整个行业,因为它可以作为处理和验证交易的权威中介。
### 比特币,以太坊和其他加密货币
截至 2020 年 6 月,超过 [5000 万人拥有区块链钱包][5] 。他们大多数用于金融交易,例如交易比特币、以太坊和其他加密货币。对许多人来说,像交易员观察股票价格一样,[查看加密货币价格][6] 已成为主流。
加密货币平台也使用开源软件。[以太坊项目][7] 开发出了任何人都可以免费使用的开源软件,社区中大量的开发者都为此贡献了代码。比特币客户端的参考实现版是由 450 多个开发人员和工程师进行开发的,他们已经贡献了超过 150,000 个贡献。
加密货币区块链是一个持续增长的记录。每个被称作为块的记录按顺序链接在一起,它们互相链接形成一条链。每个块都有其自己的唯一标记,这个标记称为 [哈希][8] 。一个块包含自身的哈希值和前一个块的加密计算出的哈希值。从本质上讲,每个块都链接到前一个块,形成了无法中断的长链,每个块都包含其它区块的信息,用于验证交易。
在金融或是加密货币的区块链中没有中央银行。这些分布在整个互联网中的区块,建立了一个性能强大的审计跟踪系统。任何人都能够通过区块链来验证交易,但却不能更改上面的记录。
### 牢不可破的区块链
尽管区块链不受任何政府或机构的监管,但分布式的网络保证了它们的安全。随着链的增长,每一笔交易都会增加伪造的难度。区块分布在世界各地的网络中,它们使用的信任标记不可被改变,这条链条几乎变得牢不可破。
这种去中心化的网络,其背后的代码是开源的,这也是用户在交易中不必使用诸如银行或经纪人之类的中介就可以相互信任的原因之一。支撑加密货币平台的软件是由相互独立的开发者组建的联盟创建的,并且任何人都可以免费使用。这创造了世界上最大的制衡体系之一。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/open-source-blockchain
作者:[Matt Shealy][a]
选题:[lujun9972][b]
译者:[xiao-song-123](https://github.com/xiao-song-123)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/mshealy
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/cube_innovation_process_block_container.png?itok=vkPYmSRQ "cubes coming together to create a larger cube"
[2]: https://www.linuxfoundation.org/wp-content/uploads/2020/08/2020_kernel_history_report_082720.pdf
[3]: https://www.freecodecamp.org/news/what-is-a-dapp-a-guide-to-ethereum-dapps/
[4]: https://www.investopedia.com/ask/answers/063015/what-are-some-major-regulatory-agencies-responsible-overseeing-financial-institutions-us.asp
[5]: https://www.statista.com/statistics/647374/worldwide-blockchain-wallet-users/
[6]: https://www.okex.com/markets
[7]: https://ethereum.org/en/
[8]: https://opensource.com/article/18/7/bitcoin-blockchain-and-open-source

View File

@ -0,0 +1,173 @@
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12779-1.html)
[#]: subject: (How to Free Up Space in /boot Partition on Ubuntu Linux?)
[#]: via: (https://itsfoss.com/free-boot-partition-ubuntu/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
如何在 Ubuntu Linux 上释放 /boot 分区的空间?
======
前几天,我收到一个警告,`/boot` 分区已经几乎满了,没有剩余空间了。是的,我有一个独立的 `/boot` 分区我相信现在很少有人这样做了。LCTT 译注:个人认为保留单独的 /boot 分区是个好的运维经验,除此以外,/tmp、/var 也单独划定分区比较好。)
这是我第一次看到这样一个错误,它让我很迷惑。现在,这里有一些 [方法来释放在 Ubuntu (或基于 Ubuntu 的分区)上的分区][1] ,但是在这种情况下并不是所有的方法都能用。
这就是为什么我决定写这些我释放 `/boot` 分区空间的步骤的原因。
### 如何在 Ubuntu 上释放 /boot 分区的空间
![][2]
我建议你仔细阅读这些解决方案,并由此得出最适合你情况的解决方案。解决方案的操作很容易,但是你需要在你的生产力系统上小心的执行这些解决方案。
#### 方法 1: 使用 apt autoremove
你不必是一名终端专家来做这件事,它只需要一个命令,你将移除未使用的内核来释放 `/boot` 分区中是空间。
你所有要做的事情是,输入:
```
sudo apt autoremove
```
这个命令不仅仅可以移除未使用的内核,而且也将移除你不需要的或工具安装后所不需要的依赖项。
在你输入命令后,它将列出将被移除的东西,你只需要确认操作即可。如果你很好奇它将移除什么,你可以仔细检查一下看看它实际移除了什么。
这里是它应该看起来的样子:
![][3]
你必须按 `Y` 按键来继续。
**值得注意的是,这种方法只在你还剩余一点点空间,并且得到警告的情况下才有效。但是,如果你的 `/boot` 分区已经满了APT 甚至可能不会工作。**
在接下来的方法中,我将重点介绍两种不同的方法,通过这些方法你可以使用 GUI 和终端来移除旧内核来释放空间。
#### 方法 2: 手动移除未使用的内核
在你尝试 [移除一些旧内核][4] 来释放空间前,你需要识别当前活动的内核,并且确保你不会删除它。
为 [检查你的内核的版本][5] ,在终端中输入下面的命令:
```
uname -r
```
[uname 命令通常用于获取 Linux 系统信息][6]。在这里,这个命令显示当前正在被使用的 Linux 内核。它看起来应该是这样:
![][7]
现在,你已经知道你当前的 Linux 内核是什么,你必须移除一个不同于这个版本的内核。你应该把它记录在某些地方,以便你不会不知不觉地移除它。
接下来,要移除它,你可以使用终端或 GUI。
> 警告!
>
> 在删除内核时一定要额外的小心。只识别和删除旧内核,而不是当前你正在使用的内核,否则你将会拥有一个残缺的系统。
##### 使用一个 GUI 工具来移除旧的 Linux 内核
你可以使用 [Synaptic 软件包管理器][8] 或一个类似 [Stacer][9] 的工具来开始。就我个人而言,当我遇到一个满满的 `/boot` 分区且 APT 损坏时,我使用 [Stacer][6] 来丢弃旧内核。因此,让我向你展示一下它看起的样子。
首先,你需要启动 Stacer ,然后导航到软件包卸载器,如下面屏幕截图所示。
![][10]
在这里,搜索 “image” ,你将找到你所拥有的 Linux 内核。你只需要删除旧内核版本的镜像,而不是当前内核的镜像。
在上面的屏幕截图中,我已经指出了我系统上的当前内核和旧内核,因此你必须注意你系统上的内核。
你没有必要删除任何其它东西,只需要删除旧的内核版本。
同样的,只需要在软件包列表中搜索 “headers” ,并删除如下显示的旧的 “headers” 版本。
![][11]
作为提醒,你 **不会希望移除 `linux-headers-generic`** 。只关注一下那些与其相关的有版本号的就行。
然后就这样你完成了所有的工作APT 将会再次工作,并且你将成功地释放来自 `/boot` 分区的一些空间。同样地,你也可以使用任意其它的软件包管理器来完成这些工作。
#### 使用命令行来移除旧内核
使用命令行来移除旧内核与使用 GUI 来移除旧内核是一样的。因此,如果你没有选择使用 GUI 软件(如果它是一台远程机器/一项远程服务)的权利,或者如果你只是对终端情有独钟,你可以仿效下面的步骤。
首先,使用下面的命令列出所有已安装的内核:
```
ls -l /boot
```
它应该看起来像这样:
![][12]
标记为 “old” 的内核,或者不匹配你当前内核版本,都是未使用的内核,你可以删除它们。
现在,你可以使用 `rm` 命令来移除具体指定来自 `/boot` 分区中的内核,使用下面的命令(一个命令对应一个内核):
```
sudo rm /boot/vmlinuz-5.4.0-7634-generic
```
务必检查系统的版本 — 这里可能与你的系统的版本不同。
如果你有很多未使用的内核,这将需要一些时间。因此,你也可以下面的命令丢弃多个内核:
```
sudo rm /boot/*-5.4.0-{7634}-*
```
为了清晰起见,你需要用逗号分隔内核版本号的最后一部分/编码,以便同时删除它们。
假设,我有两个旧的内核 5.4.0-7634-generic 和 5.4.0-7624 ,那么命令将是:
```
sudo rm /boot/*-5.4.0-{7634,7624}-*
```
如果你不希望在 grub 启动菜单中再看到这些旧的内核版本,你可以使用下面的命令简单地 [更新 grub][13]
```
sudo update-grub
```
就这样,你完成了所有的工作。你已经释放了空间,还修复了可能潜在的破损的 APT 问题,如果它是一个在你的 `/boot` 分区填满后出现的重要的问题的话。
在一些情况下,你需要输入这些命令来修复破损的(正如我在论坛中注意到的):
```
sudo dpkg --configure -a
sudo apt install -f
```
注意,除非你发现 APT 已破损,否则你不需要输入上面的命令。就我个人而言,我不需要这些命令,但是我发现这些命令对论坛上的一些人很有用。
--------------------------------------------------------------------------------
via: https://itsfoss.com/free-boot-partition-ubuntu/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean)
校对:[wxy](https://github.com/wxy)
本文由 [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/free-up-space-ubuntu-linux/
[2]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/free-boot-space-ubuntu-linux.jpg?resize=800%2C450&ssl=1
[3]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/apt-autoremove-screenshot.jpg?resize=800%2C415&ssl=1
[4]: https://itsfoss.com/remove-old-kernels-ubuntu/
[5]: https://itsfoss.com/find-which-kernel-version-is-running-in-ubuntu/
[6]: https://linuxhandbook.com/uname/
[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/uname-r-screenshot.jpg?resize=800%2C198&ssl=1
[8]: https://itsfoss.com/synaptic-package-manager/
[9]: https://itsfoss.com/optimize-ubuntu-stacer/
[10]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/09/stacer-remove-kernel.jpg?resize=800%2C562&ssl=1
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/09/stacer-remove-kernel-header.png?resize=800%2C576&ssl=1
[12]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/09/command-kernel-list.png?resize=800%2C432&ssl=1
[13]: https://itsfoss.com/update-grub/

View File

@ -0,0 +1,61 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12791-1.html)
[#]: subject: (Start using virtual tables in Apache Cassandra 4.0)
[#]: via: (https://opensource.com/article/20/10/virtual-tables-apache-cassandra)
[#]: author: (Ben Bromhead https://opensource.com/users/ben-bromhead)
如何在 Apache Cassandra 4.0 中使用虚拟表
======
> 虚拟表是什么以及如何使用。
![](https://img.linux.net.cn/data/attachment/album/202011/04/234511kpmv6dzac6fjmr65.jpg)
在最近的发布的 [Apache Cassandra 4.0 测试版][3]中的[众多新增功能][2]中,<ruby>虚拟表<rt>virtual table</rt></ruby>是一个值得关注的功能。
在以前的 Cassandra 版本中,用户需要访问 <ruby>Java 管理扩展<rt>Java Management Extensions</rt></ruby>[JMX][4] 来查看 Cassandra 的细节,如运行中的<ruby>压实<rt>compaction</rt></ruby>、客户端、度量和各种配置设置。虚拟表消除了这些挑战。Cassandra 4.0 测试版让用户能够从一个只读的系统表中以 <ruby>Cassandra 查询语言<rt>Cassandra Query Language</rt></ruby>CQL行的形式查询这些细节和数据。
以下是之前 Cassandra 版本中基于 JMX 的机制是如何工作的。想象一下,一个用户想要检查集群中某个节点的压实状态。用户首先要建立一个 JMX 连接,在节点上运行 `nodetool compactionstats`。这个要求马上就给用户带来了一些复杂的问题。用户的客户端是否配置了 JMX 访问Cassandra 节点和防火墙是否配置为允许 JMX 访问?是否准备好了适当的安全和审计措施,并落实到位?这些只是用户在处理 Cassandra 以前版本时必须面对的其中一些问题。
在 Cassandra 4.0 中,虚拟表使得用户可以利用之前配置的驱动来查询所需信息。这一变化消除了与实现和维护 JMX 访问相关的所有开销。
Cassandra 4.0 创建了两个新的<ruby>键空间<rt>keyspace</rt></ruby>来帮助用户利用虚拟表:`system_views` 和 `system_virtual_schema`。`system_views` 键空间包含了用户查询的所有有价值的信息,有用地存储在一些表中。`system_virtual_schema` 键空间,顾名思义,存储了这些虚拟表的所有必要的模式信息。
![system_views and system_virtual_schema keyspaces and tables][5]
重要的是要明白,每个虚拟表的范围仅限于其节点。任何虚拟表查询都将返回的数据,只对其协调器的节点有效,而不管一致性如何。为了简化这一要求,已经在几个驱动中添加了支持,以便在这些查询中指定协调器节点 Python、DataStax Java 和其他驱动现在提供了这种支持)。
为了说明这一点,请查看这个 `sstable_tasks` 虚拟表。这个虚拟表显示了对 [SSTables][7] 的所有操作,包括压实、清理、升级等。
![Querying the sstable_tasks virtual table][8]
如果用户在以前的 Cassandra 版本中运行 `nodetool compactionstats`,则会显示相同类型的信息。 在这里,这个查询发现该节点当前有一个活动的压缩。它还显示了它的进度以及它的键空间和表。得益于虚拟表,用户可以快速收集这些信息,并同样有效地获得正确诊断集群健康状况所需的能力。
需要说明的是Cassandra 4.0 并没有去除对 JMX 访问的需求。JMX 仍然是查询某些指标的唯一选择。尽管如此,用户会欢迎简单地使用 CQL 来获取关键集群指标的能力。由于虚拟表提供的便利,用户可能会将之前投入到 JMX 工具的时间和资源重新投入到 Cassandra 本身。客户端工具也应该开始利用虚拟表提供的优势。
如果你对 Cassandra 4.0 测试版及其虚拟表功能感兴趣,请[试试试它][3]。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/virtual-tables-apache-cassandra
作者:[Ben Bromhead][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/ben-bromhead
[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://www.instaclustr.com/apache-cassandra-4-0-beta-released/
[3]: https://cassandra.apache.org/download/
[4]: https://en.wikipedia.org/wiki/Java_Management_Extensions
[5]: https://opensource.com/sites/default/files/uploads/cassandra_virtual-tables.png (system_views and system_virtual_schema keyspaces and tables)
[6]: https://creativecommons.org/licenses/by-sa/4.0/
[7]: https://cassandra.apache.org/doc/latest/architecture/storage_engine.html#sstables
[8]: https://opensource.com/sites/default/files/uploads/cassandra_virtual-tables_sstable_tasks.png (Querying the sstable_tasks virtual table)

View File

@ -0,0 +1,123 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12787-1.html)
[#]: subject: (How to Clear Apt Cache and Reclaim Precious Disk Space)
[#]: via: (https://itsfoss.com/clear-apt-cache/)
[#]: author: (Abhishek Prakash https://itsfoss.com/author/abhishek/)
如何清除 APT 缓存来回收宝贵的磁盘空间
======
![][13]
如何清除 APT 缓存?你只需使用这个 [apt-get 命令][1]选项:
```
sudo apt-get clean
```
但是,清理 APT 缓存不仅仅是运行上面的命令。
在本教程中,我将解释什么是 APT 缓存、为什么会使用它、为什么你要清理它,以及关于清理 APT 缓存你应该知道的其他事情。
我将在这里使用 Ubuntu 作为参考,但由于这是关于 APT 的,因此它也适用于 [Debian][2] 和其他基于 Debian 和 Ubuntu 的发行版,比如 Linux Mint、Deepin 等等。
### 什么是 APT 缓存?为什么要使用它?
当你使用 `apt-get` 或 [apt 命令][3]安装一个软件包时(或在软件中心安装 DEB 包APT [包管理器][4]会以 .deb 格式下载软件包及其依赖关系,并将其保存在 `/var/cache/apt/archives` 文件夹中。
![][5]
下载时,`apt` 将 deb 包保存在 `/var/cache/apt/archives/partial` 目录下。当 deb 包完全下载完毕后,它会被移到 `/var/cache/apt/archives` 目录下。
下载完包的 deb 文件及其依赖关系后,你的系统就会[从这些 deb 文件中安装包][6]。
现在你明白缓存的用途了吧?系统在安装软件包之前,需要一个地方把软件包文件存放在某个地方。如果你了解 [Linux 目录结构][7],你就会明白,`/var/cache` 是合适的地方。
#### 为什么安装包后要保留缓存?
下载的 deb 文件在安装完成后并不会立即从目录中删除。如果你删除了一个软件包,然后重新安装,你的系统会在缓存中查找这个软件包,并从这里获取它,而不是重新下载(只要缓存中的软件包版本与远程仓库中的版本相同)。
这样就快多了。你可以自己尝试一下,看看一个程序第一次安装,删除后再安装需要多长时间。你可以[使用 time 命令来了解完成一个命令需要多长时间][8]`time sudo apt install package_name`。
我找不到任何关于缓存保留策略的内容,所以我无法说明 Ubuntu 会在缓存中保留下载的包多长时间。
#### 你应该清理 APT 缓存吗?
这取决于你。如果你的根目录下的磁盘空间用完了,你可以清理 APT 缓存来回收磁盘空间。这是 [Ubuntu 上释放磁盘空间的几种方法][9]之一。
使用 [du 命令][10]检查缓存占用了多少空间:
![][11]
有的时候,这可能会占用几百兆,如果你正在运行一个服务器,这些空间可能是至关重要的。
#### 如何清理 APT 缓存?
如果你想清除 APT 缓存,有一个专门的命令来做。所以不要去手动删除缓存目录。只要使用这个命令就可以了:
```
sudo apt-get clean
```
这将删除 `/var/cache/apt/archives` 目录的内容(除了锁文件)。以下是 `apt-get clean` 命令模拟删除内容:
![][12]
还有一个命令是关于清理 APT 缓存的:
```
sudo apt-get autoclean
```
`clean` 不同的是,`autoclean` 只删除那些无法从仓库中下载的包。
假设你安装了包 xyz。它的 deb 文件仍然保留在缓存中。如果现在仓库中有新的 xyz 包,那么缓存中现有的这个 xyz 包就已经过时了,没有用了。`autoclean` 选项会删除这种不能再下载的无用包。
#### 删除 apt 缓存安全吗?
是的,清除 APT 创建的缓存是完全安全的。它不会对系统的性能产生负面影响。也许如果你重新安装软件包,下载时间会更长一些,但也仅此而已。
再说一次,使用 `apt-get clean` 命令。它比手动删除缓存目录更快、更简单。
你也可以使用像 [Stacer][14] 或 [Bleachbit][15] 这样的图形工具来实现这个目的。
#### 总结
在写这篇文章的时候,新的 `apt` 命令没有这样的内置选项。不过,为了保持向后的兼容性,仍然可以运行 `apt clean` (内部应该是运行了 `apt-get clean`)。请参考这篇文章来[了解 apt 和 apt-get 的区别][16]。
我希望你觉得这个关于 APT 缓存的解释很有趣。虽然这不是什么必要的东西,但了解这些小东西会让你对你的 Linux 系统更加了解。
欢迎你在评论区提出反馈和建议。
--------------------------------------------------------------------------------
via: https://itsfoss.com/clear-apt-cache/
作者:[Abhishek Prakash][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/abhishek/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/apt-get-linux-guide/
[2]: https://www.debian.org/
[3]: https://itsfoss.com/apt-command-guide/
[4]: https://itsfoss.com/package-manager/
[5]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/apt-get-clean-cache.png?resize=800%2C470&ssl=1
[6]: https://itsfoss.com/install-deb-files-ubuntu/
[7]: https://linuxhandbook.com/linux-directory-structure/
[8]: https://linuxhandbook.com/time-command/
[9]: https://itsfoss.com/free-up-space-ubuntu-linux/
[10]: https://linuxhandbook.com/find-directory-size-du-command/
[11]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/apt-cache-archive-size.png?resize=800%2C233&ssl=1
[12]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/apt-get-clean-ubuntu.png?resize=800%2C339&ssl=1
[13]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/Clear-Apt-Cache.png?resize=800%2C450&ssl=1
[14]: https://itsfoss.com/optimize-ubuntu-stacer/
[15]: https://itsfoss.com/use-bleachbit-ubuntu/
[16]: https://itsfoss.com/apt-vs-apt-get-difference/

View File

@ -0,0 +1,81 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12775-1.html)
[#]: subject: (LibreOffice Wants Apache to Drop the Ailing OpenOffice and Support LibreOffice Instead)
[#]: via: (https://itsfoss.com/libreoffice-letter-openoffice/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
文档基金会希望 Apache 放弃陷入困境的 OpenOffice转而支持 LibreOffice
======
对于 Linux 用户来说,当我们想到[微软 Office 的开源替代品][1]时Apache OpenOffice 仍然是一个相关的推荐这是不言而喻的。然而在过去的几年里OpenOffice 的发展几乎是停滞的。
当然,考虑到 Abhishek 早在 2016 年就写过 [Apache OpenOffice 关闭的可能性][2],这并不令人震惊。
现在,在一封[文档基金会的公开信][3]中,他们呼吁 Apache OpenOffice 推荐用户开始使用更好的替代品,比如 LibreOffice。在本文中我将提到文档基金会的博文中的一些重点以及它对 Apache OpenOffice 的意义。
![][4]
### Apache OpenOffice 是历史LibreOffice 是未来?
尽管我当年没有使用过 OpenOffice但可以肯定地说它绝对不是微软 Office 的现代开源替代品。至少现在不是了。
是的Apache OpenOffice 对于传统用户来说仍然是很重要的东西,在几年前是一个很好的替代品。
以下是 OpenOffice 和 LibreOffice 的主要发布时间线:
![][5]
现在 OpenOffice 已经没有重大的开发了Apache OpenOffice 的未来是什么?一个相当活跃的项目,这个最大的开源基金会会不发布重大版本?
这听起来并不乐观,而这正是文档基金会在他们的公开信中所强调的:
> OpenOffice.org是 LibreOffice 的”父项目“,它是一个伟大的办公套件,它改变了世界。它有着引人入胜的历史,但**自从 2014 年以来Apache OpenOffice (它现在的家)还没有一个重大的版本**。没错,六年多来,没有重大的新功能或重大更新到来,也很少发布次要版本,而且在及时的安全更新方面也存在问题。
对于一个普通用户来说,如果他们不知道 [LibreOffice][6]我肯定希望他们知道。但是Apache 基金会是否应该建议 OpenOffice 用户尝试使用 LibreOffice 来体验更好或更高级的办公套件呢?
我不知道,也许是,或者不是?
> ...很多用户不知道 LibreOffice 的存在。OpenOffice 的品牌仍然如此强大,尽管该软件已经有六年多没有重大的版本发布,而且几乎没有人开发或支持它。
正如在公开信中提到的,文档基金会强调了 LibreOffice 相对于 OpenOffice的 优势/改进,并呼吁 Apache OpenOffice 开始推荐他们的用户尝试更好的东西(即 LibreOffice
> 我们呼吁 Apache OpenOffice 做正确的事情。我们的目标应该是**把强大的、最新的、维护良好的生产力工具送到尽可能多的人手中**。让我们一起努力吧!
### Apache OpenOffice 应该做什么?
如果 OpenOffice 能完成工作,用户可能不需要努力寻找替代品。那么,因为他们的缓慢开发而呼唤另一个项目,建议用户采用未来工具并推荐它是一个好主意么?
在争论中,有人可能会说,如果你已经完成了你的目标,并且对改进 OpenOffice 没有兴趣,那么推广你的竞争对手才是公平的。而且,这并没有错,开源社区应该一直合作,以确保新用户得到最好的选择。
从另一个侧面来看,我们可以说,文档基金会对于 OpenOffice 到了 2020 年即使没有任何重大改进却仍然有重要意义感到沮丧。
我不会去评判,但当我看了这封公开信时,这些矛盾的想法就浮现在我的脑海里。
### 你认为是时候把 OpenOffice 搁置起来,依靠 LibreOffice 了吗?
即使 LibreOffice 似乎是一个更优越的选择并且绝对值得关注你认为应该怎么做Apache 是否应该停止 OpenOffice并将用户重定向到 LibreOffice
欢迎你的意见。
--------------------------------------------------------------------------------
via: https://itsfoss.com/libreoffice-letter-openoffice/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [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/best-free-open-source-alternatives-microsoft-office/
[2]: https://itsfoss.com/openoffice-shutdown/
[3]: https://blog.documentfoundation.org/blog/2020/10/12/open-letter-to-apache-openoffice/
[4]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/libre-office-open-office.png?resize=800%2C450&ssl=1
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/libre-office-open-office-derivatives.jpg?resize=1536%2C319&ssl=1
[6]: https://itsfoss.com/libreoffice-tips/

View File

@ -0,0 +1,101 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12804-1.html)
[#]: subject: (5 open source tools I can't live without)
[#]: via: (https://opensource.com/article/20/10/open-source-tools)
[#]: author: (Victoria Martinez de la Cruz https://opensource.com/users/vkmc)
5 个我不可或缺的开源工具
======
> 通过将这些工具放在自己的技能包中,提高你在终端内、外的工作效率。
![](https://img.linux.net.cn/data/attachment/album/202011/08/185810ffjljj7o830fboz3.jpg)
前段时间,我参与了一个在科技人士中广为流传的 Twitter 话题。“挑战?只挑选五个你不能没有的工具。”我开始结合我的日常生活来思考这个问题,只挑出五个工具并不容易。我使用了许多我认为必不可少的工具,比如用来与同事和朋友联系的 [IRC][2] 客户端(是的,我仍然使用 IRC一个用来做各种事情的出色的文本编辑器一个用来保持有条不紊的日历应用以及当需要更直接的互动时的一个视频会议平台。
所以,让我给这个挑战来个变化:选出五个能提高你工作效率的开源工具。这是我的清单。请在评论中分享你的清单。
### tmate
![tmate screenshot][3]
哦,我喜欢这个工具。`tmate` 是著名的 [tmux][5] 终端多路复用器的一个复刻,它允许你启动一个 `tmux` 会话并通过 SSH 共享。你可以用它来进行[结对编程][6](这是我的主要使用场景),也可以用来进行远程控制。
如果你经常与你的团队成员合作,并且你想要一个简单的、与发行版无关的、开源的方式与他们一起编程(而且共享终端访问对你来说已经足够了),这绝对是你必须加到列表中的东西。
在 [tmate 的网站][7]上获取更多信息,或者在 [GitHub][8] 上查看代码。
### ix
`ix` 是一个命令行粘贴板。你不需要安装任何东西。你可以通过 `curl` 到 [ix.io][9] 站点来创建新的粘贴。例如,`echo Hello world. | curl -F 'f:1=<-' ix.io` 会给你一个到 ix.io 的链接那里粘贴了消息 Hello world 的信息当你想分享日志用于调试或在没有桌面环境的服务器上保存配置文件时这非常方便
有一个缺点是源码还没有公布,尽管它的目的是自由开源。如果你是作者,并且正在阅读这篇文章,请发布代码,这样我们就可以为打磨它的过程做出贡献。
### asciinema
是的,这是另一个终端工具,`asciinema` 可以让你记录你的终端。使用它的方法有很多,但我一般用它来制作演示。它非常容易使用,而且有很多 Linux 发行版和其他平台的软件包。
要想知道它是如何工作的,可以看看这个[酷炫的演示][10]。是不是很棒?
在 [asciinema 的网站][11]上获取更多信息,在 [GitHub][12] 上访问其源代码。
### GNOME Pomodoro
![pomodoro timer gnome][13]
好了,关于终端工具的介绍就到此为止。现在我想和大家分享一下这个简单的宝物,它让你的工作变得有条不紊。你听说过 [番茄工作法][14] 吗Pomodoro 基本上是一个时间管理工具。它使用一个番茄形状的计时器帮助你将时间分成工作时间和休息时间默认情况下25 分钟的工作后有 5 分钟的休息时间)。而且,每隔 4 个“番茄”之后,你就会有更长的休息时间(默认为 15 分钟)。这样做的目的是让你在工作时间内保持专注,而在休息时间内进行伸展和放松。
这听起来非常非常简单,你可能会对让一个番茄形状的时钟来控制你的生活感到犹豫,但它确实帮助我变得跟有条理,并且在试图同时专注于许多事情时避免感到疲惫。
无论你是什么角色,我都强烈推荐这种做法。而在众多实现它的不同工具中,我推荐 GNOME Pomodoro 应用。它适用于主要的 GNU/Linux 发行版,所以它需要你使用 GNOME 桌面环境(这可能是它的缺点)。
在 [GNOME Pomodoro 的网站][15]上查看更多信息,并访问其 [GitHub][16] 仓库来获取源码并了解如何做出贡献。
### Jitsi
最后但同样重要的是 Jitsi。当你在一个远程、遍布全球的团队中工作时你需要一种与人们联系的方式。即时通讯是好的但有时最好还是开个快速会议面对面地讨论事情看到对方的脸。有很多[视频会议工具][17]可用,但我很喜欢 Jitsi。不仅因为它是免费和开源的还因为它提供了一个简洁、实用的界面。你可以设置自己的 Jitsi 服务器(用于商业目的),但你也可以通过访问 [Jitsi Meet][18] 网站来试用一个公共的 Jitsi 实例。
设置这种会议的一个好做法是:只有在你心中有明确的议程时才使用它。而且要时刻问自己,这个会议能不能用电子邮件代替?遵循这些准则,谨慎使用 Jitsi你的工作日将会非常高效!
在 [Jitsi 网站][19]上了解更多信息,并通过访问其 [GitHub][20] 仓库开始贡献。
* * *
我希望我的清单能帮助你在生产力上达到一个新的水平。你的 5 个不能离开的开源生产力工具是什么?在评论中告诉我。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/open-source-tools
作者:[Victoria Martinez de la Cruz][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/vkmc
[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.wikipedia.org/wiki/Internet_Relay_Chat
[3]: https://opensource.com/sites/default/files/pictures/tmate-opensource.jpg (tmate screenshot)
[4]: https://creativecommons.org/licenses/by-sa/4.0/
[5]: https://opensource.com/article/20/7/tmux-cheat-sheet
[6]: https://en.wikipedia.org/wiki/Pair_programming
[7]: https://tmate.io/
[8]: https://github.com/tmate-io/tmate
[9]: http://ix.io/
[10]: https://asciinema.org/a/239367
[11]: https://asciinema.org/
[12]: https://github.com/asciinema/asciinema
[13]: https://opensource.com/sites/default/files/pictures/pomodoro_timer_gnome.jpg (pomodoro timer gnome)
[14]: https://en.wikipedia.org/wiki/Pomodoro_Technique
[15]: https://gnomepomodoro.org/
[16]: https://github.com/codito/gnome-pomodoro
[17]: https://opensource.com/article/20/5/open-source-video-conferencing
[18]: https://meet.jit.si/
[19]: https://jitsi.org/
[20]: https://github.com/jitsi

View File

@ -0,0 +1,184 @@
[#]: collector: "lujun9972"
[#]: translator: "xiao-song-123"
[#]: reviewer: "wxy"
[#]: publisher: "wxy"
[#]: url: "https://linux.cn/article-12842-1.html"
[#]: subject: "5 steps to learn any programming language"
[#]: via: "https://opensource.com/article/20/10/learn-any-programming-language"
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
五步学会任何编程语言
======
> 只需一点编程经验,你就可以在短短几天内(有时更少)学会一种新编程语言。
![](https://img.linux.net.cn/data/attachment/album/202011/19/225851j7miw3kd17joowa7.jpg)
有些人喜欢学习新的编程语言,也有一些人觉得学习一种都是可望不可及的事情。在本文中,我将向你展示如何像程序员一样思考,这样你就可以自信地学习任何一门你想要学习的编程语言。
事实上,一旦你学会了如何编程,你使用的编程语言就不再是一个障碍,而更像是一种形式。实际上,这就是教育家们倡导 [让孩子尽早学习编程][2] 的众多原因之一。不管他们的入门语言有多简单,这种编程的逻辑和儿童们(或成人学习者)以后可能遇到的其他语言的逻辑有着想通之处。
只需有一点编程经验(你可以从我们这里的几篇介绍性文章中获得),你就可以在短短几天内(有时更短)学习任何编程语言。这并不是魔法,你也确实要为此付出一些努力。诚然,学习一种编程语言每个的可用库,或者学习打包代码以及进行交付的细微差别,需要的时间远远不止几天。但是,就入门来说,比你想像中的要容易许多,剩下的则要通过不断练习来完成。
当有经验的程序员静下心来学习一门新的编程语言时,他们会寻找五样东西。只要你知道了这五件事,你就可以开始编码了。
### 1、语法
![Syntax][3]
语言的语法描述了代码的结构。这包括如何逐行编写代码,以及用于构造代码语句的实际单词。
例如,[Python][5] 以使用缩进来指示一个代码块在哪里结束以及另一代码块在哪里开始而闻名:
```
while j < rows:
while k < columns:
tile = Tile(k * w)
board.add(tile)
k += 1
j += 1
k = 0
```
[Lua][6] 只是使用关键字 `end`
```
for i,obj in ipairs(hit) do
if obj.moving == 1 then
obj.x,obj.y = v.mouse.getPosition()
end
end
```
[Java][7]、[C][8]、C++ 之类的编程语言使用花括号:
```
while (std::getline(e,r)) {
wc++;
}
```
编程语言的语法还包括包括库、设置变量和终止行等内容。通过练习,你将学会在阅读示例代码时下意识地识别语法需求(和惯例)。
#### 实践
当学习一门新的编程语言时,要努力理解它的语法。你不需要去记住它,只需要知道如果忘记了以后去哪里查找。使用好的 [IDE][9] 也很有帮助,因为很多 IDE 在出现语法错误时会提醒你。
### 2、内置函数和条件
![built-in words][10]
就像自然语言一样,编程语言可以识别的合法单词是有限的。这个词汇表可以使用其他库进行扩展,但是核心语言知道一组特定的关键字。大多数语言并没有你想的那么多关键字。即使在像 C 语言这样非常低级的语言中,也只有 32 个关键字,比如 `for`、`do`、`while`、`int`、`float`、`char`、`break` 等等。
了解了这些关键字,你就可以编写基本的表达式,也就是构建程序的代码块。许多内置的关键字能帮助你构建条件语句,这些条件语句影响整个程序的流程。例如,如果你想编写一个允许单击和拖动图标的程序,那么你的代码就必须检测用户的鼠标指针何时位于图标上。只有当鼠标光标位于图标外部边缘相同的坐标时,才执行导致使鼠标抓取图标的代码。这是一个经典的 `if` / `then` 语句,但不同的语言可以用不同的方式表达。
Python 使用 `if`、`elif `和 `else` 的组合来实现条件语句,但是并不显式的关闭语句:
```
if var == 1:
    # action
elif var == 2:
    # some action
else:
    # some other action
```
[Bash][11] 使用 `if`、`elif`、`else`,并且使用 `fi` 来结束语句:
```
if [ "$var" = "foo" ]; then
   # action
elif [ "$var" = "bar" ]; then
   # some action
else
   # some other action
fi
```
然而 C 和 Java, 使用 `if`、`else` 和 `else if`,用花括号把它们括起来:
```
if (boolean) {
   // action
} else if (boolean) {
   // some action
} else {
   // some other action
}
```
各种编程语言虽然在关键字的选择和语法上有细微的变化,但基本是相同的。学习如何在编程语言中定义条件语句,包括 `if` / `then`、`do...while` 和 `case` 语句。
#### 实践
要熟悉编程语言能够理解的关键字集。在实践中,你的代码将不仅仅包含编程语言的关键字,可以肯定的是,有包含很多简单函数的库来帮助你做一些事情,诸如将输出打印到屏幕或显示窗口之类。然而,驱动这些库的逻辑始于编程语言的内置关键字。
### 3、数据类型
![Data types][12]
代码是用来处理数据的,因此你必须学习编程语言如何识别不同类型的数据。所有编程语言都能理解整数,大多数的语言能理解小数和单个字符(`a`、`b`、`c` 等等)。它们通常被表示为 `int``float`、`double` 和 `char`,当然,语言的内置词汇表会告诉你如何引用这些实体。
有时候在编程语言中内置了一些额外的数据类型也有时是通过引用库来启用复杂的数据类型。例如Python 可以识别关键字为 `str` 的字符串,但是 C 语言的代码中必须包含 `string.h` 头文件才能实现字符串特性。
#### 实践
库可以为你的代码解锁各种类型的数据,但是学习编程语言中包含的基本数据类型是一个明智的起点。
### 4、运算符和解析器
![Operators][13]
一旦你理解了编程语言可处理的数据类型,就可以学习如何分析这些数据了。幸运的是,数学这门学科是相当稳定的,所以算数运算符在许多语言中通常是相同的(或至少非常相似)。例如,两个整数相加通常用 `+` 符号完成,而测试一个整数是否大于另一个整数通常用 `>` 符号完成。测试是否相等通常使用 `==` 来完成(是的,是两个等号,因为通常一个等号用来赋值)。
当然也有一些例外,比如像 Lisp 和 Bash 语言算数运算符就不是如此,但与其他语言一样,这只是一个心理翻译的问题。一旦你了解了表达方式有何不同,很快就可以适应它。快速浏览一下一门编程语言的算数运算符通常足以让你了解算数操作是如何完成的。
你还需要知道如何比较和操作非数值数据比如字符和字符串。这些通常是通过编程语言的核心库来进行的的。例如Python 提供了 `split()` 方法,而 C 语言需要引入头文件 `string.h` 来提供 `strtok()` 函数。
#### 实践
了解用于处理基本数据类型的基本函数和关键字,并寻找可帮助你完成复杂操作的核心库。
### 5、函数
![Class][14]
代码不只是计算机的待办清单。通常情况下,在编写代码时你往往希望向计算机提供一组理论条件和一组操作指令,当满足每个条件时计算机就会采取这些操作。尽管使用条件语句以及数学和逻辑运算符进行流控制可以做很多事情,但是引入了函数和类之后,代码会变得更加高效,因为它们使你可以定义子程序。例如,如果应用程序非常频繁地需要一个确认对话框,那么将其作为类的实例编写一次要比每次需要它时重新编写实现起来要容易得多。
你需要学习如何在编程语言中定义类和函数。更准确地说,你首先需要了解编程语言中是否支持类和函数。大多数现代语言都支持函数,但是类是面向对象的编程语言中所特有的。
#### 实践
学习语言中可用的结构,这些结构可以帮助你高效地编写和使用代码。
### 你可以学到任何东西
学习编程语言,就其本身而言,是一种编码过程中的子程序。一旦理解了代码如何工作,你所使用的语言就只是一种传递逻辑的媒介。学习一门新编程语言的过程几乎都是一样的:通过简单的练习来学习语法,通过学习词汇来积累进行复杂动作的能力,然后练习、练习、再练习。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/learn-any-programming-language
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[xiao-song-123](https://github.com/xiao-song-123)
校对:[wxy](https://github.com/wxy)
本文由 [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/learn-programming-code-keyboard.png?itok=xaLyptT4 "Learning to program"
[2]: https://opensource.com/article/20/9/scratch
[3]: https://opensource.com/sites/default/files/uploads/syntax_0.png "Syntax"
[4]: https://creativecommons.org/licenses/by-sa/4.0/
[5]: https://opensource.com/downloads/cheat-sheet-python-37-beginners
[6]: https://opensource.com/article/20/2/lua-cheat-sheet
[7]: https://opensource.com/downloads/java-cheat-sheet
[8]: https://opensource.com/downloads/c-programming-cheat-sheet
[9]: https://opensource.com/resources/what-ide
[10]: https://opensource.com/sites/default/files/uploads/builtin.png "built-in words"
[11]: https://opensource.com/downloads/bash-cheat-sheet
[12]: https://opensource.com/sites/default/files/uploads/type.png "Data types"
[13]: https://opensource.com/sites/default/files/uploads/operator.png "Operators"
[14]: https://opensource.com/sites/default/files/uploads/class.png "Class"

View File

@ -0,0 +1,167 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12860-1.html)
[#]: subject: (Secure NTP with NTS)
[#]: via: (https://fedoramagazine.org/secure-ntp-with-nts/)
[#]: author: (Miroslav Lichvar https://fedoramagazine.org/author/mlichvar/)
用 NTS 保证 NTP 的安全
======
![](https://img.linux.net.cn/data/attachment/album/202011/26/111649pt32v9j22x3ooa33.jpg)
许多计算机使用<ruby>网络时间协议<rt>Network Time Protocol</rt></ruby>NTP通过互联网来同步系统时钟。NTP 是少数几个仍在普遍使用的不安全的互联网协议之一。攻击者如果能够观察到客户端和服务器之间的网络流量就可以向客户端提供虚假的数据并根据客户端的实现和配置强迫其将系统时钟设置为任何时间和日期。如果客户端的系统时钟不准确一些程序和服务就可能无法工作。例如如果根据客户端的系统时钟Web 服务器的证书似乎已经过期Web 浏览器将无法正常工作。可以使用<ruby>网络时间安全<rt>Network Time Security</rt></ruby>NTS来保证 NTP 的安全。
Fedora 33 [^1] 是第一个支持 NTS 的 Fedora 版本。NTS 是一种新的 NTP 验证机制。它使客户端能够验证它们从服务器接收的数据包在传输过程中有没有被修改。当 NTS 启用时,攻击者唯一能做的就是丢弃或延迟数据包。关于 NTS 的更多细节,请参见 [RFC8915][3]。
使用对称密钥可以很好地保证 NTP 的安全。遗憾的是,服务器必须为每个客户端配备不同的密钥,而且密钥必须安全地分发才行。这对于本地网络上的私有服务器来说可能是实用的,但它不能扩展到有着数百万客户端的公共服务器上。
NTS 包括一个<ruby>密钥建立<rt>Key Establishment</rt></ruby>NTS-KE协议它可以自动创建服务器与其客户端之间使用的加密密钥。它在 TCP 端口 4460 上使用<ruby>传输层安全<rt>Transport Layer Security</rt></ruby>TLS。它被设计成可以扩展到非常多的客户端而对准确性的影响最小。服务器不需要保存任何客户端特定的状态。它为客户提供 cookiecookie 是加密的,包含验证 NTP 数据包所需的密钥。隐私是 NTS 的目标之一。客户端在每次服务器响应时都会得到一个新的 cookie所以它不必重复使用 cookie。这可以防止被动观察者跟踪在网络之间迁移的客户端。
Fedora 中默认的 NTP 客户端是 Chrony。Chrony 在 4.0 版本中增加了 NTS 支持但并没有改变默认配置。Chrony 仍然使用 [pool.ntp.org][4] 项目中的公共服务器,而且默认情况下 NTS 没有启用。
目前,支持 NTS 的公共 NTP 服务器非常少。两个主要的提供商是 Cloudflare 和 Netnod。[Cloudflare 服务器][5]分布在世界各地的不同地方。他们使用的是<ruby>任播<rt>anycast</rt></ruby>地址,应该可以让大多数客户到达一个接近的服务器。[Netnod 服务器][6]位于瑞典。在未来,我们可能会看到更多支持 NTS 的公共 NTP 服务器。
为了获得最佳的可靠性,配置 NTP 客户端的一般建议是至少有三个工作的服务器。为了达到最好的精度,建议选择距离较近的服务器,以减少网络延迟和非对称网络路由造成的不对称性。如果你不关心细粒度的精度,你可以忽略这个建议,使用任何你信任的 NTS 服务器,无论它们位于哪里。
如果你确实想要高准确度,但又没有近距离的 NTS 服务器,你可以将远处的 NTS 服务器和近处的非 NTS 服务器混合使用。但是,这样的配置不如只使用 NTS 服务器的配置安全。攻击者仍然不能强迫客户机接受任意时间,但他们确实对客户机的时钟及其估计精度有更大的控制权,这在某些环境下可能是不可接受的。
### 在安装程序中启用客户端 NTS
安装 Fedora 33 时你可以在“Time & Date”对话框的“Network Time”配置中启用 NTS。在点击“+”(添加)按钮之前,请输入服务器的名称并检查 NTS 支持情况。你可以添加一个或多个具有 NTS 的服务器或池。要删除默认的服务器池(`2.fedora.pool.ntp.org`请取消选中“Use”列中的相应标记。
![Fedora 安装程序中的网络时间配置][7]
### 在配置文件中启用客户端 NTS
如果你从之前的 Fedora 版本升级,或者你没有在安装程序中启用 NTS你可以直接在 `/etc/chrony.conf` 中启用 NTS。除了推荐的 `iburst` 选项外,还可以对指定服务器使用 `nts` 选项。例如:
```
server time.cloudflare.com iburst nts
server nts.sth1.ntp.se iburst nts
server nts.sth2.ntp.se iburst nts
```
你还应该允许客户端将 NTS 密钥和 cookie 保存到磁盘上,这样它就不必在每次启动时重复 NTS-KE 会话。在 `chrony.conf` 中添加以下一行,如果还没有的话:
```
ntsdumpdir /var/lib/chrony
```
如果不想让 DHCP 提供的 NTP 服务器与你指定的服务器混在一起,请在 `chrony.conf` 中删除或注释以下一行:
```
sourcedir /run/chrony-dhcp
```
当你完成编辑 `chrony.conf` 后,保存你的更改并重新启动 `chronyd` 服务:
```
systemctl restart chronyd
```
### 检查客户端状态
在 root 用户下运行以下命令,检查 NTS 密钥建立是否成功:
```
# chronyc -N authdata
Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen
=========================================================================
time.cloudflare.com NTS 1 15 256 33m 0 0 8 100
nts.sth1.ntp.se NTS 1 15 256 33m 0 0 8 100
nts.sth2.ntp.se NTS 1 15 256 33m 0 0 8 100
```
`KeyID`、`Type` 和 `KLen` 列应该有非零值。如果它们为零,请检查系统日志中是否有来自 `chronyd` 的错误信息。一个可能的故障原因是防火墙阻止了客户端与服务器的 TCP 端口(端口 4460的连接。
另一个可能的故障原因是由于客户机的时钟错误而导致证书无法验证。这是 NTS 的先有鸡还是先有蛋的问题。你可能需要手动修正日期或暂时禁用 NTS以使 NTS 正常工作。如果你的电脑有实时时钟,几乎所有的电脑都有,而且有好的电池做备份,这种操作应该只需要一次。
如果计算机没有实时时钟或电池,就像一些常见的小型 ARM 计算机(如树莓派)那样,你可以在 `/etc/sysconfig/chronyd` 中添加 `-s` 选项来恢复上次关机或重启时保存的时间。时钟会落后于真实时间,但如果电脑没有关机太久,服务器的证书也没有在离到期时间太近的时候更新,应该足以让时间检查成功。作为最后的手段,你可以用 `nocerttimecheck` 指令禁用时间检查。详情请参见`chrony.conf(5)` 手册页。
运行下面的命令来确认客户端是否在进行 NTP 测量:
```
# chronyc -N sources
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* time.cloudflare.com 3 6 377 45 +355us[ +375us] +/- 11ms
^+ nts.sth1.ntp.se 1 6 377 44 +237us[ +237us] +/- 23ms
^+ nts.sth2.ntp.se 1 6 377 44 -170us[ -170us] +/- 22ms
```
`Reach` 列应该有一个非零值,最好是 377。上图所示的值 377 是一个八进制数,它表示最后八个请求都有有效的响应。如果启用了 NTS 的话,验证检查将包括 NTS 认证。如果该值一直很少或从未达到 377则表明 NTP 请求或响应在网络中丢失了。众所周知,一些主要的网络运营商有中间设备,它可以阻止或限制大的 NTP 数据包的速率,以缓解利用 `ntpd` 的监控协议进行的放大攻击。不幸的是,这影响了受 NTS 保护的 NTP 数据包尽管它们不会引起任何放大。NTP 工作组正在考虑为 NTP 提供一个替代端口,作为解决这个问题的办法。
### 在服务器上启用 NTS
如果你有自己的 NTP 服务器,运行着 `chronyd`,你可以启用服务器的 NTS 支持,让它的客户端安全同步。如果该服务器是其他服务器的客户端,它应该使用 NTS 或对称密钥与之同步。客户端假设同步链在所有服务器到主时间服务器之间是安全的。
启用服务器 NTS 类似于在 Web 服务器上启用 HTTPS。你只需要一个私钥和证书。例如证书可以由 Let's Encrypt 权威机构使用 `certbot` 工具签署。当你有了密钥和证书文件(包括中间证书),在 `chrony.conf` 中用以下指令指定它们:
```
ntsserverkey /etc/pki/tls/private/foo.example.net.key
ntsservercert /etc/pki/tls/certs/foo.example.net.crt
```
确保之前在客户端配置中提到的 `ntsdumpdir` 指令存在于 `chrony.conf` 中。它允许服务器将其密钥保存到磁盘上,这样服务器的客户端在重启服务器时就不必获取新的密钥和 cookie 了。
重新启动 `chronyd` 服务:
```
systemctl restart chronyd
```
如果系统日志中没有来自 `chronyd` 的错误信息,那么它应该是可以接受客户端连接的,如果服务器有防火墙,则需要同时允许 UDP 123 和 TCP 4460 端口的 NTP 和 NTS-KE 服务。
你可以用下面的命令在客户端机器上进行快速测试:
```
$ chronyd -Q -t 3 'server foo.example.net iburst nts maxsamples 1'
2020-10-13T12:00:52Z chronyd version 4.0 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 +DEBUG)
2020-10-13T12:00:52Z Disabled control of system clock
2020-10-13T12:00:55Z System clock wrong by -0.001032 seconds (ignored)
2020-10-13T12:00:55Z chronyd exiting
```
如果你看到一个“System clock wrong”消息说明它是正确工作的。
在服务器上,你可以使用下面的命令来检查它已经处理了多少个 NTS-KE 连接和认证的 NTP 数据包:
```
# chronyc serverstats
NTP packets received : 2143106240
NTP packets dropped : 117180834
Command packets received : 16819527
Command packets dropped : 0
Client log records dropped : 574257223
NTS-KE connections accepted: 104
NTS-KE connections dropped : 0
Authenticated NTP packets : 52139
```
如果你看到非零的 “NTS-KE connections accepted” 和 “Authenticated NTP packets”这意味着至少有一些客户端能够连接到 NTS-KE 端口,并发送一个认证的 NTP 请求。
[^1]: Fedora 33 Beta 安装程序包含一个较旧的 Chrony 预发布版本,它不能与当前的 NTS 服务器一起工作,因为 NTS-KE 端口已经改变。因此,在安装程序中的网络时间配置中,服务器总是显示为不工作。安装后,需要更新 chrony 包,才能与当前的服务器配合使用。
--------------------------------------------------------------------------------
via: https://fedoramagazine.org/secure-ntp-with-nts/
作者:[Miroslav Lichvar][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://fedoramagazine.org/author/mlichvar/
[b]: https://github.com/lujun9972
[1]: https://fedoramagazine.org/wp-content/uploads/2020/10/secure-ntp-with-nts-816x345.jpg
[2]: tmp.rl0XC1HIGm#footnote1
[3]: https://tools.ietf.org/html/rfc8915
[4]: https://www.pool.ntp.org
[5]: https://developers.cloudflare.com/time-services/nts/usage
[6]: https://www.netnod.se/time-and-frequency/how-to-use-nts
[7]: https://fedoramagazine.org/wp-content/uploads/2020/10/anaconda-nts.png

View File

@ -0,0 +1,117 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12798-1.html)
[#]: subject: (ninja: a simple way to do builds)
[#]: via: (https://jvns.ca/blog/2020/10/26/ninja--a-simple-way-to-do-builds/)
[#]: author: (Julia Evans https://jvns.ca/)
ninja一个简单的构建方式
======
大家好!每隔一段时间,我就会发现一款我非常喜欢的新软件,今天我想说说我最近喜欢的一款软件:[ninja][1]
### 增量构建很有用
我做了很多小项目,在这些项目中,我想设置增量构建。例如,现在我正在写一本关于 bash 的杂志,杂志的每一页都有一个 `.svg`文件。我需要将 SVG 转换为 PDF我的做法是这样的
```
for i in *.svg
do
svg2pdf $i $i.pdf # or ${i/.svg/.pdf} if you want to get really fancy
done
```
这很好用,但是我的 `svg2pdf` 脚本有点慢(它使用 Inkscape而且当我刚刚只更新了一页的时候必须等待 90 秒或者其他什么时间来重建所有的 PDF 文件,这很烦人。
### 构建系统是让人困惑的
在过去,我对使用 `make``bazel` 这样的构建系统来做我的小项目一直很反感,因为 `bazel` 是个大而复杂的东西,而 `make` 对我来说感觉有点神秘。我真的不想使用它们中的任何一个。
所以很长时间以来,我只是写了一个 bash 脚本或者其他的东西来进行构建,然后就认命了,有时候只能等一分钟。
### ninja 是一个极其简单的构建系统
`ninja` 并不复杂!以下是我所知道的关于 ninja 构建文件的语法:创建一个 `rule` 和一个 `build`
`rule` 有一个命令(`command`)和描述(`description`)参数(描述只是给人看的,所以你可以知道它在构建你的代码时在做什么)。
```
rule svg2pdf
command = inkscape $in --export-text-to-path --export-pdf=$out
description = svg2pdf $in $out
```
`build` 的语法是 `build output_file: rule_name input_files`。下面是一个使用 `svg2pdf` 规则的例子。输出在规则中的 `$out` 里,输入在 `$in` 里。
```
build pdfs/variables.pdf: svg2pdf variables.svg
```
这就完成了!如果你把这两个东西放在一个叫 `build.ninja` 的文件里,然后运行 `ninja`ninja 会运行 `inkscape variables.svg --export-text-to-path --export-pdf=pdfs/variables.pdf`。然后如果你再次运行它,它不会运行任何东西(因为它可以告诉你已经构建了 `pdfs/variables.pdf`,而且是最新的)。
Ninja 还有一些更多的功能(见[手册][2]),但我还没有用过。它最初是[为 Chromium][3] 构建的,所以即使只有一个小的功能集,它也能支持大型构建。
### ninja 文件通常是自动生成的
ninja 的神奇之处在于,你不必使用一些混乱的构建语言,它们很难记住,因为你不经常使用它(比如 `make`相反ninja 语言超级简单,如果你想做一些复杂的事情,那么你只需使用任意编程语言生成你想要的构建文件。
我喜欢写一个 `build.py` 文件,或者像这样的文件,创建 ninja 的构建文件,然后运行 `ninja`
```
with open('build.ninja', 'w') as ninja_file:
# write some rules
ninja_file.write("""
rule svg2pdf
command = inkscape $in --export-text-to-path --export-pdf=$out
description = svg2pdf $in $out
""")
# some for loop with every file I need to build
for filename in things_to_convert:
ninja_file.write(f"""
build {filename.replace('svg', 'pdf')}: svg2pdf {filename}
""")
# run ninja
import subprocess
subprocess.check_call(['ninja'])
```
我相信有一堆 `ninja` 的最佳实践,但我不知道。对于我的小项目而言,我发现它很好用。
### meson 是一个生成 ninja 文件的构建系统
我对 [Meson][4] 还不太了解,但最近我在构建一个 C 程序 [plocate][5],一个比 `locate` 更快的替代方案)时,我注意到它有不同的构建说明,而不是通常的 `./configure; make; make install`
```
meson builddir
cd builddir
ninja
```
看起来 Meson 是一个可以用 ninja 作为后端的 C/C++/Java/Rust/Fortran 构建系统。
### 就是这些!
我使用 ninja 已经有几个月了。我真的很喜欢它,而且它几乎没有给我带来让人头疼的构建问题,这让我感觉非常神奇。
--------------------------------------------------------------------------------
via: https://jvns.ca/blog/2020/10/26/ninja--a-simple-way-to-do-builds/
作者:[Julia Evans][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://jvns.ca/
[b]: https://github.com/lujun9972
[1]: https://ninja-build.org/
[2]: https://ninja-build.org/manual.html
[3]: http://neugierig.org/software/chromium/notes/2011/02/ninja.html
[4]: https://mesonbuild.com/Tutorial.html
[5]: https://blog.sesse.net/blog/tech/2020-09-28-00-37_introducing_plocate

View File

@ -0,0 +1,117 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12834-1.html)
[#]: subject: (KDE Neon vs Kubuntu: Whats the Difference Between the Two KDE Distribution?)
[#]: via: (https://itsfoss.com/kde-neon-vs-kubuntu/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
KDE Neon vs Kubuntu这两款 KDE 发行版有什么区别?
======
当你发现两款基于 [Ubuntu][1] 并由 [KDE][2] 驱动的 Linux 发行版,你会选择哪一个?
* [Kubuntu][3] 是 Ubuntu 的官方 KDE 版本。
* [KDE Neon][4] 是 KDE 自己发布的基于 Ubuntu 的发行版。
我知道这常常会让人感到困惑,尤其是当你从来没有使用过这两个版本,但有人推荐你使用它们。因此,为了帮助你做出决定,我想整理一份 KDE Neon 和 Kubuntu 的区别(和相似之处)。
让我们先开始了解相似之处,然后再继续了解不同之处。
注:根据你的系统,你对这两个发行版的体验可能有所不同。所以,请把这篇文章作为一个参考,而不是一个”哪个更好“的比较。
### KDE Neon vs Kubuntu功能上的比较
![][5]
基于相似性比较发行版是一个不错的做法。所以,从理论上,我试图把最重要的区别写下来。
然而,值得注意的是,发行版的兼容性、性能和稳定性会根据你的硬件而有所不同,而这里没有考虑到这一点。
#### Ubuntu 作为基础
![][6]
是的,这两个 Linux 发行版都是基于 Ubuntu 的,但 KDE Neon 只基于最新的 Ubuntu LTS 版本,而 Kubuntu 则提供了基于 Ubuntu LTS 的版本和非 LTS 版本。
所以,如果使用 KDE Neon你可以期望在下一个 Ubuntu LTS 版本(每 2 年)的几个月后就能用上最新的 Ubuntu 功能。但是,对于 Kubuntu 来说,你可以选择一个非 LTS 版本,并尝试使用带有 6 个月的软件更新的最新 Ubuntu 版本。
KDE Neon 确实提供了测试版和开发者版,但这些都是为了测试预发布的 KDE 软件而提供的。
#### KDE Plasma 桌面
![][7]
尽管这两个发行版都采用了 KDE plasma 桌面,而且你可以获得相同程度的定制,但 KDE Neon 会首先获得最新的 KDE Plasma 桌面。
如果你还不知道KDE Neon 是由 KDE 官方团队开发的,由 Jonathan RiddellKubuntu 创始人)在[被 Canonical 强制赶出 Kubuntu][8] 后宣布的。
所以,不仅限于最新的 Plasma 桌面,如果你想尽快获得最新最好的 KDEKDE Neon 是最佳选择。
Kubuntu 最终会得到更新的 KDE 软件的更新,但这需要时间。如果你不太确定需要最新的 KDE 软件/桌面,而只是需要一个稳定的 KDE 系统,你应该选择 Kubuntu LTS 版本。
#### 预装软件
开箱即用,你会发现 Kubuntu 已经预装了一些必要的工具和应用程序,但是,对于 KDE Neon你需要找到并安装一些应用和工具。
从某些方面看,与 Kubuntu 相比KDE Neon 可能是一个轻量级的发行版。然而,对于新的 Linux 用户来说,他们可能会发现 Kubuntu 是一个易于使用的体验,并预装了更多必要的软件和工具。
#### 软件更新
如果你没有使用按流量计费的连接,这可能根本不重要。但是,我应该提一下,考虑到常规的 Ubuntu LTS 修复/更新以及 KDE 软件更新KDE Neon 会有更多的软件更新。
对于 Kubuntu你只会得到 Ubuntu LTS 的更新(除非你使用的是非 LTS 版本)。所以,从技术上讲,你会有更少的更新数量。
#### Ubuntu KDE 版与 Plasma 的体验差异
![][11]
我知道如果你没有尝试过这两个版本你可能会认为它们很相似。但是Kubuntu 是 Ubuntu 的官方版本,它更注重 Ubuntu 在 KDE 桌面环境上的使用体验。
而 KDE Neon 在技术上是一样的,但它的目的是为了获得一流的 Plasma 桌面体验,并搭载最新的东西。
尽管这两个发行版开箱即可完美工作,但它们有不同的愿景和相应的开发工作。你只需要决定你自己想要什么,然后选择其中之一。
#### 硬件兼容性
![Kubuntu Focus Laptop][12]
正如我前面提到的,这不是一个基于事实的观点。但是,根据我在网上快速了解用户分享的反馈或经验,似乎 Kubuntu 可以与各种旧硬件以及新硬件(可能追溯到 2012 年)一起工作,而 KDE Neon 可能不能。
只需要记住,如果你尝试 KDE Neon但由于某些原因不能工作。你知道该怎么做。
### 总结
那么你会选择哪个呢KDE Neon 还是 Kubuntu这完全是你的选择。
两者都是[初学者友好的 Linux 发行版][13]的不错选择,但如果你想要最新的 KDE Plasma 桌面KDE Neon 会更有优势。你可以在我们的 [KDE Neon 评测][10]中阅读更多关于它的内容。
欢迎在下面的评论中告诉我你的想法,你觉得它们中的任何一个有什么好的/坏的地方。
--------------------------------------------------------------------------------
via: https://itsfoss.com/kde-neon-vs-kubuntu/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://ubuntu.com/
[2]: https://kde.org/
[3]: https://kubuntu.org
[4]: https://neon.kde.org
[5]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/kde-neon-vs-kubuntu.png?resize=800%2C450&ssl=1
[6]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/01/install_ubuntu_8.jpg?resize=796%2C611&ssl=1
[7]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/kde-plasma-5-20-feat.png?resize=800%2C394&ssl=1
[8]: https://lwn.net/Articles/645973/
[9]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/08/kde-neon-review.jpg?fit=800%2C450&ssl=1
[10]: https://itsfoss.com/kde-neon-review/
[11]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/01/kubuntu-kde.jpg?resize=800%2C450&ssl=1
[12]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/01/kubuntu-focus-laptop.jpg?resize=800%2C600&ssl=1
[13]: https://itsfoss.com/best-linux-beginners/

View File

@ -0,0 +1,172 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12850-1.html)
[#]: subject: (You can Surf Internet in Linux Terminal With These Command Line Browsers)
[#]: via: (https://itsfoss.com/terminal-web-browsers/)
[#]: author: (Ankush Das https://itsfoss.com/author/ankush/)
使用命令行浏览器在 Linux 终端上网浏览
======
![](https://img.linux.net.cn/data/attachment/album/202011/22/212007f9s7aabmcj4aa9lo.jpg)
我猜你阅读这篇文章可能是用 Firefox 或基于 Chrome 的浏览器(如 [Brave][1]),或者,也可能是 Chrome 浏览器或 [Chromium][2]。
换句话说,你正在利用基于 GUI 的方式浏览网页。然而,在以前,人们使用终端来获取资源和浏览网页,因为所有的东西大多是基于文本的。
虽然现在不能从终端上获取每个信息,但对于一些文本信息,还是可以尝试使用命令行浏览器,从 Linux 终端上打开网页。
不仅如此,如果你访问的是远程服务器,或者只有一个没有 GUI 的终端,终端网页浏览器就可以发挥用处了。
因此,在本文中,我将介绍一些基于终端的 Web 浏览器,你可以在 Linux 上尝试它们。
### Linux 用户的最佳终端 Web 浏览器
注:此榜单排名不分先后。
#### 1、W3M
![][3]
`w3m` 是一个流行的基于文本的开源终端 Web 浏览器。尽管其初始项目已经不再活跃,但另一个开发者 Tatsuya Kinoshita 正在维护着它的一个活跃分支。
`w3m` 相当简单,支持 SSL 连接、色彩,也支持内嵌图片。当然,根据你试图访问的资源,你那边的情况可能会有所不同。根据我的简单测试,它似乎无法加载 [DuckDuckGo][4],但我可以[在终端中使用 Google][5]就够了。
安装后,你可以简单的在终端中输入 `w3m` 以得到帮助。如果你感兴趣的话,也可以到 [GitHub][6] 上去查看它的仓库。
**如何安装和使用 w3m**
`w3m` 在任何基于 Debian 的 Linux 发行版的默认仓库中都是可用的。如果你有一个基于 Arch 的发行版,但没有直接可用的软件包,你可能需要查看一下 [AUR][7]。
对于 Ubuntu你可以通过键入以下内容来安装它
```
sudo apt install w3m w3m-img
```
在这里,我们将 w3m 包和图片扩展一起安装,以支持内嵌图片。接下来,要开始安装,你只需要按照下面的命令进行操作即可:
```
w3m xyz.com
```
当然,你需要将 `xyz.com` 替换成任何你想浏览或测试的网站。最后,你应该知道,你可以使用键盘上的方向键来导航,当你想采取一个动作时,按回车键。
要退出,你可以按 `SHIFT+Q`,返回上一页是 `SHIFT+B`。其他快捷键包括用 `SHIFT+T` 打开新标签页和用 `SHIFT+U` 打开新的 URL。
你可以通过访问它的手册页来了解更多信息。
#### 2、Lynx
![][8]
Lynx 是另一个开源的命令行浏览器,你可以试试。幸运的是,很多的网站在使用 Lynx 时往往能正常工作,所以我说它在这方面肯定更好。我能够加载 DuckDuckGo并使其工作。
除此之外,我还注意到它可以让你在访问各种 Web 资源时接受或拒绝 cookie。你也可以将它设置为总是接受或拒绝。所以这是件好事。
另一方面,在终端上使用时,窗口不能很好地调整大小。我还没有寻找到任何解决方法,所以如果你正在尝试这个,你可能会想要这样做。不论如何,它都很好用,当你在终端启动它时,你会得到所有键盘快捷键的说明。
请注意,它与系统终端主题不匹配,所以无论你的终端看起来如何,它都会看起来不同。
**如何安装 Lynx**
与 w3m 不同的是,如果你有兴趣尝试的话,确实可以找到一些 Win32 上的安装程序。不过,在 Linux 上,它在大多数的默认仓库中都是可用的。
对于 Ubuntu 来说,你只需要输入:
```
sudo apt install lynx
```
要想使用,你只需要按照下面的命令进行操作:
```
lynx examplewebsite.com
```
在这里,你只需要将示例网站替换成你想要访问的资源即可。
如果你想找其他 Linux 发行版的软件包,可以查看他们的[官网资源][9]。
#### 3、Links2
![][10]
Links2 是一款有趣的基于文本的浏览器,你可以在你的终端上轻松使用,用户体验良好。它提供了一个很好的界面,你启动它后,只要输入网址就可以了。
![][11]
值得注意的是,主题将取决于你的终端设置,我设置为“黑绿色”主题,因此你看到的就是这个。当你以命令行浏览器的方式启动它后,你只需要按任意键就会出现 URL 提示,或者按 `Q` 键退出。它相当好用,可以渲染大多数网站的文字。
与 Lynx 不同的是,你没有接受或拒绝 cookie 的功能。除此之外,它似乎工作的还不错。
**如何安装 Links2**
正如你所期望的,你会发现它在大多数默认的仓库中都有。对于 Ubuntu你可以在终端输入以下命令来安装它
```
sudo apt install links2
```
如果你想在其他 Linux 发行版上安装它,你可以参考它的[官方网站][12]获取软件包或文档。
#### 4、eLinks
![][13]
eLinks 类似于 Links2但它已经不再维护了。你仍然可以在各种发行版的默认仓库中找到它因此我把它保留在这个列表中。
它不会与你的系统终端主题相融合。所以,如果你需要的话,作为一个没有“黑暗”模式的文本型浏览器,这可能不是一个漂亮的体验。
**如何安装 eLinks**
在 Ubuntu 上,安装它很容易。你只需要在终端中输入以下内容:
```
sudo apt install elinks
```
对于其他 Linux 发行版,你应该可以在标准软件仓库中找到它。但是,如果你在软件仓库中找不到它,你可以参考[官方安装说明][14]。
### 总结
在终端上运行的基于文本的 Web 浏览器并不多,这并不奇怪。一些项目,如 [Browsh][15],试图呈现一个现代的 Linux 命令行浏览器,但在我这里它不能工作。
虽然像 `curl``wget` 这样的工具允许你[从 Linux 命令行下载文件][16],但这些基于终端的 Web 浏览器提供了额外的功能。
除了命令行浏览器之外,如果你想在终端上玩玩,也可以尝试一些[Linux 命令行游戏][17]。
对于 Linux 终端上的文本型 Web 浏览器,你有什么看法?欢迎在下面的评论中告诉我你的想法。
--------------------------------------------------------------------------------
via: https://itsfoss.com/terminal-web-browsers/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://itsfoss.com/brave-web-browser/
[2]: https://itsfoss.com/install-chromium-ubuntu/
[3]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/10/w3m-google.jpg
[4]: https://duckduckgo.com/
[5]: https://itsfoss.com/review-googler-linux/
[6]: https://github.com/tats/w3m
[7]: https://itsfoss.com/aur-arch-linux/
[8]: https://i0.wp.com/itsfoss.com/wp-content/uploads/2020/10/lynx-terminal.jpg
[9]: https://lynx.invisible-island.net/lynx-resources.html
[10]: https://i1.wp.com/itsfoss.com/wp-content/uploads/2020/10/links2-terminal.jpg
[11]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/links2-terminal-welcome.jpg
[12]: http://links.twibright.com/download.php
[13]: https://i2.wp.com/itsfoss.com/wp-content/uploads/2020/10/elinks-terminal.jpg
[14]: http://elinks.or.cz/documentation/installation.html
[15]: https://www.brow.sh/
[16]: https://itsfoss.com/download-files-from-linux-terminal/
[17]: https://itsfoss.com/best-command-line-games-linux/

View File

@ -0,0 +1,126 @@
[#]: collector: (lujun9972)
[#]: translator: (wxy)
[#]: reviewer: (wxy)
[#]: publisher: (wxy)
[#]: url: (https://linux.cn/article-12865-1.html)
[#]: subject: (5 new sudo features you need to know in 2020)
[#]: via: (https://opensource.com/article/20/10/sudo-19)
[#]: author: (Peter Czanik https://opensource.com/users/czanik)
2020 年 5 个新 sudo 功能
======
> 从集中会话记录、chroot 支持到 Python APIsudo 1.9 提供了许多新功能。
![](https://img.linux.net.cn/data/attachment/album/202011/28/143544x5cdcxzf9dcujdng.jpg)
当你想在 [POSIX 系统][2]上执行一个操作时,最安全的方法之一就是使用 `sudo` 命令。与以 root 用户身份登录并执行命令可能是个危险的操作不同,`sudo` 授予任何被系统管理员[指定为 “sudoer”][3]的用户临时权限,来执行通常受限制的活动。
几十年来,这个系统帮助 Linux、Unix 和 macOS 系统免受愚蠢的错误和恶意攻击,它是当今所有主要 Linux 发行版的默认管理机制。
当在 2020 年 5 月发布 sudo 1.9 时,它带来了许多新功能,包括集中收集会话记录,支持 `sudo` 内的 chroot以及 Python API。如果你对其中的任何一项感到惊讶请阅读我的文章了解一些 [sudo 鲜为人知的功能][4]。
`sudo` 不仅仅是一个管理命令的前缀。你可以微调权限,记录终端上发生的事情,使用插件扩展`sudo`,在 LDAP 中存储配置,进行广泛的日志记录,以及更多。
1.9.0 版本和后续的小版本增加了各种新功能(我将在下面介绍),包括:
* 一个集中收集 `sudo` 会话记录的记录服务
* 审计插件 API
* 审批插件 API
* Python 对插件的支持
* `sudo` 内置 chroot 和 CWD 支持(从 1.9.3 开始)
### 哪里可以得到 sudo 1.9
大多数的 Linux 发行版仍然封装了上一代的 `sudo`1.8 版本并且在长期支持LTS的发行版中会保持这个版本数年。据我所知提供了最完整的 sudo 1.9 包的 Linux 发行版是 openSUSE[Tumbleweed][5],它是一个滚动发行版,而且该 `sudo` 包的子包中有 Python 支持。最近的 [Fedora][6] 版本包含了 sudo 1.9,但没有 Python 支持。[FreeBSD Ports][7] 有最新的 `sudo` 版本,如果你自己编译 `sudo` 而不是使用软件包,你可以启用 Python 支持。
如果你喜欢的 Linux 发行版还没有包含 sudo 1.9,请查看 [sudo 二进制页面][8]来查看是否有现成的包可以用于你的系统。这个页面还提供了一些商用 Unix 变种的软件包。
像往常一样,在你开始试验 `sudo` 设置之前,*确保你知道 root 密码*。是的,即使在 Ubuntu 上也是如此。有一个临时的“后门”是很重要的;如果没有这个后门,如果出了问题,你就必须得黑掉自己的系统。记住:语法正确的配置并不意味着每个人都可以在该系统上通过 `sudo` 做任何事情!
### 记录服务
记录服务可以集中收集会话记录。与本地会话记录存储相比,这有很多优势:
* 更方便地在一个地方进行搜索,而不是访问各个机器来寻找记录
* 即使在发送机器停机的情况下也可以进行记录
* 本地用户若想掩盖其轨迹,不能删除记录
为了快速测试,你可以通过非加密连接向记录服务发送会话。我的博客中包含了[说明][9],可以在几分钟内完成设置。对于生产环境,我建议使用加密连接。有很多可能性,所以请阅读最适合你的环境的[文档][10]。
### 审计插件 API
新的审计插件 API 不是一个用户可见的功能。换句话说,你不能从 `sudoers` 文件中配置它。它是一个 API意味着你可以从插件中访问审计信息包括用 Python 编写的插件。你可以用很多不同的方式来使用它,比如当一些有趣的事情发生时,从 `sudo` 直接发送事件到 Elasticsearch 或日志即服务LaaS上。你也可以用它来进行调试并以任何你喜欢的格式将其他难以访问的信息打印到屏幕上。
根据你使用它的方式,你可以在 `sudo` 插件手册页(针对 C 语言)和 `sudo` Python 插件手册中找到它的文档。在 `sudo` 源代码中可以找到 [Python 代码示例][11],在我的博客上也有一个[简化的例子][12]。
### 审批插件 API
审批插件 API 可以在命令执行之前加入额外的限制。这些限制只有在策略插件成功后才会运行,因此你可以有效地添加额外的策略层,而无需更换策略插件,进而无需更换 `sudoers`。可以定义多个审批插件,而且所有插件都必须成功,命令才能执行。
与审计插件 API 一样,你可以从 C 和 Python 中使用它。我博客上记录的[示例 Python 代码][13]是对该 API 的一个很好的介绍。一旦你理解了它是如何工作的,你就可以扩展它来将 `sudo` 连接到工单系统,并且只批准有相关开放工单的会话。你也可以连接到人力资源数据库,这样只有当班的工程师才能获得管理权限。
### Python 对插件的支持
尽管我不是程序员,但我最喜欢的 sudo 1.9 新特性是 Python 对插件的支持。你可以用 Python 也能使用 C 语言调用大部分 API。幸运的是`sudo` 对性能不敏感,所以运行速度相对较慢的 Python 代码对 `sudo` 来说不是问题。使用 Python 来扩展 `sudo` 有很多优势:
* 更简单、更快速的开发
* 不需要编译;甚至可以通过配置管理分发代码
* 许多 API 没有现成的 C 客户端,但有 Python 代码
除了审计和审批插件 API 之外,还有一些其他的 API你可以用它们做一些非常有趣的事情。
通过使用策略插件 API你可以取代 `sudo` 策略引擎。请注意,你将失去大部分的 `sudo` 功能,而且没有基于 `sudoers` 的配置。这在小众情况下还是很有用的,但大多数时候,最好还是继续使用 `sudoers`,并使用审批插件 API 创建额外的策略。如果你想尝试一下,我的 [Python 插件介绍][14]提供了一个非常简单的策略:只允许使用 `id` 命令。再次确认你知道 root 密码,因为一旦启用这个策略,它就会阻止任何实际使用 `sudo` 的行为。
使用 I/O 日志 API你可以访问用户会话的输入和输出。这意味着你可以分析会话中发生了什么甚至在发现可疑情况时终止会话。这个 API 有很多可能的用途,比如防止数据泄露。你可以监控屏幕上的关键字,如果数据流中出现任何关键字,你可以在关键字出现在用户的屏幕上之前中断连接。另一种可能是检查用户正在输入的内容,并使用这些数据来重建用户正在输入的命令行。例如,如果用户输入 `rm -fr /`,你可以在按下回车键之前就断开用户的连接。
组插件 API 允许非 Unix 组的查找。在某种程度上,这与审批插件 API 类似,因为它也扩展了策略插件。你可以检查一个用户是否属于一个给定的组,并在后面的配置部分基于此采取行动。
### chroot 和 CWD 支持
`sudo` 的最新功能是支持 chroot 和改变工作目录CWD这两个选项都不是默认启用的你需要在 `sudoers` 文件中明确启用它们。当它们被启用时,你可以调整目标目录或允许用户指定使用哪个目录。日志反映了这些设置何时被使用。
在大多数系统中chroot 只对 root 用户开放。如果你的某个用户需要 chroot你需要给他们 root 权限,这比仅仅给他们 chroot 权限要大得多。另外,你可以通过 `sudo` 允许访问 chroot 命令,但它仍然允许漏洞,他们可以获得完全的权限。当你使用 `sudo` 内置的 chroot 支持时,你可以轻松地限制对单个目录的访问。你也可以让用户灵活地指定根目录。当然,这可能会导致灾难(例如,`sudo --chroot / -s`),但至少事件会被记录下来。
当你通过 `sudo` 运行一个命令时,它会将工作目录设置为当前目录。这是预期的行为,但可能有一些情况下,命令需要在不同的目录下运行。例如,我记得使用过一个应用程序,它通过检查我的工作目录是否是 `/root` 来检查我的权限。
### 尝试新功能
希望这篇文章能启发你仔细研究一下 sudo 1.9。集中会话记录比在本地存储会话日志更加方便和安全。chroot 和 CWD 支持为你提供了额外的安全性和灵活性。而使用 Python 来扩展 `sudo`,可以很容易地根据你的环境来定制 `sudo`。你可以通过使用最新的 Linux 发行版或 `sudo` 网站上的即用型软件包来尝试这些新功能。
如果你想了解更多关于 sudo 的信息,这里有一些资源:
* [Sudo 官网][15]
* [Sudo 博客][16]
* [Sudo on Twitter][17]
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/10/sudo-19
作者:[Peter Czanik][a]
选题:[lujun9972][b]
译者:[wxy](https://github.com/wxy)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/czanik
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/tools_osyearbook2016_sysadmin_cc.png?itok=Y1AHCKI4 (Wratchet set tools)
[2]: https://opensource.com/article/19/7/what-posix-richard-stallman-explains
[3]: https://opensource.com/article/17/12/using-sudo-delegate
[4]: https://opensource.com/article/19/10/know-about-sudo
[5]: https://software.opensuse.org/distributions/tumbleweed
[6]: https://getfedora.org/
[7]: https://www.freebsd.org/ports/
[8]: https://www.sudo.ws/download.html#binary
[9]: https://blog.sudo.ws/posts/2020/03/whats-new-in-sudo-1.9-recording-service/
[10]: https://www.sudo.ws/man/sudo_logsrvd.man.html#EXAMPLES
[11]: https://github.com/sudo-project/sudo/blob/master/plugins/python/example_audit_plugin.py
[12]: https://blog.sudo.ws/posts/2020/06/sudo-1.9-using-the-new-audit-api-from-python/
[13]: https://blog.sudo.ws/posts/2020/08/sudo-1.9-using-the-new-approval-api-from-python/
[14]: https://blog.sudo.ws/posts/2020/01/whats-new-in-sudo-1.9-python/
[15]: https://www.sudo.ws/
[16]: https://blog.sudo.ws/
[17]: https://twitter.com/sudoproject

Some files were not shown because too many files have changed in this diff Show More