Merge remote-tracking branch 'LCTT/master'

This commit is contained in:
Xingyu Wang 2020-10-19 18:24:39 +08:00
commit 14ea2e1dcf
12 changed files with 1397 additions and 734 deletions

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

@ -1,28 +1,28 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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 中来确保你的自动化工作流计划不会与其他东西冲突。
![Calendar close up snapshot][1]
”随时“是执行自动化工作流的好时机吗?答案可能是否定的,原因各不相同
> 通过将日历应用集成到 Ansible 中,确保你的自动化工作流计划不会与其他东西冲突。
如果你希望避免同时进行更改,以最大限度地减少对关键业务流程的影响,并降低意外服务中断的风险,那么其他人不应该试图在你的自动化运行的同时进行更改。
![](https://img.linux.net.cn/data/attachment/album/202010/18/221110wk9kd9ewrde11zxx.jpg)
在某些情况下,可能存在一个正在进行的计划维护窗口。 或者,可能有大型事件即将来临、一个关键的业务时间,或者假期,你或许不想在星期五晚上进行更改。
“随时”是执行自动化工作流的好时机吗?出于不同的原因,答案可能是否定的。
如果要避免同时进行更改,以最大限度地减少对关键业务流程的影响,并降低意外服务中断的风险,则在你的自动化运行的同时,其他任何人都不应该试图进行更改。
在某些情况下,可能存在一个正在进行的计划维护窗口。或者,可能有大型事件即将来临、一个关键的业务时间、或者假期(你或许不想在星期五晚上进行更改)。
![Street scene with a large calendar and people walking][2]
([Curtis MacNewton][3], [CC BY-ND 2.0][4])
无论出于什么原因,你都希望将此信息发送到你的自动化平台,并防止在特定时间段内执行周期或临时任务。在变更管理的行话中,我说的是当变更活动不应该发生时,指定封锁窗口。
无论出于什么原因,你都希望将此信息发送到你的自动化平台,以防止在特定时间段内执行周期性或临时任务。用变更管理的行话,我说的是当变更活动不应该发生时,指定封锁窗口。
### Ansible 中的日历集成
@ -30,11 +30,10 @@
目标是这样的:在执行任何自动化或变更活动之前,你要执行一个 `pre-task` ,它会检查日历中是否已经安排了某些事情(目前或最近),并确认你没有在一个阻塞的时间段中。
想象一下,你有一个名为 `calendar` 的虚构模块,它可以连接到一个远程日历,比如 Google 日历,以确定你指定的时间是否已经以其他方式被标记为繁忙。你可以写一个类似这样的 playbook
想象一下,你有一个名为 `calendar` 的虚构模块,它可以连接到一个远程日历,比如 Google 日历,以确定你指定的时间是否已经以其他方式被标记为繁忙。你可以写一个类似这样的剧本:
```
\- name: Check if timeslot is taken
- name: Check if timeslot is taken
  calendar:
    time: "{{ ansible_date_time.iso8601 }}"
  register: output
@ -46,10 +45,7 @@ Ansible 实际会给出 `ansible_date_time`,将其传递给 `calendar` 模块
![Google Calendar screenshot][6]
(Nicolas Leiva, [CC BY-SA 4.0][7])
那么这个任务的输出就会高亮这个时间段被占用的事实 `busy: true`
那么这个任务的输出就会指明这个时间段被占用的事实 `busy: true`
```
ok: [localhost] =&gt; {
@ -66,7 +62,6 @@ ok: [localhost] =&gt; {
接下来,[Ansible Conditionals][8] 将帮助阻止所有之后任务的执行。一个简单的例子,你可以在下一个任务上使用 `when` 语句来强制它只有当上一个输出中的 `busy` 字段不是 `true` 时,它才会运行:
```
tasks:
  - shell: echo "Run this only when not busy!"
@ -75,9 +70,9 @@ tasks:
### 总结
在[上一篇文章][9]中,我说过 Ansible 是一个将事物连接在一起的框架,将不同的构建相互连接,以协调端到端自动化工作流。
在[上一篇文章][9]中,我说过 Ansible 是一个将事物连接在一起的框架,将不同的组成部分相互连接,以协调端到端自动化工作流。
这篇文章探讨了 playbook 如何与日历应用集成以检查可用性。然而,我只做了一些表面工作!例如,你的任务也可以阻止日历中的一个时间段,这里的发挥空间很大。
这篇文章探讨了 Ansible 剧本如何与日历应用集成以检查可用性。然而,我只做了一些表面工作!例如,你的任务也可以阻止日历中的一个时间段,这里的发挥空间很大。
在我的下一篇文章中,我将深入 `calendar` 模块是如何构建的,以及其他编程语言如何与 Ansible 一起使用。如果你和我一样是 [Go][10] 的粉丝,请继续关注!
@ -92,7 +87,7 @@ via: https://opensource.com/article/20/10/calendar-ansible
作者:[Nicolas Leiva][a]
选题:[lujun9972][b]
译者:[geekpi](https://github.com/geekpi)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出

View File

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (MATRIXKOO)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -1,66 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: ( chenmu-kk )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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/)
NFC vs. Bluetooth LE: When to use which
======
Near-field communications and Bluetooth LE are low-power wireless technologies suited for different uses in enterprises.
Metamorworks / Getty Images
Among many options for low-power, relatively short-ranged connectivity, two technologies stand out near-field communication and Bluetooth low energy. Both have relatively low deployment costs and are simple to use.
NFC is best known for being the technology behind many modern smart cards. NFC chips need to be very close within a few centimeters to a reader for a connection to be made, but thats an upside in its primary enterprise use case, which is security and access control.
[[Get regularly scheduled insights by signing up for Network World newsletters.]][1]
Bluetooth LE is a low-power derivative of the main Bluetooth standard, offsetting lower potential throughput with substantially reduced energy consumption and the consequent ability to fit into a wider range of potential use cases.
Next, well delve into more in-depth descriptions of each technology and their primary use cases.
### NFC features
NFC operates at near-contact ranges devices must be within several centimeters of each other in order to make contact. A readable passive NFC “tag” requires no independent power source at all, drawing energy from the initiators signal, which operates at around 13.5MHz and requires between 100 and 700 µA of power when actively reading a tag.
“The short range is actually an advantage,” said Gartner research senior director and analyst Bill Ray. “The big thing about NFC is that its not just the radio, theres a massive security protocol built-in.” That is, a potential bad actor would have to be very close within a few meters, using specialized equipment to even be able to detect an NFC connection taking place. NFC implementations can also layer on SSL technology for additional safety.
Thats not a surprise, given NFCs origins as a contactless payment technology. Its roots in that area create an appeal for retailers, which could use NFC to let customers get additional information about items before they buy, get coupons or ask for assistance from a clerk simply by touching their phones to an NFC hotspot.
While the short range involved has limited the number of use cases that make sense for NFC technology, its not solely about opening doors and buying lattes. NFC can be used to bootstrap connections for quick and easy pairing between devices, so a user could simply tap their phone on a properly equipped projector in a conference room to create an NFC connection, validate that the smartphone is an approved device to connect to, and give a presentation. The presentation or video data itself wouldnt be transferred via NFC, but the NFC handshake acts as a validation for a different wireless protocol, eliminating the need to sign into, for example, a Wi-Fi network, or any other higher-bandwidth network that could stream that data.
### Bluetooth LE characteristics
Bluetooth LE, by contrast, operates over substantially longer distances anywhere up to several dozen meters and has about twice the maximum bandwidth of an NFC connection at 1 Mbit/second. Its an outgrowth of the well-known Bluetooth technology, optimized for machine-to-machine connectivity, thanks to its lower power usage than the main-line standard. It uses less than 15 mA of power at either end of a connection, and has a practical range of about 10 meters, securing connections with AES encryption.
Yet its far from a drop-in replacement for NFC, according to Forrester principal analyst Andre Kindness.
“From an information transfer perspective [NFC is] a lot quicker than BLE,” he said. BLE usually takes an appreciable fraction of a second or longer to identify and secure a connection, while that process is more or less instantaneous with NFC.
Bluetooth LE, however, is considerably more versatile than NFC, thanks to its greater range, according to IDC senior research analyst Patrick Filkins.
“I think Bluetooth [LE] is a little better suited for enterprise,” he said. Use cases like asset tracking, indoor navigation, and targeted advertisements are just the tip of the iceberg.
For enterprises, then, the upshot is fairly straightforward NFC use cases are mostly separate from those for which a company would use Bluetooth, but, for the rare overlap where a choice can be made, the relative advantages and disadvantages are clear. NFC is very short-ranged, cheap, connects instantly and has a lower data transfer rate. Bluetooth LE works over much longer distances and at higher speeds, costs somewhat more and takes a moment to “handshake” its connections.
Join the Network World communities on [Facebook][2] and [LinkedIn][3] to comment on topics that are top of mind.
--------------------------------------------------------------------------------
via: https://www.networkworld.com/article/3574932/nfc-vs-bluetooth-le-when-to-use-which.html
作者:[Jon Gold][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://www.networkworld.com/author/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

@ -1,266 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (HankChow)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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)
Automate your container orchestration with Ansible modules for Kubernetes
======
Combine Ansible with Kubernetes for cloud automation. Plus, get our
cheat sheet for using the Ansible k8s module.
![Ship captain sailing the Kubernetes seas][1]
[Ansible][2] is one of the best tools for automating your work. [Kubernetes][3] is one of the best tools for orchestrating containers. What happens when you combine the two? As you might expect, Ansible combined with Kubernetes lets you automate your container orchestration. 
### Ansible modules
On its own, Ansible is basically just a framework for interpreting YAML files. Its true power comes from its [many modules][4]. Modules are what enable you to invoke external applications with just a few simple configuration settings in a playbook.
There are a few modules that deal directly with Kubernetes, and a few that handle related technology like [Docker][5] and [Podman][6]. Learning a new module is often similar to learning a new terminal command or a new API. You get familiar with a module from its documentation, you learn what arguments it accepts, and you equate its options to how you might use the application it interfaces with.
### Access a Kubernetes cluster
To try out Kubernetes modules in Ansible, you must have access to a Kubernetes cluster. If you don't have that, then you might try to open a trial account online, but most of those are short term. Instead, you can install [Minikube][7], as described on the Kubernetes website or in Bryant Son's excellent article on [getting started with Minikube][8]. Minikube provides a local instance of a single-node Kubernetes install, allowing you to configure and interact with it as you would a full cluster.
**[Download the [Ansible k8s cheat sheet][9]]**
Before installing Minikube, you must ensure that your environment is ready to serve as a virtualization backend. You may need to install `libvirt` and grant yourself permission to the `libvirt` group:
```
$ sudo dnf install libvirt
$ sudo systemctl start libvirtd
$ sudo usermod --append --groups libvirt `whoami`
$ newgrp libvirt
```
#### Install Python modules
To prepare for using Kubernetes-related Ansible modules, you should also install a few helper Python modules:
```
$ pip3.6 install kubernetes --user
$ pip3.6 install openshift --user
```
#### Start Kubernetes
If you're using Minikube instead of a Kubernetes cluster, use the `minikube` command to start up a local, miniaturized Kubernetes instance on your computer:
```
`$ minikube start --driver=kvm2 --kvm-network default`
```
Wait for Minikube to initialize. Depending on your internet connection, this could take several minutes.
### Get information about your cluster
Once you've started your cluster successfully, you can get information about it with the `cluster-info` option:
```
$ 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'.
```
### Use the k8s module
The entry point for using Kubernetes through Ansible is the `k8s` module, which enables you to manage Kubernetes objects from your playbooks. This module describes states resulting from `kubectl` instructions. For instance, here's how you would create a new [namespace][10] with `kubectl`:
```
`$ kubectl create namespace my-namespace`
```
It's a simple action, and the YAML representation of the same result is similarly terse:
```
\- hosts: localhost
  tasks:
    - name: create namespace
      k8s:
        name: my-namespace
        api_version: v1
        kind: Namespace
        state: present
```
In this case, the host is defined as `localhost`, under the assumption that you're running this against Minikube. Notice that the module in use defines the syntax of the parameters available (such as `api_version` and `kind`).
Before using this playbook, verify it with `yamllint`:
```
`$ yamllint example.yaml`
```
Correct any errors, and then run the playbook:
```
`$ ansible-playbook ./example.yaml`
```
Verify that the new namespace has been created:
```
$ 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
```
### Pull a container image with Podman
Containers are Linux systems, almost impossibly minimal in scope, that can be managed by Kubernetes. Much of the container specifications have been defined by the [LXC project][11] and Docker. A recent addition to the container toolset is Podman, which is popular because it runs without requiring a daemon.
With Podman, you can pull a container image from a repository, such as Docker Hub or Quay.io. The Ansible syntax for this is simple, and all you need to know is the location of the container, which is available from the repository's website:
```
   - name: pull an image
      podman_image:
        name: quay.io/jitesoft/nginx
```
Verify it with `yamllint`:
```
`$ yamllint example.yaml`
```
And then run the playbook:
```
$ 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
```
### Deploy with Ansible
You're not limited to small maintenance tasks with Ansible. Your playbook can interact with Ansible in much the same way a configuration file does with `kubectl`. In fact, in many ways, the YAML you know by using Kubernetes translates to your Ansible plays. Here's a configuration you might pass directly to `kubectl` to deploy an image (in this example, a web server):
```
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
```
If you know these parameters, then you mostly know the parameters required to accomplish the same with Ansible. You can, with very little modification, move that YAML into a `definition` element in your Ansible playbook:
```
   - 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
```
After running this, you can see the deployment with `kubectl`, as usual:
```
$ kubectl -n my-namespace get pods
NAME                      READY  STATUS
nginx-deploy-7fdc9-t9wc2  1/1    Running
```
### Modules for the cloud
As more development and deployments move to the cloud, it's important to understand how to automate the important aspects of your cloud. The `k8s` and `podman_image` modules are only two examples of modules related to Kubernetes and a mere fraction of modules developed for the cloud. Take a look at your workflow, find the tasks you want to track and automate, and see how Ansible can help you do more by doing less.
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/9/ansible-modules-kubernetes
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/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,682 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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)
Add throwing mechanics to your Python game
======
Running around avoiding enemies is one thing. Fighting back is another.
Learn how in the 12th article in this series on creating a platformer in
Pygame.
![Gaming on a grid with penguin pawns][1]
This is part 12 in an ongoing series about creating video games in [Python 3][2] using the [Pygame][3] module. Previous articles are:
1. [Learn how to program in Python by building a simple dice game][4]
2. [Build a game framework with Python using the Pygame module][5]
3. [How to add a player to your Python game][6]
4. [Using Pygame to move your game character around][7]
5. [What's a hero without a villain? How to add one to your Python game][8]
6. [Put platforms in a Python game with Pygame][9]
7. [Simulate gravity in your Python game][10]
8. [Add jumping to your Python platformer game][11]
9. [Enable your Python game player to run forward and backward][12]
10. [Put some loot in your Python platformer game][13]
11. [Add scorekeeping to your Python game][14]
My previous article was meant to be the final article in this series, and it encouraged you to go program your own additions to this game. Many of you did! I got emails asking for help with a common mechanic that I hadn't yet covered: combat. After all, jumping to avoid baddies is one thing, but sometimes it's awfully satisfying to just make them go away. It's common in video games to throw something at your enemies, whether it's a ball of fire, an arrow, a bolt of lightning, or whatever else fits the game.
Unlike anything you have programmed for your platformer game in this series so far, throwable items have a _time to live_. Once you throw an object, it's expected to travel some distance and then disappear. If it's an arrow or something like that, it may disappear when it passes the edge of the screen. If it's a fireball or a bolt of lightning, it might fizzle out after some amount of time.
That means each time a throwable item is spawned, a unique measure of its lifespan must also be spawned. To introduce this concept, this article demonstrates how to throw only one item at a time. (In other words, only one throwable item may exist at a time.) On the one hand, this is a game limitation, but on the other hand, it is a game mechanic in itself. Your player won't be able to throw 50 fireballs at once, since you only allow one at a time, so it becomes a challenge for your player to time when they release a fireball to try to hit an enemy. And behind the scenes, this also keeps your code simple.
If you want to enable more throwable items at once, challenge yourself after you finish this tutorial by building on the knowledge you gain.
### Create the throwable class
If you followed along with the other articles in this series, you should be familiar with the basic `__init__` function when spawning a new object on the screen. It's the same function you used for spawning your [player][6] and your [enemies][8]. Here's an `__init__` function to spawn a throwable object:
```
class Throwable(pygame.sprite.Sprite):
    """
    Spawn a throwable object
    """
    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
```
The primary difference in this function compared to your `Player` class or `Enemy` class `__init__` function is that it has a `self.firing` variable. This variable keeps track of whether or not a throwable object is currently alive on screen, so it stands to reason that when a throwable object is created, the variable is set to `1`.
### Measure time to live
Next, just as with `Player` and `Enemy`, you need an `update` function so that the throwable object moves on its own once it's thrown into the air toward an enemy.
The easiest way to determine the lifespan of a throwable object is to detect when it goes off-screen. Which screen edge you need to monitor depends on the physics of your throwable object.
* If your player is throwing something that travels quickly along the horizontal axis, like a crossbow bolt or arrow or a very fast magical force, then you want to monitor the horizontal limit of your game screen. This is defined by `worldx`.
* If your player is throwing something that travels vertically or both horizontally and vertically, then you must monitor the vertical limit of your game screen. This is defined by `worldy`.
This example assumes your throwable object goes a little forward and eventually falls to the ground. The object does not bounce off the ground, though, and continues to fall off the screen. You can try different settings to see what fits your game best:
```
    def update(self,worldy):
        '''
        throw physics
        '''
        if self.rect.y &lt; worldy: #vertical axis
            self.rect.x  += 15 #how fast it moves forward
            self.rect.y  += 5  #how fast it falls
        else:
            self.kill()     #remove throwable object
            self.firing = 0 #free up firing slot
```
To make your throwable object move faster, increase the momentum of the `self.rect` values.
If the throwable object is off-screen, then the object is destroyed, freeing up the RAM that it had occupied. In addition, `self.firing` is set back to `0` to allow your player to take another shot.
### Set up your throwable object
Just like with your player and enemies, you must create a sprite group in your setup section to hold the throwable object.
Additionally, you must create an inactive throwable object to start the game with. If there isn't a throwable object when the game starts, the first time a player attempts to throw a weapon, it will fail.
This example assumes your player starts with a fireball as a weapon, so each instance of a throwable object is designated by the `fire` variable. In later levels, as the player acquires new skills, you could introduce a new variable using a different image but leveraging the same `Throwable` class.
In this block of code, the first two lines are already in your code, so don't retype them:
```
player_list = pygame.sprite.Group() #context
player_list.add(player)             #context
fire = Throwable(player.rect.x,player.rect.y,'fire.png',0)
firepower = pygame.sprite.Group()
```
Notice that a throwable item starts at the same location as the player. That makes it look like the throwable item is coming from the player. The first time the fireball is generated, a `0` is used so that `self.firing` shows as available.
### Get throwing in the main loop
Code that doesn't appear in the main loop will not be used in the game, so you need to add a few things in your main loop to get your throwable object into your game world.
First, add player controls. Currently, you have no firepower trigger. There are two states for a key on a keyboard: the key can be down, or the key can be up. For movement, you use both: pressing down starts the player moving, and releasing the key (the key is up) stops the player. Firing needs only one signal. It's a matter of taste as to which key event (a key press or a key release) you use to trigger your throwable object.
In this code block, the first two lines are for context:
```
            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)
```
Unlike the fireball you created in your setup section, you use a `1` to set `self.firing` as unavailable.
Finally, you must update and draw your throwable object. The order of this matters, so put this code between your existing `enemy.move` and `player_list.draw` lines:
```
    enemy.move()  # context
    if fire.firing:
        fire.update(worldy)
        firepower.draw(world)
    player_list.draw(screen)  # context
    enemy_list.draw(screen)   # context
```
Notice that these updates are performed only if the `self.firing` variable is set to 1. If it is set to 0, then `fire.firing` is not true, and the updates are skipped. If you tried to do these updates, no matter what, your game would crash because there wouldn't be a `fire` object to update or draw.
Launch your game and try to throw your weapon.
### Detect collisions
If you played your game with the new throwing mechanic, you probably noticed that you can throw objects, but it doesn't have any effect on your foes.
The reason is that your enemies do not check for a collision. An enemy can be hit by your throwable object and never know about it.
You've already done collision detection in your `Player` class, and this is very similar. In your `Enemy` class, add a new `update` function:
```
    def update(self,firepower, enemy_list):
        """
        detect firepower collision
        """
        fire_hit_list = pygame.sprite.spritecollide(self,firepower,False)
        for fire in fire_hit_list:
            enemy_list.remove(self)
```
The code is simple. Each enemy object checks to see if it has been hit by the `firepower` sprite group. If it has, then the enemy is removed from the enemy group and disappears.
To integrate that function into your game, call the function in your new firing block in the main loop:
```
    if fire.firing:                             # context
        fire.update(worldy)                    # context
        firepower.draw(screen)                  # context
        enemy_list.update(firepower,enemy_list) # update enemy
```
You can try your game now, and most everything works as expected. There's still one problem, though, and that's the direction of the throw.
### Change the throw mechanic direction
Currently, your hero's fireball moves only to the right. This is because the `update` function of the `Throwable` class adds pixels to the position of the fireball, and in Pygame, a larger number on the X-axis means movement toward the right of the screen. When your hero turns the other way, you probably want it to throw its fireball to the left.
By this point, you know how to implement this, at least technically. However, the easiest solution uses a variable in what may be a new way for you. Generically, you can "set a flag" (sometimes also termed "flip a bit") to indicate the direction your hero is facing. Once you do that, you can check that variable to learn whether the fireball needs to move left or right.
First, create a new variable in your `Player` class to represent which direction your hero is facing. Because my hero faces right naturally, I treat that as the default:
```
        self.score = 0
        self.facing_right = True  # add this
        self.is_jumping = True
```
When this variable is `True`, your hero sprite is facing right. It must be set anew every time the player changes the hero's direction, so do that in your main loop on the relevant `keyup` events:
```
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == ord('a'):
                player.control(steps, 0)
                player.facing_right = False  # add this line
            if event.key == pygame.K_RIGHT or event.key == ord('d'):
                player.control(-steps, 0)
                player.facing_right = True  # add this line
```
Finally, change the `update` function of your `Throwable` class to check whether the hero is facing right or not and to add or subtract pixels from the fireball's position as appropriate:
```
        if self.rect.y &lt; worldy:
            if player.facing_right:
                self.rect.x += 15
            else:
                self.rect.x -= 15
            self.rect.y += 5
```
Try your game again and clear your world of some baddies.
![Python platformer with throwing capability][15]
(Seth Kenlon, [CC BY-SA 4.0][16])
As a bonus challenge, try incrementing your player's score whenever an enemy is vanquished.
### The complete code
```
#!/usr/bin/env python3
# by 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 &lt;[http://www.gnu.org/licenses/\&gt;][17].
import pygame
import pygame.freetype
import sys
import os
'''
Variables
'''
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)
'''
Objects
'''
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):
    """
    Spawn a throwable object
    """
    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):
        '''
        throw physics
        '''
        if self.rect.y &lt; 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 location, y location, img width, img height, img file
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):
    """
    Spawn a player
    """
    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):
        """
        control player movement
        """
        self.movex += x
    def jump(self):
        if self.is_jumping is False:
            self.is_falling = False
            self.is_jumping = True
    def update(self):
        """
        Update sprite position
        """
        # moving left
        if self.movex &lt; 0:
            self.is_jumping = True
            self.frame += 1
            if self.frame &gt; 3 * ani:
                self.frame = 0
            self.image = pygame.transform.flip(self.images[self.frame // ani], True, False)
        # moving right
        if self.movex &gt; 0:
            self.is_jumping = True
            self.frame += 1
            if self.frame &gt; 3 * ani:
                self.frame = 0
            self.image = self.images[self.frame // ani]
        # collisions
        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   # set damage back to 0
                self.health -= 1  # subtract 1 hp
        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  # stop jumping
        # fall off the world
        if self.rect.y &gt; 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  # stop jumping
            self.movey = 0
            if self.rect.bottom &lt;= 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  # how high to jump
        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):
    """
    Spawn an enemy
    """
    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):
        """
        enemy movement
        """
        distance = 80
        speed = 8
        if self.counter &gt;= 0 and self.counter &lt;= distance:
            self.rect.x += speed
        elif self.counter &gt;= distance and self.counter &lt;= distance * 2:
            self.rect.x -= speed
        else:
            self.counter = 0
        self.counter += 1
    def update(self, firepower, enemy_list):
        """
        detect firepower collision
        """
        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 &lt; 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 location, y location, img width, img height, img file
    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 &lt;= 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()  # spawn player
player.rect.x = 0  # go to x
player.rect.y = 30  # go to 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)
'''
Main Loop
'''
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)
    # scroll the world forward
    if player.rect.x &gt;= 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
    # scroll the world backward
    if player.rect.x &lt;= 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]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/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://opensource.com/article/17/10/python-101
[5]: https://opensource.com/article/17/12/game-framework-python
[6]: https://opensource.com/article/17/12/game-python-add-a-player
[7]: https://opensource.com/article/17/12/game-python-moving-player
[8]: https://opensource.com/article/18/5/pygame-enemy
[9]: https://opensource.com/article/18/7/put-platforms-python-game
[10]: https://opensource.com/article/19/11/simulate-gravity-python
[11]: https://opensource.com/article/19/12/jumping-python-platformer-game
[12]: https://opensource.com/article/19/12/python-platformer-game-run
[13]: https://opensource.com/article/19/12/loot-python-platformer-game
[14]: https://opensource.com/article/20/1/add-scorekeeping-your-python-game
[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

@ -1,5 +1,5 @@
[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )

View File

@ -1,94 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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 is a Desktop App for Various Streaming Music Services
======
_**Brief: MellowPlayer is a free and open-source desktop that lets you integrate web-based music streaming services on Linux and Windows.**_
Undoubtedly, a lot of users prefer tuning in to streaming services to listen to their favorite music instead of purchasing individual music from stores or downloading them for a collection.
Of course, streaming services let you explore new music and help artists reach out to a wider audience easily. But, with so much music streaming services available ([Soundcloud][1], [Spotify][2], [YouTube Music][3], [Amazon Music][4], etc) it often becomes annoying to utilize them effectively while using your computer.
You may [install Spotify on Linux][5] but there is no desktop app for Amazon Music. So, potentially you cannot manage the streaming service from a single portal.
What if a desktop app lets you integrate streaming services on both Windows and Linux for free? In this article, I will talk about such an app — [MellowPlayer][6].
### MellowPlayer: Open Source App to Integrate Various Streaming Music Services
![][7]
MellowPlayer is a free and open-source cross-platform desktop app that lets you integrate multiple streaming services and manage them all from one interface.
There are several supported streaming services that you can integrate. You also get a certain level of control to tweak your experience from each individual service. For instance, you can set to automatically skip ads or mute them on YouTube.
The cross-platform support for both Windows and Linux is definitely a plus point.
Apart from the ability to manage the streaming services, it also integrates the player with your system tray to easily control the music. This means that you can use media keys on your keyboard to control the music player.
It is also worth noting that you can add a new service that is not officially supported by just creating a plugin for it yourself within the app. To let you know more about it, let me highlight all the key features below.
### Features of MellowPlayer
![][8]
* Cross-platform (Windows &amp; Linux)
* Free &amp; Open-Source
* Plugin-based Application to let you add new service by creating a plugin
* Integrates the services as a native desktop app with the system tray
* Supports hot keys
* Notifications support
* Listening history
### Installing MellowPlayer on Linux
![][9]
MellowPlayer is available as a [Flatpak package][10]. I know its disappointing for some but its just Flatpak for Linux and an executable file for Windows. In case you didnt know, follow our guide on [using Flatpak on Linux][11] to get started.
[Download MellowPlayer][12]
### Wrapping Up
MellowPlayer is a handy desktop app for users who often dabble with multiple streaming services for music. Even though it works fine as per my test with SoundCloud, YouTube, and Spotify, I did notice that the app crashed when trying to re-size the window, just a heads up on that. You can explore more about it on its [GitLab page][13].
There are two similar applications that allow you to play multiple streaming music services: [Nuvola][14] and [Nuclear Music Player][15]. You may want to check them out.
Have you tried MellowPlayer? Feel free to share your thoughts in the comments below.
--------------------------------------------------------------------------------
via: https://itsfoss.com/mellow-player/
作者:[Ankush Das][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://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,69 @@
[#]: collector: (lujun9972)
[#]: translator: ( chenmu-kk )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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/)
NFC vs. 蓝牙 LE: 如何抉择
======
近场通信和蓝牙LE是适合企业不同用途的低功耗无线技术。
Metamorworks / Getty Images
在低功率、相对短距离连接的众多选择中,两种技术脱颖而出——近场通信和低功耗蓝牙。两者都具有相对低廉的部署成本且易于使用。
NFC作为许多现代智能卡片的背后技术而为大众所熟知。NFC芯片必须十分接近在几厘米内读卡器来实现连接 但这是它主要企业用例(安全性和访问控制)的一个优势。
[[通过注册Network World时事通讯定期获取信息。]][1]
蓝牙LE是主要蓝牙标准的低功耗衍生产品通过显著降低能耗来抵消较低的潜在吞吐量并具备适应更宽广的潜在用例的能力。
接下来,我们将研究每种技术更深入的细节内容以及它们的主要用例。
### NFC的未来
NFC在近距离接触范围内工作设备间必须靠近到几厘米范围内来进行连接一个可读无源的NFC芯片根本不需要任何独立电源它会从读卡器的信号中汲取能量工作频率在13.5MHz附近并且在主动读取芯片时需要100-700µA的电源。
Gartner研究高级总监兼分析师说“事实上短距离是它的优势。” NFC的一大优点是它不仅仅是无线电还内置了庞大的安全协议。也就是说潜在的不良因素将会逼近——使用专用设备在几米的范围内才能检测到正在发生的NFC连接。 NFC的施行还可以在SSL技术上分层来提高安全性。
考虑到NFC本就起源于非接触式支付技术这不足为奇。它的根源在于对零售商的吸引力它可以使用NFC让客户在购买商品、获取优惠券或者向店员寻求帮助前通过简单地使用手机来连接NFC热点就可以获取相关的信息。
尽管NFC只能在一个很短的范围内使用限制了使用NFC技术用例的数量但它不仅仅是打开门买一杯拿铁。NFC用于引导连接便于设备间轻松快速的配对因此用户可以在配备有投影仪的会议室中使用手机即可创建一个NFC连接并验证智能手机是否是一个可连接的授权设备并显示相关的信息。演示文稿或者视频数据本身不会通过NFC来传输但是NFC握手可作为不同无线协议间的验证从而无需用户登录例如Wi-Fi网络或者任何其他更高带宽可以传输数据的网络。
### 蓝牙LE的特点
相较之下Bluetooth LE可以在更长的距离上运行长达几十米在1 Mbit / s的带宽下其最大带宽约为NFC连接的两倍。它是出名的蓝牙技术的产物相较于主线标准的更低功耗优化了双机连接。 在双机连接的任何一端电流均小于15 mA实用范围约为10米可通过AES加密保护连接。
根据Forrester首席分析师Andre Kindness的说法它远非NFC的替代品。
他说:“从信息传递角度来看, [NFC] 比BLE快一点。”BLE通常需要一秒或更长时间的验证并安全连接而NFC几乎在瞬间完成连接。
然而根据IDC高级研究分析师Patrick Filkins的说法相较于NFC蓝牙LE由于范围更广而有着更多的通用性。
他说“我认为蓝牙LE比较适合企业”。而类似于资产追踪室内导航和目标广告的用例只是冰山一角。
对于企业结果是相当直接的——NFC用例大多与公司使用蓝牙的用例是分开的对于少有的可以选择的重叠相对的优势和劣势显而易见。NFC有着短距离廉价即时连接以及更低数据转换率的优点。蓝牙LE工作的距离更远、传输速率更高成本也更高还需要一点时间来进行“握手”连接。
加入 [Facebook][2] 和 [LinkedIn][3] 上的Network World社区在最热门的话题下留下你的评论。
--------------------------------------------------------------------------------
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/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [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

@ -1,284 +0,0 @@
[#]: collector: (lujun9972)
[#]: translator: (robsean)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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 语言要素放置到一份易读的备忘录上。
![备忘录封面图片][1]
在 1972 年,丹尼斯·里奇在贝尔实验室,在几年前,他和他的团队成员发明了 Unix 。在创建了一个经久不衰的操作系统(至今仍在使用)之后,他需要一种好的方法来编程这些 Unix 计算机以便它们可用执行新的任务。在现在看来这很奇怪但在当时编程语言相对较少FortranLisp[Algol][2] 以及 B 语言都很流行,但是,对于贝尔实验室的研究员们想要做的事情来说,它们还是远远不够的。丹尼斯·里奇创造了他自己的解决方案,表现出一种以程序员的主要特征而闻名的特质,他称之为 C 语言,并且在近 50 年后,它仍在广泛的使用。
### 为什么你应该学习 C 语言
今天,这里有很多语言为程序员提供比 C 语言更多是特性。最明显的一种语言是 C++ 语言,一种相当明显的命名方式的语言,它在 C 语言之上构建,创建了一种很好的面向对象的语言。不过,这里有很多其它的语言,它们都很好的存在理由。计算机擅长始终如一的重复,因此任何可预见的东西都足以构建到一种语言中,对程序员来说这意味着更少的工作量。为什么要在 C++ 语言中一行 (`long x = long(n);`) 可以做到的相同的事时,而要花费两行来改写 C 语言中的一个 `int` 为一个 `long` ?
然而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
```
这个程序成功地执行,但是没有触发第二个命令。
#### 变量和类型
在一些语言中,你可以在不具体指定变量所包含的数据的 _类型_ 的情况下创建变量。这些语言如此设计使得解释器对一个变量运行一些测试来企图发现变量什么样的数据类型。例如Python 知道当你创建一个表达式时,`var=1` 定义了一个整型数,将 `var` 添加一些东西上,这显然是一个整型数。它同样知道当你连接 `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` 默认运行以及如何在函数之间传递数据。
### 条件语句
在真实的编程中你通常希望你的代码根据数据做出判断。这是使用This is done with _条件_ 语句完成的,并且 `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 语言有用。 正如你学习时,使用 [Jim Hall][12] 的 FreeDOS 的 [C 语言忘备录][11]。它在一张双面纸忘备录上放置所有的基本要素,因此在你实施练习时,你可以立即访问 C 语言语法的所有要素。
--------------------------------------------------------------------------------
via: https://opensource.com/article/20/8/c-programming-cheat-sheet
作者:[Seth Kenlon][a]
选题:[lujun9972][b]
译者:[robsean](https://github.com/robsean)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/coverimage_cheat_sheet.png?itok=lYkNKieP (Cheat Sheet cover image)
[2]: https://opensource.com/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,267 @@
[#]: collector: (lujun9972)
[#]: translator: (HankChow)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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 模块。
![Ship captain sailing the Kubernetes seas][1]
[Ansible][2] 是实现自动化工作的优秀工具,而 [Kubernetes][3] 则是容器编排方面的利器要是把两者结合起来会有怎样的效果呢正如你所猜测的Ansible + Kubernetes 的确可以实现容器编排自动化。
### Ansible 模块
实际上Ansible 本身只是一个用于解释 YAML 文件的框架。它真正强大之处在于它[丰富的模块][4],所谓<ruby>模块<rt>module</rt></ruby>,就是在 Ansible playbook 中让你得以通过简单配置就能调用外部应用程序的一些工具。
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 的操作,在 playbook 中使用 `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那么主机名应该定义为 `localhost`。需要注意的是,模块中对其它可用参数也定义了对应的语法(例如 `api_version``kind` 参数)。
在运行这个 playbook 之前,先通过 `yamllint` 命令验证是否有错误:
```
`$ yamllint example.yaml`
```
确保没有错误之后,运行 playbook
```
`$ 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 拉取容器镜像
容器是受 Kubernetes 管理的最小单位 Linux 系统,因此 [LXC 项目][11]和 Docker 对容器定义了很多规范。Podman 是一个最新的容器操作工具集,它不需要守护进程就可以运行,为此受到了很多用户的欢迎。
通过 Podman 可以从 Docker Hub 或者 Quay.io 拉取到容器镜像。这一操作对应的 Ansible 语法也很简单,只需要将存储库网站提供的镜像路径写在 playbook 中的相应位置就可以了:
```
   - name: pull an image
      podman_image:
        name: quay.io/jitesoft/nginx
```
使用 `yamllint` 验证:
```
`$ yamllint example.yaml`
```
运行 playbook
```
$ 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 除了可以执行小型维护任务以外,还可以通过 playbook 实现其它由 `kubectl` 实现的功能,因为两者的 YAML 文件之间只有少量的差异。 在 Kubernetes 中使用的 YAML 文件只需要稍加改动,就可以在 Ansible playbook 中使用。例如下面这个用于使用 `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 文件中的大部分内容放到 playbook 中的 `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)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/seth
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/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,94 @@
[#]: collector: (lujun9972)
[#]: translator: (geekpi)
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: 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 上整合基于网络的音乐流媒体服务。**_
毋庸置疑,很多用户都喜欢使用流媒体服务来收听自己喜欢的音乐,而不是从商店购买单首音乐或者下载收藏。
当然,流媒体服务可以让你探索新的音乐,帮助艺术家轻松接触到更多的听众。但是,由于有许多的音乐流媒体服务([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 的特点
![][8]
* 跨平台 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)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://itsfoss.com/author/ankush/
[b]: https://github.com/lujun9972
[1]: https://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/