使用 Python 和 Asyncio 编写在线多人游戏（一）

Summary: 最近版本的 Python 对 asyncio 的引入和一个特别的 async/await 语法使得异步代码看起来像常规的阻塞代码一样，这使得 Python 成为了一个值得信赖的异步编程语言，所以我将尝试利用这些新特点来创建一个多人在线游戏。

期待第二篇，挺有意思

来自广东深圳的 Chrome Mobile 53.0|Android 4.4 用户

你在 Python 中用过异步编程吗？本文中我会告诉你怎样做，而且用一个[能工作的例子](http://snakepit-game.com/)来展示它：这是一个流行的贪吃蛇游戏，而且是为多人游戏而设计的。

* [游戏入口在此，点此体验](http://snakepit-game.com/)。

![](/data/attachment/album/201609/14/063325kqmx47j79v9a7egm.jpg)

### 1、简介

在技术和文化领域，大规模多人在线游戏（MMO）毋庸置疑是我们当今世界的潮流之一。很长时间以来，为一个 MMO 游戏写一个服务器这件事总是会涉及到大量的预算与复杂的底层编程技术，不过在最近这几年，事情迅速发生了变化。基于动态语言的现代框架允许在中档的硬件上面处理大量并发的用户连接。同时，HTML5 和 WebSockets 标准使得创建基于实时图形的游戏的直接运行至浏览器上的客户端成为可能，而不需要任何的扩展。

对于创建可扩展的非堵塞性的服务器来说，Python 可能不是最受欢迎的工具，尤其是和在这个领域里最受欢迎的 Node.js 相比而言。但是最近版本的 Python 正在改变这种现状。[asyncio](https://docs.python.org/3/library/asyncio.html) 的引入和一个特别的 [async/await](https://docs.python.org/3/whatsnew/3.5.html#whatsnew-pep-492) 语法使得异步代码看起来像常规的阻塞代码一样，这使得 Python 成为了一个值得信赖的异步编程语言，所以我将尝试利用这些新特点来创建一个多人在线游戏。

### 2、异步

一个游戏服务器应该可以接受尽可能多的用户并发连接，并实时处理这些连接。一个典型的解决方案是创建线程，然而在这种情况下并不能解决这个问题。运行上千的线程需要 CPU 在它们之间不停的切换（这叫做上下文切换），这将导致开销非常大，效率很低下。更糟糕的是使用进程来实现，因为，不但如此，它们还会占用大量的内存。在 Python 中，甚至还有一个问题，Python 的解释器（CPython）并不是针对多线程设计的，相反它主要针对于单线程应用实现最大的性能。这就是为什么它使用 GIL（global interpreter lock），这是一个不允许同时运行多线程 Python 代码的架构，以防止同一个共享对象出现使用不可控。正常情况下，在当前线程正在等待的时候，解释器会转换到另一个线程，通常是等待一个 I/O 的响应（举例说，比如等待 Web 服务器的响应）。这就允许在你的应用中实现非阻塞 I/O 操作，因为每一个操作仅仅阻塞一个线程而不是阻塞整个服务器。然而，这也使得通常的多线程方案变得几近无用，因为它不允许你并发执行 Python 代码，即使是在多核心的 CPU 上也是这样。而与此同时，在一个单一线程中拥有非阻塞 I/O 是完全有可能的，因而消除了经常切换上下文的需要。

实际上，你可以用纯 Python 代码来实现一个单线程的非阻塞 I/O。你所需要的只是标准的 [select](https://docs.python.org/2/library/select.html) 模块，这个模块可以让你写一个事件循环来等待未阻塞的 socket 的 I/O。然而，这个方法需要你在一个地方定义所有 app 的逻辑，用不了多久，你的 app 就会变成非常复杂的状态机。有一些框架可以简化这个任务，比较流行的是 [tornade](http://www.tornadoweb.org/) 和 [twisted](http://twistedmatrix.com/)。它们被用来使用回调方法实现复杂的协议（这和 Node.js 比较相似）。这种框架运行在它自己的事件循环中，按照定义的事件调用你的回调函数。并且，这或许是一些情况的解决方案，但是它仍然需要使用回调的方式编程，这使你的代码变得碎片化。与写同步代码并且并发地执行多个副本相比，这就像我们在普通的线程上做的一样。在单个线程上这为什么是不可能的呢？

这就是为什么出现微线程（microthread）概念的原因。这个想法是为了在一个线程上并发执行任务。当你在一个任务中调用阻塞的方法时，有一个叫做“manager” (或者“scheduler”)的东西在执行事件循环。当有一些事件准备处理的时候，一个 manager 会转移执行权给一个任务，并等着它执行完毕。任务将一直执行，直到它遇到一个阻塞调用，然后它就会将执行权返还给 manager。

>
> 微线程也称为轻量级线程（lightweight threads）或绿色线程（green threads）（来自于 Java 中的一个术语）。在伪线程中并发执行的任务叫做 tasklets、greenlets 或者协程（coroutines）。
>
>
>

Python 中的微线程最早的实现之一是 [Stackless Python](http://www.stackless.com/)。它之所以这么知名是因为它被用在了一个叫 [EVE online](http://www.eveonline.com/) 的非常有名的在线游戏中。这个 MMO 游戏自称说在一个持久的“宇宙”中，有上千个玩家在做不同的活动，这些都是实时发生的。Stackless 是一个独立的 Python 解释器，它代替了标准的函数栈调用，并且直接控制程序运行流程来减少上下文切换的开销。尽管这非常有效，这个解决方案不如在标准解释器中使用“软”库更流行，像 [eventlet](http://eventlet.net/) 和 [gevent](http://www.gevent.org/) 的软件包配备了修补过的标准 I/O 库，I/O 函数会将执行权传递到内部事件循环。这使得将正常的阻塞代码转变成非阻塞的代码变得简单。这种方法的一个缺点是从代码上看这并不分明，它的调用是非阻塞的。新版本的 Python 引入了本地协程作为生成器的高级形式。在 Python 的 3.4 版本之后，引入了 asyncio 库，这个库依赖于本地协程来提供单线程并发。但是仅仅到了 Python 3.5 ，协程就变成了 Python 语言的一部分，使用新的关键字 async 和 await 来描述。这是一个简单的例子，演示了使用 asyncio 来运行并发任务。

```
import asyncio

async def my_task(seconds):
    print("start sleeping for {} seconds".format(seconds))
    await asyncio.sleep(seconds)
    print("end sleeping for {} seconds".format(seconds))

all_tasks = asyncio.gather(my_task(1), my_task(2))
loop = asyncio.get_event_loop()
loop.run_until_complete(all_tasks)
loop.close()

```

我们启动了两个任务，一个睡眠 1 秒钟，另一个睡眠 2 秒钟，输出如下：

```
start sleeping for 1 seconds
start sleeping for 2 seconds
end sleeping for 1 seconds
end sleeping for 2 seconds

```

正如你所看到的，协程不会阻塞彼此——第二个任务在第一个结束之前启动。这发生的原因是 asyncio.sleep 是协程，它会返回执行权给调度器，直到时间到了。

在下一节中，我们将会使用基于协程的任务来创建一个游戏循环。

---

via: <https://7webpages.com/blog/writing-online-multiplayer-game-with-python-asyncio-getting-asynchronous/>

作者：[Kyrylo Subbotin](https://7webpages.com/blog/writing-online-multiplayer-game-with-python-asyncio-getting-asynchronous/) 译者：[xinglianfly](https://github.com/xinglianfly) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

（题图来自：[deviantart.net](http://img00.deviantart.net/44f3/i/2009/121/1/6/hydra_by_ruth_tay.jpg)）


QOwnNotes：一款记录笔记和待办事项的应用，集成 ownCloud 云服务

Summary:
QOwnNotes 是一款自由而开源的笔记记录和待办事项的应用，可以运行在 Linux、Windows 和 mac 上。
这款程序将你的笔记保存为纯文本文件，它支持 Markdown 支持，并与 ownCloud 云服务紧密集成。

还以为QQ出的#(滑稽)

正要大赞QQ，发现是QO

是呀，第一眼都误认为是QQ了~

看名字，一定是用 Qt 开发的。

还有是为 ownCloud 开发的。

Atom即视感。

[QOwnNotes](http://www.qownnotes.org/) 是一款自由而开源的笔记记录和待办事项的应用，可以运行在 Linux、Windows 和 mac 上。

这款程序将你的笔记保存为纯文本文件，它支持 Markdown 支持，并与 ownCloud 云服务紧密集成。

![](/data/attachment/album/201609/14/135853szxxerxksk7orlt9.jpg)

QOwnNotes 的亮点就是它集成了 ownCloud 云服务（当然是可选的）。在 ownCloud 上用这款 APP，你就可以在网路上记录和搜索你的笔记，也可以在移动设备上使用（比如一款像 CloudNotes 的软件[2](http://peterandlinda.com/cloudnotes/)）。

不久以后，用你的 ownCloud 账户连接上 QOwnNotes，你就可以从你 ownCloud 服务器上分享笔记和查看或恢复之前版本记录的笔记（或者丢到垃圾箱的笔记）。

同样，QOwnNotes 也可以与 ownCloud 任务或者 Tasks Plus 应用程序相集成。

>
> 如果你不熟悉 [ownCloud][3] 的话，这是一款替代 Dropbox、Google Drive 和其他类似商业性的网络服务的自由软件，它可以安装在你自己的服务器上。它有一个网络界面，提供了文件管理、日历、照片、音乐、文档浏览等等功能。开发者同样提供桌面同步客户端以及移动 APP。
>
>
>

因为笔记被保存为纯文本，它们可以在不同的设备之间通过云存储服务进行同步，比如 Dropbox，Google Drive 等等，但是在这些应用中不能完全替代 ownCloud 的作用。

我提到的上述特点，比如恢复之前的笔记，只能在 ownCloud 下可用（尽管 Dropbox 和其他类似的也提供恢复以前的文件的服务，但是你不能在 QOwnnotes 中直接访问到）。

鉴于 QOwnNotes 有这么多优点，它支持 Markdown 语言（内置了 Markdown 预览模式），可以标记笔记，对标记和笔记进行搜索，在笔记中加入超链接，也可以插入图片：

![](/data/attachment/album/201609/14/135441wraix0attti0tb0x.png)

标记嵌套和笔记文件夹同样支持。

代办事项管理功能比较基本还可以做一些改进，它现在打开在一个单独的窗口里，它也不用和笔记一样的编辑器，也不允许添加图片或者使用 Markdown 语言。

![](/data/attachment/album/201609/14/135451vb9p5p19lmqp8q6p.png)

它可以让你搜索你代办事项，设置事项优先级，添加提醒和显示完成的事项。此外，待办事项可以加入笔记中。

这款软件的界面是可定制的，允许你放大或缩小字体，切换窗格等等，也支持无干扰模式。

![](/data/attachment/album/201609/14/135459gk6k66zxxn6bk6xh.png)

从程序的设置里，你可以开启黑夜模式（这里有个 bug，在 Ubuntu 16.04 里有些工具条图标消失了），改变状态条大小，字体和颜色方案（白天和黑夜）：

![](/data/attachment/album/201609/14/135507cxuab4ozt53u83a4.png)

其他的特点有支持加密（笔记只能在 QOwnNotes 中加密），自定义键盘快捷键，输出笔记为 pdf 或者 Markdown，自定义笔记自动保存间隔等等。

访问 [QOwnNotes](http://www.qownnotes.org/) 主页查看完整的特性。

### 下载 QOwnNotes

如何安装，请查看安装页（支持 Debian、Ubuntu、Linux Mint、openSUSE、Fedora、Arch Linux、KaOS、Gentoo、Slackware、CentOS 以及 Mac OSX 和 Windows）。

QOwnNotes 的 [snap](https://uappexplorer.com/app/qownnotes.pbek) 包也是可用的，在 Ubuntu 16.04 或更新版本中，你可以通过 Ubuntu 的软件管理器直接安装它。

为了集成 QOwnNotes 到 ownCloud，你需要有 [ownCloud 服务器](https://download.owncloud.org/download/repositories/stable/owncloud/)，同样也需要 [Notes](https://github.com/owncloud/notes)、[QOwnNotesAPI](https://github.com/pbek/qownnotesapi)、[Tasks](https://apps.owncloud.com/content/show.php/Tasks?content=164356)、[Tasks Plus](https://apps.owncloud.com/content/show.php/Tasks+Plus?content=170561) 等 ownColud 应用。这些可以从 ownCloud 的 Web 界面上安装，不需要手动下载。

请注意 QOenNotesAPI 和 Notes ownCloud 应用是实验性的，你需要“启用实验程序”来发现并安装他们，可以从 ownCloud 的 Web 界面上进行设置，在 Apps 菜单下，在左下角点击设置按钮。

---

via: <http://www.webupd8.org/2016/09/qownnotes-is-note-taking-and-todo-list.html>

作者：[Andrew](http://www.webupd8.org/p/about.html) 译者：[jiajia9linuxer](https://github.com/jiajia9linuxer) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


使用 HTTP/2 服务端推送技术加速 Node.js 应用

Summary: 四月份，Cloudflare 宣布了对 HTTP/2 服务端推送技术的支持，他们是通过 HTTP 的 Link 头部来实现这项支持的。

配图好评！

我觉得这种东西自己开发太麻烦了，就别自己捣鼓了，找个第三方，方便，GoEasy就挺不错的，我昨天试了一下，代码简洁易懂，几分钟我就洗了一个自己的实时推送功能；官网: goeasy.io

四月份，我们宣布了对 [HTTP/2 服务端推送技术](https://www.cloudflare.com/http2/server-push/)的支持，我们是通过 HTTP 的 [Link 头部](https://www.w3.org/wiki/LinkHeader)来实现这项支持的。我的同事 John 曾经通过一个例子演示了[在 PHP 里支持服务端推送功能](https://blog.cloudflare.com/using-http-2-server-push-with-php/)是多么的简单。

![](/data/attachment/album/201609/14/142937id3ze66x6eqd6j63.jpg)

我们想让现今使用 Node.js 构建的网站能够更加轻松的获得性能提升。为此，我们开发了 [netjet](https://www.npmjs.com/package/netjet) 中间件，它可以解析应用生成的 HTML 并自动添加 Link 头部。当在一个示例的 Express 应用中使用这个中间件时，我们可以看到应用程序的输出多了如下 HTTP 头：

![](/data/attachment/album/201609/14/142907thea5xd18s8ot8xo.png)

[本博客](https://blog.cloudflare.com/accelerating-node-js-applications-with-http-2-server-push/)是使用 [Ghost](https://ghost.org/)（LCTT 译注：一个博客发布平台）进行发布的，因此如果你的浏览器支持 HTTP/2，你已经在不知不觉中享受了服务端推送技术带来的好处了。接下来，我们将进行更详细的说明。

netjet 使用了带有定制插件的 [PostHTML](https://github.com/posthtml/posthtml) 来解析 HTML。目前，netjet 用它来查找图片、脚本和外部 CSS 样式表。你也可以用其它的技术来实现这个。

在响应过程中增加 HTML 解析器有个明显的缺点：这将增加页面加载的延时（到加载第一个字节所花的时间)。大多数情况下，所新增的延时被应用里的其他耗时掩盖掉了，比如数据库访问。为了解决这个问题，netjet 包含了一个可调节的 LRU 缓存，该缓存以 HTTP 的 ETag 头部作为索引，这使得 netjet 可以非常快的为已经解析过的页面插入 Link 头部。

不过，如果我们现在从头设计一款全新的应用，我们就应该考虑把页面内容和页面中的元数据分开存放，从而整体地减少 HTML 解析和其它可能增加的延时了。

任意的 Node.js HTML 框架，只要它支持类似 Express 这样的中间件，netjet 都是能够兼容的。只要把 netjet 像下面这样加到中间件加载链里就可以了。

```
var express = require('express');
var netjet = require('netjet');
var root = '/path/to/static/folder';

express()
  .use(netjet({
    cache: {
      max: 100
    }
  }))
  .use(express.static(root))
  .listen(1337);

```

稍微加点代码，netjet 也可以摆脱 HTML 框架，独立工作：

```
var http = require('http');
var netjet = require('netjet');

var port = 1337;
var hostname = 'localhost';
var preload = netjet({
  cache: {
    max: 100
  }
});

var server = http.createServer(function (req, res) {
  preload(req, res, function () {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/html');
      res.end('<!doctype html><h1>Hello World</h1>');
  });
});

server.listen(port, hostname, function () {
  console.log('Server running at http://' + hostname + ':' + port+ '/');
});

```

[netjet 文档里](https://www.npmjs.com/package/netjet)有更多选项的信息。

### 查看推送了什么数据

![](/data/attachment/album/201609/14/142909eebxdjlvb8pvz3vg.png)

访问[本文](https://blog.cloudflare.com/accelerating-node-js-applications-with-http-2-server-push/)时，通过 Chrome 的开发者工具，我们可以轻松的验证网站是否正在使用服务器推送技术（LCTT 译注： Chrome 版本至少为 53）。在“Network”选项卡中，我们可以看到有些资源的“Initiator”这一列中包含了`Push`字样，这些资源就是服务器端推送的。

不过，目前 Firefox 的开发者工具还不能直观的展示被推送的资源。不过我们可以通过页面响应头部里的`cf-h2-pushed`头部看到一个列表，这个列表包含了本页面主动推送给浏览器的资源。

希望大家能够踊跃为 netjet 添砖加瓦，我也乐于看到有人正在使用 netjet。

### Ghost 和服务端推送技术

Ghost 真是包罗万象。在 Ghost 团队的帮助下，我把 netjet 也集成到里面了，而且作为测试版内容可以在 Ghost 的 0.8.0 版本中用上它。

如果你正在使用 Ghost，你可以通过修改 config.js、并在`production`配置块中增加 `preloadHeaders` 选项来启用服务端推送。

```
production: {
  url: 'https://my-ghost-blog.com',
  preloadHeaders: 100,
  // ...
}

```

Ghost 已经为其用户整理了[一篇支持文档](http://support.ghost.org/preload-headers/)。

### 总结

使用 netjet，你的 Node.js 应用也可以使用浏览器预加载技术。并且 [CloudFlare](https://blog.cloudflare.com/accelerating-node-js-applications-with-http-2-server-push/) 已经使用它在提供了 HTTP/2 服务端推送了。

---

via: <https://blog.cloudflare.com/accelerating-node-js-applications-with-http-2-server-push/>

作者：[Terin Stock](https://blog.cloudflare.com/author/terin-stock/) 译者：[echoma](https://github.com/echoma) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


开源新闻速递：elementary OS 0.4 正式发布

Summary:
更多：
- Linux Mint 18 "Sarah" KDE 版正式发布；
-  Linux LTS 内核 3.14 结束了其支持周期。

如果gnome3.22发布，我的gnome主题又挂了，我就换KDE，，，，

哈哈！想知道背后的故事。

### 今日关注

![](/data/attachment/album/201609/15/061407m9mhp9pd7yzpr9kq.jpg)

以界面优美而著称的 elementary OS 0.4 “Loki” 在经过了两个 Beta 版本之后[发布](http://blog.elementary.io/post/147637979911/loki-04-stable-release)了正式版，原本我们以为还会放出 RC 版的。“Loki” 基于 Ubuntu 16.04 LTS，由于是 LTS 版本，会支持到 2021年。

Cody Garver 在[发布](http://blog.elementary.io/post/147637979911/loki-04-stable-release)公告中说，“Loki 是 elementary OS 的最新版本，它是个以设计为导向的开源 Linux 操作系统，用于桌面计算机和笔记本电脑。它接替了发布于 2015 年 4 月的 Freya，它已经下载多达 120 万次 。”

elementary OS 0.4 “Loki” 最引人注目的地方是其重新打造的系统指示器，包括音乐、电源、蓝牙、日期与时间、网络等等，以及新的提示中心、多个应用菜单改进、重新设计的系统设置面板、更好的隐私保护、更加安全可靠。

### 图文摘要

![](/data/attachment/album/201609/15/054848az997kc95qzuwuqd.jpg)

*Linux Mint 18 "Sarah" KDE 版正式[发布](http://blog.linuxmint.com/?p=3092)。它是基于 Ubuntu 16.04 LTS 的，同样会支持 5 年。*

![](/data/attachment/album/201609/15/055050mlzovchrfvv2rjph.jpg)

*每年都在一个欧洲城市举办的 GUADEC 2017 会议[定于](https://www.gnome.org/news/2016/09/guadec-2017/)英国的<ruby> 曼彻斯特 <rp>  （ </rp> <rt>  Manchester </rt> <rp>  ） </rp></ruby>召开。因此，按照去年召开的 GUADEC 2015 的规定，GNOME 3.26 的开发代号也将叫做“Manchester”。GNOME 3.24 将于明年 3 月正式发布，而 3.26 则计划在 9 月发布，再过几天 GNOME 3.22 就要发布了。*

![](/data/attachment/album/201609/15/060504hdsrdd6zl9ddylhc.jpg)

*Greg Kroah-Hartman [宣布](http://lkml.iu.edu/hypermail/linux/kernel/1609.1/02103.html) Linux LTS 内核 3.14 结束了其支持周期，强烈建议使用该系列内核的用户马上升级到 4.4 LTS 或最新稳定版 4.7.3。*

![](/data/attachment/album/201609/15/060941tbc1dgjj0j5rge5b.jpg)

*VirtualBox 5.1.6 发布，首次支持最新的 Linux 4.8 内核。*

![](/data/attachment/album/201609/15/061153s0rhkjb7rinij5nn.jpg)

*LFS 和 BLFS [发布](http://lists.linuxfromscratch.org/pipermail/lfs-support/2016-September/050372.html) 7.10，不再支持 Qt4 和 KDE4 。*


Swift 3.0 发布！

Summary: 这是 Apple 开源 Swift 之后首次发布的重大版本。Swift 3 是一个重要版本，包含了多达上百项的主要改进，包括对语言核心和标准库的改进，Linux 版本增加了核心库，并首次发布了 Swift 包管理器。

swift, 从入门到重学

重学——笑哭了

哈哈

这是 [Apple 开源 Swift](/article-6689-1.html) 之后首次[发布](https://swift.org/blog/swift-3-0-released/)的重大版本。Swift 3 是一个重要版本，包含了多达上百项的主要改进，包括对语言核心和标准库的改进，Linux 版本增加了核心库，并首次发布了 [Swift 包管理器](https://swift.org/package-manager)。

![](/data/attachment/album/201609/15/064535hws92mm990rwrw07.jpg)

Swift 3 不兼容于之前发布的 2.2 和 2.3，也就是说，之前为 2.2 和 2.3 开发的代码，需要经过修改才能运行在 3.0 上。具体的不兼容情况和迁移信息请参见： [SE-0005](https://github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md) 、 [SE-0006](https://github.com/apple/swift-evolution/blob/master/proposals/0006-apply-api-guidelines-to-the-standard-library.md) 和[迁移指南](https://swift.org/migration-guide/)。这些改变主要来自对标准库 API 的命名，也完全改变了导入 Objective-C API 到 Swift 的方式。不过 Xcode 8.0 代码迁移工具能自动处理许多必要的源代码变化。

Swift 3.0 的文档也相应更新了，更多语言细节可以参考[这里](https://swift.org/documentation/#the-swift-programming-language)，或免费的 iBook。

平台支持方面，Linux 版本现在包括了 [Swift 核心库](https://swift.org/core-libraries/)和 [Swift 包管理器](https://swift.org/package-manager)。Ubuntu 14.04 和 15.10 用户可以[下载](https://swift.org/download/)官方发布的二进制版本。而对 Mac 平台， Swift 3.0 会作为 [Xcode 8.0](https://itunes.apple.com/app/xcode/id497799835) 的一部分出现。

源代码也可以在 GitHub 上下载到：

* [swift](https://github.com/apple/swift)
* [swift-llvm](https://github.com/apple/swift-llvm)
* [swift-clang](https://github.com/apple/swift-clang)
* [swift-lldb](https://github.com/apple/swift-lldb)
* [swift-cmark](https://github.com/apple/swift-cmark)
* [swift-corelibs-foundation](https://github.com/apple/swift-corelibs-foundation)
* [swift-corelibs-libdispatch](https://github.com/apple/swift-corelibs-libdispatch)
* [swift-corelibs-xctest](https://github.com/apple/swift-corelibs-xctest)
* [swift-llbuild](https://github.com/apple/swift-llbuild)
* [swift-package-manager](https://github.com/apple/swift-package-manager)


MySQL 8.0.0 发布

已使用mariadb！

mysql被收购后，变化还是比较大的

变化

mariaDB路过

感觉啥都在刷版本号，

Win系统一下子刷到10，bug满天飞；

三星直接来了个Note7，挺清真的！

和 java 学而已。<br />
java 8 不就是 1.8 么。

![](/data/attachment/album/201609/15/225359t3t36tfqqyayyjq7.jpg)

MySQL 开发团队于 12 日宣布 MySQL 8.0.0 开发里程碑版本（DMR）发布！

可能有人会惊奇 MySQL 为何从 5.x 一下跳跃到了 8.0。事实上，MySQL 5.x 系列已经延续了很多年，从被 Oracle 收购之前就是 5.1，而收购之后一直维持在 5.x，比如 5.5，5.6，5.7 等等。其实，如果按照原本的发布节奏，可以把 5.6.x 当成 6.x，5.7.x 当成 7.x。所以，只是换了版本命名方式而已。

不过这次发布的 MySQL 8.0.0 开发版本还是有不少亮点的。

### MySQL 8.0.0 亮点

* 事务性数据字典，完全脱离了 MyISAM 存储引擎
真正将数据字典放到了 InnoDB 中的一些表中，从此不再需要 FRM、TRG、PAR 文件啦！Information Schema 现在以数据字典表的一个视图出现。原则上可以完全不需要 MyISAM 数据表类型了，所有的系统表都可以放到 InnoDB 之中。
* SQL 角色
角色是一系列权限的集合。可以创建角色，给某个用户授予和去除角色。这对于权限管理很方便。
* utf8mb4 字符集将成为默认字符集，并支持 Unicode 9
默认字符集将从 `latin1` 改为 `utf8mb4`，默认<ruby> 定序 <rp>  （ </rp> <rt>  collation </rt> <rp>  ） </rp></ruby>将从`latin1_swedish_ci` 改为 `utf8mb4_800_ci_ai`。
* 不可见索引
可以将一些索引设置为不可见，这样 SQL 优化器就不会用到它，但是它会继续在后台保持更新。当有需要时，可以随时恢复可见。
* 对二进制数据可以进行位操作
不仅仅可以对 `BIGINT`进行位操作，从 8.0 开始也支持对 `[VAR]BINARY/[TINY|MEDIUM|LONG]BLOB`进行位操作了。
* 改进了对 IPv6 和 UUID 的操作
`INET6_ATON()` 和 `INET6_NTOA()` 现在可以进行位操作了，因为`INET6_ATON()`现在返回的是`VARBINARY(16)` 数据类型（128 位）。改进了 UUID 操作，引入了三个新的函数 `UUID_TO_BIN()`, `BIN_TO_UUID()`和 `IS_UUID()` 。MySQL 并没有特殊的 IPv6 和 UUID 数据类型，而是以`VARBINARY(16)` 数据类型保存的。
* 持续性的全局变量
可以用 `SET PERSIST` 来设置持久性的全局变量，即便服务器重启也会保持下来。
* <ruby> 性能数据库 <rp>  （ </rp> <rt>  Performance Schema </rt> <rp>  ） </rp></ruby>的改进
比如对性能数据库增加了 100 多个索引，可以检索更快。
* 重构 SQL 分析器
持续不断的逐步改进 SQL 分析器。旧的分析器由于其语法复杂性和自顶向下的分析方式从而有严重的限制，导致难以维护和扩展。
* 成本模型
InnoDB 缓冲区现在可以估算主内存缓存区中的有多少表和索引，这可以让优化器选择访问方式时知道数据是否可以存储在内存中还是必须存储到磁盘上。
* <ruby> 直方图 <rp>  （ </rp> <rt>  Histograms </rt> <rp>  ） </rp></ruby>
通过使用直方图，用户或 DBA 可以对数据分布进行统计，这可以用于查询优化以寻找优化的查询方案。
* 改进扫描性能
改进了 InnoDB 范围查询的性能，可提升全表查询和范围查询 5-20% 的性能。
* 重构 BLOB
重构 BLOB 加速了片段读取/更新操作，可以加速 JSON 数据的操作。
* 持久化自增值
InnoDB 会持久化保持自增序列的最大值到 redo 日志中。这个改进还修复了一个非常老的 199 号 bug。
* 临时表
取消对压缩临时表的支持，并存储临时表的元数据到内存中。

其它的更多重要改进和细节，请参考 MySQL 8.0.0 [发布公告](http://dev.mysql.com/doc/relnotes/mysql/8.0/en/)和[这里](http://mysqlserverteam.com/the-mysql-8-0-0-milestone-release-is-available/)。

### 下载

目前 8.0.0 还是开发版本，如果你希望体验和测试最新特性，可以从 [dev.mysql.com](http://dev.mysql.com/downloads/mysql/) 下载各个平台的安装包。不过，MySQL 软件包是越来越大了，Linux 平台上的二进制打包后就将近有 1 GB。如果在产品环境中使用，在 8.0 没有进入稳定版本之前，请继续使用 5.7 系列，当前最新的版本是 5.7.15 GA 版本——这只有 600 M 多。

最新的源代码放在 [GitHub](https://github.com/mysql/mysql-server) 上，感兴趣的朋友可以去看看，其中有不少是中国人的贡献。


百度运用 FPGA 方法大规模加速 SQL 查询

通过机器学习和FPGA硬件级别的层面来突破 SQL 查询语言之于 CPU 等硬件的短板，这是老菜棒子久而久之要做的事情。大型公司就这德行，细节不披露，搞得神神叨叨的。实际上可能才起步，自己也没有多少干货。

![](/data/attachment/album/201609/16/131625wa0q0zeygd0n2nd0.jpg)

尽管我们对百度今年工作焦点的关注集中在这个中国搜索巨头在深度学习方面的举措上，许多其他的关键的，尽管不那么前沿的应用表现出了大数据带来的挑战。

正如百度的欧阳剑在本周 Hot Chips 大会上谈论的，百度坐拥超过 1 EB 的数据，每天处理大约 100 PB 的数据，每天更新 100 亿的网页，每 24 小时更新处理超过 1 PB 的日志更新，这些数字和 Google 不分上下，正如人们所想象的。百度采用了类似 Google 的方法去大规模地解决潜在的瓶颈。

正如刚刚我们谈到的，Google 寻找一切可能的方法去打败摩尔定律，百度也在进行相同的探索，而令人激动的、使人着迷的机器学习工作是迷人的，业务的核心关键任务的加速同样也是，因为必须如此。欧阳提到，公司基于自身的数据提供高端服务的需求和 CPU 可以承载的能力之间的差距将会逐渐增大。

![](/data/attachment/album/201609/16/131626tang0wqi5ad7sq5a.png)

对于百度的百亿亿级问题，在所有数据的接受端是一系列用于数据分析的框架和平台，从该公司的海量知识图谱，多媒体工具，自然语言处理框架，推荐引擎，和点击流分析都是这样。简而言之，大数据的首要问题就是这样的：一系列各种应用和与之匹配的具有压倒性规模的数据。

当谈到加速百度的大数据分析，所面临的几个挑战，欧阳谈到抽象化运算核心去寻找一个普适的方法是困难的。“大数据应用的多样性和变化的计算类型使得这成为一个挑战，把所有这些整合成为一个分布式系统是困难的，因为有多变的平台和编程模型（MapReduce，Spark，streaming，user defined，等等）。将来还会有更多的数据类型和存储格式。”

尽管存在这些障碍，欧阳讲到他们团队找到了（它们之间的）共同线索。如他所指出的那样，那些把他们的许多数据密集型的任务相连系在一起的就是传统的 SQL。“我们的数据分析任务大约有 40% 是用 SQL 写的，而其他的用 SQL 重写也是可用做到的。” 更进一步，他讲道他们可以享受到现有的 SQL 系统的好处，并可以和已有的框架相匹配，比如 Hive，Spark SQL，和 Impala 。下一步要做的事情就是 SQL 查询加速，百度发现 FPGA 是最好的硬件。

![](/data/attachment/album/201609/16/131627tav5qmwdfbqwwdvq.png)

这些主板，被称为处理单元（ 下图中的 PE ），当执行 SQL 时会自动地处理关键的 SQL 功能。这里所说的都是来自演讲，我们不承担责任。确切的说，这里提到的 FPGA 有点神秘，或许是故意如此。如果百度在基准测试中得到了如下图中的提升，那这可是一个有竞争力的信息。后面我们还会继续介绍这里所描述的东西。简单来说，FPGA 运行在数据库中，当其收到 SQL 查询的时候，该团队设计的软件就会与之紧密结合起来。

![](/data/attachment/album/201609/16/131628p75l737pd5iud355.png)

欧阳提到了一件事，他们的加速器受限于 FPGA 的带宽，不然性能表现本可以更高，在下面的评价中，百度安装了 2 块12 核心，主频 2.0 GHz 的 intl E26230 CPU，运行在 128G 内存。SDA 具有 5 个处理单元，（上图中的 300MHz FPGA 主板）每个分别处理不同的核心功能（<ruby> 筛选 <rp>  （ </rp> <rt>  filter </rt> <rp>  ） </rp></ruby>，<ruby> 排序 <rp>  （ </rp> <rt>  sort </rt> <rp>  ） </rp></ruby>，<ruby> 聚合 <rp>  （ </rp> <rt>  aggregate </rt> <rp>  ） </rp></ruby>，<ruby> 联合 <rp>  （ </rp> <rt>  join </rt> <rp>  ） </rp></ruby>和<ruby> 分组 <rp>  （ </rp> <rt>  group by </rt> <rp>  ） </rp></ruby>）

为了实现 SQL 查询加速，百度针对 TPC-DS 的基准测试进行了研究，并且创建了称做处理单元（PE）的特殊引擎，用于在基准测试中加速 5 个关键功能，这包括<ruby> 筛选 <rp>  （ </rp> <rt>  filter </rt> <rp>  ） </rp></ruby>，<ruby> 排序 <rp>  （ </rp> <rt>  sort </rt> <rp>  ） </rp></ruby>，<ruby> 聚合 <rp>  （ </rp> <rt>  aggregate </rt> <rp>  ） </rp></ruby>，<ruby> 联合 <rp>  （ </rp> <rt>  join </rt> <rp>  ） </rp></ruby>和<ruby> 分组 <rp>  （ </rp> <rt>  group by </rt> <rp>  ） </rp></ruby>，（我们并没有把这些单词都像 SQL 那样大写）。SDA 设备使用卸载模型，具有多个不同种类的处理单元的加速卡在 FPGA 中组成逻辑，SQL 功能的类型和每张卡的数量由特定的工作量决定。由于这些查询在百度的系统中执行，用来查询的数据被以列格式推送到加速卡中（这会使得查询非常快速），而且通过一个统一的 SDA API 和驱动程序，SQL 查询工作被分发到正确的处理单元而且 SQL 操作实现了加速。

SDA 架构采用一种数据流模型，加速单元不支持的操作被退回到数据库系统然后在那里本地运行，比其他任何因素，百度开发的 SQL 加速卡的性能被 FPGA 卡的内存带宽所限制。加速卡跨整个集群机器工作，顺便提一下，但是数据和 SQL 操作如何分发到多个机器的准确原理没有被百度披露。

![](/data/attachment/album/201609/16/131630yw0737s17tmz273c.png)

![](/data/attachment/album/201609/16/131632i0qwwpbvkvrbwty0.png)

我们受限与百度所愿意披露的细节，但是这些基准测试结果是十分令人鼓舞的，尤其是 Terasort 方面，我们将在 Hot Chips 大会之后跟随百度的脚步去看看我们是否能得到关于这是如何连接到一起的和如何解决内存带宽瓶颈的细节。

---

via: <http://www.nextplatform.com/2016/08/24/baidu-takes-fpga-approach-accelerating-big-sql/>

作者：[Nicole Hemsoth](http://www.nextplatform.com/author/nicole/) 译者：[LinuxBars](https://github.com/LinuxBars) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


GitHub 2016 章鱼猫观察报告

Summary: GitHub 又发布了一年一度的章鱼猫观察报告。在这个报告中，分别对开源和社区做了一些有趣的统计，现将其中一些有趣的数据和趋势撷取出来分享给大家。

开源贡献者最多的组织，微软那个应该只是 Microsoft这个组织，不包括 dotnet 这个组织吧

嗯，应该是这样的，是我判断失误，修改下。

语言一共是316种

TNND，它第一版发布时候写错成 36 种，我还纳闷呢，心想是有些不算？

GitHub 又发布了一年一度的[章鱼猫观察报告](https://octoverse.github.com/)。在这个报告中，分别对开源和社区做了一些有趣的统计，现将其中一些有趣的数据和趋势撷取出来分享给大家。完整的报告请移步[此处](https://octoverse.github.com/)。

![](/data/attachment/album/201609/16/134327p8vbxk87v7vp9bvp.jpg)

### GitHub 上最流行的开源项目

从[让阿波罗 11 号登月的代码](https://github.com/chrislgarry/Apollo-11)到[开源课程](https://github.com/FreeCodeCamp/FreeCodeCamp)，过去十二个月中，GitHub 上又涌现了一大批开源项目。以下是最流行的（得到星标最多）项目：

![](/data/attachment/album/201609/16/135241qlxxe1qrzigasaee.jpg)

*最流行的开源项目*

其中使用最多的开源许可证是：[MIT](http://choosealicense.com/licenses/mit/)、[Apache-2.0](http://choosealicense.com/licenses/apache-2.0/) 和 [GNU General Public License v3.0](http://choosealicense.com/licenses/gpl-3.0/)。

### GitHub 上最爱用的编程语言

GitHub 上存放的开源项目使用了多达 316 种不同的编程语言，其中在过去十二月中提交的 PR（<ruby> 拉取请求 <rp>  （ </rp> <rt>  Pull Request </rt> <rp>  ） </rp></ruby>，用于向项目提交补丁） 使用最多的前 15 种编程语言是（其中的数字是 PR 数量）：

![](/data/attachment/album/201609/16/140520jz9n9wwppp8pqp7p.jpg)

*PR 中最流行的 15 种语言*

PR 中最流行的语言居然是 JavaScript，是因为 JavaScript 比较容易么？而且 JavaScript、C# 和 Go 语言的 PR 增长率达到了两倍，甚至，Swift 和 TypeScript 虽然总量不多，但是增长率达到了 3.5 倍。

### 贡献者的活跃程度

“<ruby> 活跃 <rp>  （ </rp> <rt>  Active </rt> <rp>  ） </rp></ruby>”是指有过代码提交、写了备注、被星标和<ruby> 问题汇报 <rp>  （ </rp> <rt>  issue </rt> <rp>  ） </rp></ruby>等行为。

这十二个月以来，有 580 万以上的活跃用户、33 万以上的活跃组织、1.9 亿以上的活跃仓库、1 千万以上的活跃问题汇报。

“<ruby> 贡献者 <rp>  （ </rp> <rt>  contributors </rt> <rp>  ） </rp></ruby>”是指对项目/仓库推送了代码、对打开或评论了问题和 PR 的人，按照贡献者对项目和组织进行排名：

![](/data/attachment/album/201609/16/141926ux0c9sc0uex95ivx.jpg)

*开源贡献者最多的前十个仓库*

其中贡献者最多的仓库是 [Font-Awesome](https://github.com/FortAwesome/Font-Awesome) 项目，这是一个图标字体的项目，不太理解为何有这么多的贡献者。其次是 [docker](https://github.com/docker/docker) 和 [npm](https://github.com/npm/npm)。

![](/data/attachment/album/201609/16/143111usshhhs8brb55kwr.jpg)

*开源贡献者最多的组织*

开源贡献者最多的组织是微软，超过了 Facebook、docker，以及谷歌。看来微软这一年确实是在开源方面下了死力。

![](/data/attachment/album/201609/16/143347zqvivvsvvdbabq35.jpg)

*被最多分支的仓库*

仓库被<ruby> 分支 <rp>  （ </rp> <rt>  fork </rt> <rp>  ） </rp></ruby>的越多代表了对它感兴趣、甚至会参与到开发中的人越多。这个排名第一的 [datasharing](https://github.com/jtleek/datasharing) 是个啥项目，我去看看——居然是一篇文章……好吧，让我看看第二个 [Spoon-Knife](https://github.com/octocat/Spoon-Knife)，这，是章鱼猫的一个教人如何分支仓库的例子……那么第三个 [ProgrammingAssignment2](https://github.com/rdpeng/ProgrammingAssignment2) ，哎，也是一个课程上用的例子……

好吧，我收回之前对分支的看法，就不能有个“正常”点的仓库嘛？

还好，第四 [bootstrap](https://github.com/twbs/bootstrap) 和第五 [tensorflow](https://github.com/tensorflow/tensorflow) 都是比较正常的开源项目。总之，项目流行不流行，不要看分支数量了。

![](/data/attachment/album/201609/16/143347w3m74zmm3ubd2b4d.jpg)

*被最多用户评审过代码的仓库*

这里的<ruby> 代码评审者 <rp>  （ </rp> <rt>  reviewers </rt> <rp>  ） </rp></ruby>指的是对修改过的代码进行过评论的人，这也代表贡献者对仓库的关注度。好吧。我除了对第一名 [homebrew](https://github.com/Homebrew/homebrew) 有点不解，其它的几名都觉得还算正常。

### GitHub 的新增用户

GitHub 已经有超过 520 万的用户和超 30 万的组织。这十二月以来，有超过 81 万的人发起了人生第一个 PR，更有 280 万人创造了他自己的第一个仓库。

![](/data/attachment/album/201609/16/150132x8vtqkrvhcy88kqh.jpg)

*新用户注册增长最多的国家*

而中国，是新用户注册增长最多的国家，基本上翻了一番。

### GitHub 上的组织

GitHub 上已经有超过 8 千万的 PR，而这些 PR 中有超过 85% 的来自于组织。在 GitHub 上以组织形式活动的除了商业性组织以外，很多大公司也在其企业的开发中采用了 [GitHub Enterprise](https://enterprise.github.com/home) ，其中不乏财富50强里面公司。

### 总结

报告就解读到这里，详细的图文并茂的报告，请移步 [GitHub](https://octoverse.github.com/)。


小米能通过后门在你的 Android 手机上静默安装任何应用

Summary: 一位来自荷兰的计算机专业的学生，正着手调查一个名为 “AnalyticsCore.apk” 的神秘预装程序。它 7 * 24 小时不间断的在后台运行，即使你删除它了还会重新出现！

雷布斯有一套的

究竟是真的？还是存粹的阴谋论？其实就看小米的自律能力了

确实有的，但现在是只要掌握信息，就会收集，不管是谁，一个德性

我给我妈买了个小米，不止一次后台自动安装软件。本来没有安装过的软件，第二天早上起床发现多了个APP

只有在更新后才偶尔安装一两个小米自家的应用，我怀疑你手机里有流氓软件，或者自己手快不小心安装的

1.可以确认不是手快安装，2.老妈电子盲，手机只有一个QQ，一个微信，一个开心消消乐打发时间，3都是晚间自动安装，第二天使用才发现

老爸老妈才会不小心装，<手动笑哭>隔段时间我看父母手机就有，还有qq微信是很大的流氓啊，不知道吗？

联想手机也有后台静默安装病毒的后门。被我抓住过好几次。

你以为智能手机市场争得头破血流的图个啥？

小米5刚出的时候就买了，貌似也没见有新的APP突然冒出来，那些系统自带的，倒是经常自动更新，也没去管它。

小米5，有两次手机莫名其妙的安装了应用...

确实，QQ，微信就是个大流氓。<br />
一不小心QQ微信就产仔了。

说的好像黑客比你小米的开发人员差一样，人家黑客比你高明多了。你放了后门你以为你有能力挡得住吗？人家黑客一下就可以解决你了。

有后门就肯定会被攻破！不管这种后门处于什么样的官方目的！！！

小米确实是经常更新自家程序，不过现在都一个德性，没有例外

我看我还是继续用谷歌亲儿子比较好。

niuihioioojiaojicojijoicoinciojioioja

验证码验证码验证码

*[更新] 文末补充了小米公司的申明。*

你是否拥有一台小米，HTC，三星或者是一加的 Android 手机呢？

如果回答是肯定的，那么你应该意识到，几乎所有的智能手机厂商提供的定制 ROM，如 CyanogenMod、Paranoid Android、 MIUI 或者一些其它的 ROM 都带有预装主题和用来提高设备的性能的应用。

但是，对于这些设备制造商预装的程序和服务，你是否多有考虑呢？它们的目的是什么，它们是否会对个人的安全或者是隐私构成威胁。

![](/data/attachment/album/201609/16/223043hhflfybcti3zj6fi.jpg)

出于这些问题答案的好奇心，一位来自荷兰的计算机专业的学生，同时也是一位安全爱好者，他拥有一台小米 4 智能手机，
正着手调查一个名为 “AnalyticsCore.apk” 的神秘预装程序。它 7 \* 24 小时不间断的在后台运行，即使你删除它了还会重新出现！

小米是世界上最大的智能手机制造商之一，此前一直被批评为[传播恶意软件](http://thehackernews.com/2014/10/xiaomi-data-breach-hacker.html)，（它）发售预装了间谍软件/广告软件和 [Android 操作系统的分支版本](http://thehackernews.com/2015/03/Xiaomi-Mi-4-malware.html)的手机，在没有经过用户同意的情况下，从设备中[秘密窃取用户的数据](http://thehackernews.com/2014/08/xiaomi-phones-secretly-sending-users.html)。

### 小米能够在你的设备上静默安装任何应用

在向该厂商的[支持论坛询问](http://en.miui.com/thread-184042-1-1.html) AnalyticsCore 的目的无果之后， Thijs Broenink 开始着手逆向此应用的代码，发现这个应用每隔 24 小时，都会从公司的服务器检查是否有该程序的更新。

在这些查询请求里，该应用将会发送设备的识别信息，包括手机的 IMEI、型号、MAC 地址、随机数、软件包名称及其签名。

如果在服务器上检测到名为 “Analytics.apk” 软件有更新的版本，它将会在后台自动的开始下载，然后安装，这一切都发生在用户不知情的情况下。

>
> “我无法在 Analytics 中找到任何证据，所以我猜测应该有权限更高的小米应用在后台进行安装。”Broenink 在[他的博客](https://www.thijsbroenink.com/2016/09/xiaomis-analytics-app-reverse-engineered/)中如是说。
>
>
>

当前的问题是，你的设备如何验证此 APK 的正确性，以确保它真的是一个 “Analytics” 程序呢。

Broenink 发现，手机端根本没有进行任何的检查就将此程序安装到用户的手机中，这也就意味着黑客有利用此漏洞的可能。

这也就意味着小米能够远程静默的将任何程序在服务器端重命名为“Analytics.apk”后安装到用户的手机。

>
> “所以看起来小米可以在 24 小时内把他们想要静默安装的任何（签名的？）程序包替换到你的手机上。我无法确定这个应用程序安装器什么时候被调用。但是我猜测，要是将自己的程序重命名为 Analytics.apk 后放置在正确的目录下，然后等着就会被安装了。”Broenink 说。
>
>
>

### 黑客也能利用此后门

研究人员无论是在该公司网站还是 Google 找了许久都没有发现 AnalyticsCore 程序的实际目的。很难说小米为什么在数百万的设备上放置这个神秘的“后门”。

正如我以前说过的：没有一个后门是只有他的创造者才能访问的。

所以，黑客或者是情报机构，是不是可以利用小米的这一后门在 24 小时内将恶意软件推送到数百万的设备上呢？！

更加讽刺的是，整个过程采用 HTTP 连接，也就是说它很容易受到中间人攻击。

>
> “这听起来是一个致命的漏洞，因为它们拥有我的 IMEI 和设备的型号，它们可以专门为我的设备安装任何 APK。”Broenink 说。
>
>
>

即使在小米论坛，也有很多的用户对此神秘的 APK 及其目的表示疑虑。

>
> “根本不知道这货的目的，就算是删除了它，一段时间后，它又出现了。”一位网友说道。
>
>
>

>
> 另一个用户表示，“如果查看电池用量程序，你会发现这货总是在最上面，鬼知道它吃了我多少电量。”
>
>
>

**如何阻止它秘密安装呢？**作为一个临时的解决方案，小米用户可以安装一个防火墙应用，然后在其中屏蔽所有小米相关域名的网络连接。

截至目前，在公司论坛上还没有小米团队的成员对 Broenink 提出的问题表示回应。我们将会持续关注此事件。

同时，如果你是小米的用户，如果在使用过程中有神秘奇怪的事情，在下方评论，以让我们知道。

### 来自小米的官方申明

一位小米的发言人联系到了最初发表本文的 [The Hacker News](http://thehackernews.com/2016/09/xiaomi-android-backdoor.html)，按 Thijs Broenink 的要求给出了一份官方声明，解释了关于该后门可以让黑客及小米自己在数以百万计的受影响设备上隐秘地安装任意应用的情况，声明说到：

> “AnalyticsCore 是一个内置的 MIUI 系统部件，其用途是数据分析，以帮助改善用户体验，比如 MIUI 错误分析。”

虽然该公司并没有对在无需干预的情况下就能够在你的设备上自动地后台安装任何应用表示否认或发表评论，不过该发言人澄清说黑客不能够利用这个“自升级”功能。

> “出于安全考虑，MIUI 会在安装或升级过程中检查 Analytics.apk 的签名，只有该 APK 来自官方并正确签名才会安装。”发言人补充道。

> “任何没有官方签名的 APK 都不能安装。因为 AnalyticsCore 是确保更佳的用户体验的关键，它支持自升级功能。从发布于 4 月/ 5 月的 MIUI V7.3 开始，会启用 HTTPS 用于以后的安全数据传输，以防止任何中间人攻击。”

我们将会进一步接触小米了解其无需用户干预自动安装应用的能力。


AngularJS 2.0 稳定版真的发布了！

Summary: 之前我们还哀叹，谷歌的 AngularJS 2.0 的稳定版看起来年底也未必能见到，然而，在前几天谷歌总部召开的一个会议上，突然就宣布发布了最终的稳定版——而这距离前一个版本 RC7 的发布才过去了一天。

之前我们还哀叹，谷歌的 AngularJS 2.0 的稳定版看起来年底也未必能见到，然而，在 9 月 14 日谷歌总部召开的一个会议上，突然就宣布最终的稳定版发布了——而这距离前一个版本 RC7 的发布才过去了一天。

AngularJS 2.0 的开发始于 2014 年秋天，最初计划是一年后发布正式版本，然而随着项目的日渐庞大，就日复一日的拖延下来了，不过，还好，终于在两年后正式发布了。

![](/data/attachment/album/201609/17/093946jalf4fd4tf3295fi.jpg)

这个最终版，按照其官方的说法是：

>
> “最终版”意味着什么？意味着它的稳定性已经得到了大范围用例的验证；意味着它已经针对产品化、文件尺寸和性能进行过优化；意味着借助预编译技术和内置的延迟加载机制，我们可以确信你能发布出最快、最小的应用，并且横跨浏览器、桌面和移动平台；意味着为开发人员准备的 Angular CLI 和风格指南得到了大幅强化。
>
>
>

为什么这么期待 AngularJS 2 呢？这个框架是一个革命性的 Web 开发框架，它在 2010 年 10 月的时候，采用微软的 TypeScript 重写后，更是如虎添翼，不但性能提升、功能增强，资源占用也更少了。不过，有一个不好的消息是， AngularJS 2.0 和 1.x 是不兼容的，因此如果是用 1.x 编写的应用，可能面临着大量的重写和移植工作。

作为一个持续了两年才开发完的前端框架，它的功能特性和亮点显然不是我们一篇短文就可以道尽的，因此这里只是提到一些最引人注目的特性：

* 提前（AOT）编译
* 内置按需加载
* 新的 Angular 命令行接口
* Angular 样式指南
* 支持 ES5 和 ES6
* 集成 React Native 和 NativeScript
* ……

好了，渴望尝试的 AngularJS 用户们，可以从其官网 <https://angular.io/> 或 [GitHub](https://github.com/angular/angular) 上下载，这里还有一个[五分钟入门教程](https://angular.io/docs/ts/latest/quickstart.html)。（显然，你知道的，这些都是墙外的。）另外，也有一个官方认可的中文站可以去访问： <https://angular.cn/> 。


LXDE、Xfce 及 MATE 桌面环境下的又一系统监视器应用：Multiload-ng

Summary: Multiload-ng 是一个 GTK2 图形化系统监视器应用，可集成到 Xfce、LXDE 及 MATE 的桌面面板中， 它 fork 自原来的 GNOME Multiload 应用。它也可以运行在一个独立的窗口中。

又什么用呀？

还是有些用的

楼上是不是一个人格用 linux，一个人格用 windows？

这难道是左右互搏？还是德比？

![](/data/attachment/album/201609/17/121052n2tqm7k79wtc9k9o.png)

[Multiload-ng](https://github.com/udda/multiload-ng) 是一个 GTK2 图形化系统监视器应用，可集成到 Xfce、LXDE 及 MATE 的桌面面板中， 它 fork 自原来的 GNOME Multiload 应用。它也可以运行在一个独立的窗口中。

![](/data/attachment/album/201609/17/120153eux6d0e5gsu5jdn5.png)

Multiload-ng 的特点有：

* 支持以下资源的图形块： CPU，内存，网络，交换空间，平均负载，磁盘以及温度；
* 高度可定制；
* 支持配色方案；
* 自动适应容器（面板或窗口）的改变；
* 极低的 CPU 和内存占用；
* 提供基本或详细的提示信息；
* 可自定义双击触发的动作。

相比于原来的 Multiload 应用，Multiload-ng 含有一个额外的图形块（温度），以及更多独立的图形自定义选项，例如独立的边框颜色，支持配色方案，可根据自定义的动作对鼠标的点击做出反应，图形块的方向可以被设定为与面板的方向无关。

它也可以运行在一个独立的窗口中，而不需要面板：

![](/data/attachment/album/201609/17/120250zzc555z3cc03rrcz.png)

另外，它的 GitHub page 上说还会带来更多的图形块支持。

下图展示的是在带有一个垂直面板的 Xubuntu 16.04 中，该应用分别处于水平和垂直方向的效果：

![](/data/attachment/album/201609/17/120318o8y2vwy8gzlyvs2u.png)

![](/data/attachment/album/201609/17/120331i4z53ix4i23o2lkx.png)

这个应用的偏好设置窗口虽然不是非常好看，但是有计划去改进它：

![](/data/attachment/album/201609/17/121239rzfkzgskhrcdwscs.png)

Multiload-ng 当前使用的是 GTK2，所以它不能在构建自 GTK3 下的 Xfce 或 MATE 桌面环境（面板）下工作。

对于 Ubuntu 系统而言，只有 Ubuntu MATE 16.10 使用 GTK3。但是鉴于 MATE 的系统监视器应用也是 Multiload GNOME 的一个分支，所以它们大多数的功能相同（除了 Multiload-ng 提供的额外自定义选项和温度图形块）。

该应用的[愿望清单](https://github.com/udda/multiload-ng/wiki/Wishlist) 中提及到了计划支持 GTK3 的集成以及各种各样的改进，例如温度块资料的更多来源，能够显示十进制（KB、MB、GB……）或二进制（KiB、MiB、GiB……）单位等等。

### 安装 Multiload-ng

请注意因为依赖的关系， Multiload-ng 不能在 Lubuntu 14.04 上构建。

Multiload-ng 可在 WebUpd8 的主 PPA （针对 Ubuntu 14.04 - 16.04 / Linux Mint 17.x 和 18）中获取到。可以使用下面的命令来添加 PPA 并更新软件源：

```
sudo add-apt-repository ppa:nilarimogard/webupd8
sudo apt update

```

然后可以使用下面的命令来安装这个应用：

**对于 LXDE (Lubuntu)：**

```
sudo apt install lxpanel-multiload-ng-plugin

```

**对于 Xfce (Xubuntu，Linux Mint Xfce)：**

```
sudo apt install xfce4-multiload-ng-plugin

```

**对于 MATE (Ubuntu MATE，Linux Mint MATE)：**

```
sudo apt install mate-multiload-ng-applet

```

**独立安装 (不需要集成到面板)：**

```
sudo apt install multiload-ng-standalone

```

一旦安装完毕，便可以像其他应用那样添加到桌面面板中了。需要注意的是在 LXDE 中，Multiload-ng 不能马上出现在面板清单中，除非重新启动面板。你可以通过重启会话（登出后再登录）或者使用下面的命令来重启面板：

```
lxpanelctl restart

```

独立的 Multiload-ng 应用可以像其他正常应用那样从菜单中启动。

如果要下载源码或报告 bug 等，请看 Multiload-ng 的 [GitHub page](https://github.com/udda/multiload-ng)。

---

via: <http://www.webupd8.org/2016/08/alternative-system-monitor-applet-for.html>

作者：[Andrew](http://www.webupd8.org/p/about.html) 译者：[FSSlc](https://github.com/FSSlc) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


一个月内发现的第六起 Linux DDoS 木马

Summary: Linux 是过去一个月以来最热门的木马攻击平台，在最近 30 天内，安全研究人员已经发现、分析和曝光了其它五个 Linux 木马： Rex、PNScan、Mirai、 LuaBot 和 Linux.BackDoor.Irc。

如何搞定这个ddos病毒！静待大神的解决！

简单， 你只要内存里面有那些关键字就行了。。:/

虽然我自己不会写病毒，我也很怕线上服务器被攻击，但是看到这些病毒、黑客、攻击之类的新闻就莫名其妙的兴奋！我是不是病了？

同意。

Linux 用户又有一个木马需要苦恼了，就像以往一样，这些坏蛋大多部署在被劫持的 Linux 系统上，并在接受到命令后发起 DDoS 攻击。

发现了这件事的 Dr.Web 的安全研究人员说，木马似乎是通过<ruby> 破壳漏洞 <rp>  （ </rp> <rt>  Shellshock </rt> <rp>  ） </rp></ruby>感染的这些 Linux 机器——现在仍然有很多设备没有补上这个漏洞。

![](/data/attachment/album/201609/17/200421kbihtjm4r43vidil.png)

该木马被命名为 [Linux.DDoS.93](http://vms.drweb.com/virus/?_is=1&i=8598428)，它首要会修改 /var/run/dhcpclient-eth0.pid 这个文件，并通过它在计算机启动时运行。如果该文件不存在，就会自己创建一个。

当该木马运行起来以后会进行初始化，它会启动两个进程，一个用于与 C&C （控制）服务器通讯，另外一个用于确保木马的父进程一直运行。

### 该木马启动 25 个子进程进行 DDoS 攻击

当控制该木马网络的攻击者发起攻击命令时，这个木马会启动 25 个子进程来进行 DDoS 攻击。

当前，该木马可以发出 UDP 洪泛（针对随机或特定端口），TCP 洪泛（简单的包，或给每个包随机增加至多 4096 字节的数据）和 HTTP 洪泛（通过 POST、GET 或 HEAD 请求）。

而且，该木马还能自我更新、自我删除、终止自己的进程、ping、从 C&C 服务器下载和运行文件。

### 当它发现某些名字时会关闭

这个木马还包括一个功能，如果在扫描计算机内存并列出活动的进程时发现如下字符串会关闭自己：

```
privmsg
getlocalip
kaiten
brian krebs
botnet
bitcoin mine
litecoin mine
rootkit
keylogger
ddosing
nulling
hackforums
skiddie
script kiddie
blackhat
whitehat
greyhat
grayhat
doxing
malware
bootkit
ransomware
spyware
botkiller
```

这些字符串大多数与信息安全领域有关，似乎是为了防止安全研究人员的反向工程研究，或者是为了避免感染该恶意软件作者自己的机器。

在感染过程中，该木马也会扫描它的旧版本，并会关闭旧版本然后安装一个新的。这意味着这是一个自动更新系统，该木马的最新版本总是会出现在被感染的机器上。

Linux 是过去一个月以来最热门的木马攻击平台，在最近 30 天内，安全研究人员已经发现、分析和曝光了其它五个 Linux 木马： [Rex](http://news.softpedia.com/news/rex-linux-trojan-can-launch-ddos-attacks-lock-websites-mine-for-cryptocurrency-507486.shtml)、[PNScan](http://news.softpedia.com/news/pnscan-linux-trojan-resurfaces-with-new-attacks-targeting-routers-in-india-507617.shtml)、[Mirai](http://news.softpedia.com/news/mirai-ddos-trojan-is-the-next-big-threat-for-iot-devices-and-linux-servers-507964.shtml)、 [LuaBot](http://news.softpedia.com/news/luabot-is-the-first-botnet-malware-coded-in-lua-targeting-linux-platforms-507978.shtml) 和 [Linux.BackDoor.Irc](http://news.softpedia.com/news/new-linux-trojan-discovered-coded-in-mozilla-s-rust-language-508135.shtml)。


Snap、Flatpak 这种通吃所有发行版的打包方式真的有用吗？

我个人认为，snap 的移动版的沙盒安全机制的设计还是不错的，可以有效杜绝流氓和病毒软件等非法行为。但是，桌面版的 snap 却可以轻松绕过这一机制，只要 linux 的发行版本还在使用 x window，那么它就无法避免这一点。是时候进行一场革命了！

连windows这种好几年才发布一个版本的系统都采用这种模式，更何况一年发布几百种不同版本的linux。"依赖"阻碍Linux发展多少年了，至今只能在服务器领域有所发展！

我不喜欢，但我觉得这是趋势。

依赖的确是linux安装软件最蛋疼的事情，特别是没有网络的情况下。

势不可挡的趋势，只看谁能成为最后的标准

为的是解决动态链接和关联依赖,这个在Linux中几乎会让人崩溃的应用安装障碍.但大多数时候,这个问题正在被各大发行版处理的越来越好.有了snap和flatpak的出现,又多了一种选择,总是幸福的,但不希望是唯一的选项.这并不是我希望看到的,虽然我的发声可能于事无补,但我要发出自己的声音.这就是开源的意义.

![](/data/attachment/album/201609/17/230943wvgur99cvbpvcec9.jpg)

**对新一代的打包格式开始渗透到 Linux 生态系统中的深入观察**

最近我们听到越来越多的有关于 Ubuntu 的 Snap 包和由 Red Hat 员工 Alexander Larsson 创造的 Flatpak （曾经叫做 xdg-app）的消息。

这两种下一代打包方法在本质上拥有相同的目标和特点：即不依赖于第三方系统功能库的独立包装。

这种 Linux 新技术方向似乎自然会让人脑海中浮现这样的问题：独立包的优点/缺点是什么？这是否让我们拥有更好的 Linux 系统？其背后的动机是什么？

为了回答这些问题，让我们先深入了解一下 Snap 和 Flatpak。

### 动机

根据 [Flatpak](http://flatpak.org/press/2016-06-21-flatpak-released.html) 和 [Snap](https://insights.ubuntu.com/2016/06/14/universal-snap-packages-launch-on-multiple-linux-distros) 的声明，背后的主要动机是使同一版本的应用程序能够运行在多个 Linux 发行版。

>
> “从一开始它的主要目标是允许相同的应用程序运行在各种 Linux 发行版和操作系统上。” —— Flatpak
>
>
>

>
> “……‘snap’ 通用 Linux 包格式，使简单的二进制包能够完美的、安全的运行在任何 Linux 桌面、服务器、云和设备上。” —— Snap
>
>
>

说得更具体一点，站在 Snap 和 Flatpak （以下称之为 S&F）背后的人认为，Linux 平台存在碎片化的问题。

这个问题导致了开发者们需要做许多不必要的工作来使他的软件能够运行在各种不同的发行版上，这影响了整个平台的前进。

所以，作为 Linux 发行版（Ubuntu 和 Red Hat）的领导者，他们希望消除这个障碍，推动平台发展。

但是，是否是更多的个人收益刺激了 S&F 的开发？

#### 个人收益？

虽然没有任何官方声明，但是试想一下，如果能够创造这种可能会被大多数发行版（即便不是全部）所采用的打包方式，那么这个项目的领导者将可能成为一个能够决定 Linux 大船航向的重要人物。

### 优势

这种独立包的好处多多，并且取决于不同的因素。

这些因素基本上可以归为两类：

#### 用户角度

**+** 从 Liunx 用户的观点来看：Snap 和 Flatpak 带来了将任何软件包（软件或应用）安装在用户使用的任何发行版上的可能性。

例如你在使用一个不是很流行的发行版，由于开发工作的缺乏，它的软件仓库只有很稀少的包。现在，通过 S&F 你就可以显著的增加包的数量，这是一个多么美好的事情。

**+** 同样，对于使用流行的发行版的用户，即使该发行版的软件仓库上有很多的包，他也可以在不改变它现有的功能库的同时安装一个新的包。

比方说, 一个 Debian 的用户想要安装一个 “测试分支” 的包，但是他又不想将他的整个系统变成测试版（来让该包运行在更新的功能库上）。现在，他就可以简单的想安装哪个版本就安装哪个版本，而不需要考虑库的问题。

对于持后者观点的人，可能基本上都是使用源文件编译他们的包的人，然而，除非你使用类似 Gentoo 这样基于源代码的发行版，否则大多数用户将从头编译视为是一个恶心到吐的事情。

**+** 高级用户，或者称之为 “拥有安全意识的用户” 可能会觉得更容易接受这种类型的包，只要它们来自可靠来源，这种包倾向于提供另一层隔离，因为它们通常是与系统包想隔离的。

\* 不论是 Snap 还是 Flatpak 都在不断努力增强它们的安全性，通常他们都使用 “沙盒化” 来隔离，以防止它们可能携带病毒感染整个系统，就像微软 Windows 系统中的 .exe 程序一样。（关于微软和 S&F 后面还会谈到）

#### 开发者角度

与普通用户相比，对于开发者来说，开发 S&F 包的优点可能更加清楚。这一点已经在上一节有所提示。

尽管如此，这些优点有：

**+** S&F 通过统一开发的过程，将多发行版的开发变得简单了起来。对于需要将他的应用运行在多个发行版的开发者来说，这大大的减少了他们的工作量。

**++** 因此，开发者能够更容易的使他的应用运行在更多的发行版上。

**+** S&F 允许开发者私自发布他的包，不需要依靠发行版维护者在每一个/每一次发行版中发布他的包。

**++** 通过上述方法，开发者可以不依赖发行版而直接获取到用户安装和卸载其软件的统计数据。

**++** 同样是通过上述方法，开发者可以更好的直接与用户互动，而不需要通过中间媒介，比如发行版这种中间媒介。

### 缺点

**–** 膨胀。就是这么简单。Flatpak 和 Snap 并不是凭空变出来它的依赖关系。相反，它是通过将依赖关系预构建在其中来代替使用系统中的依赖关系。

就像谚语说的：“山不来就我，我就去就山”。

**–** 之前提到安全意识强的用户会喜欢 S&F 提供的额外的一层隔离，只要该应用来自一个受信任的来源。但是从另外一个角度看，对这方面了解较少的用户，可能会从一个不靠谱的地方弄来一个包含恶意软件的包从而导致危害。

上面提到的观点可以说是有很有意义的，虽说今天的流行方法，像 PPA、overlay 等也可能是来自不受信任的来源。

但是，S&F 包更加增加这个风险，因为恶意软件开发者只需要开发一个版本就可以感染各种发行版。相反，如果没有 S&F，恶意软件的开发者就需要创建不同的版本以适应不同的发行版。

### 原来微软一直是正确的吗？

考虑到上面提到的，很显然，在大多数情况下，使用 S&F 包的优点超过缺点。

至少对于二进制发行版的用户，或者重点不是轻量级的发行版的用户来说是这样的。

这促使我问出这个问题，可能微软一直是正确的吗？如果是的，那么当 S&F 变成 Linux 的标准后，你还会一如既往的使用 Linux 或者类 Unix 系统吗？

很显然，时间会是这个问题的最好答案。

不过，我认为，即使不完全正确，但是微软有些地方也是值得赞扬的，并且以我的观点来看，所有这些方式在 Linux 上都立马能用也确实是一个亮点。

---

via: <http://www.iwillfolo.com/ubuntus-snap-red-hats-flatpack-and-is-one-fits-all-linux-packages-useful/>

作者：Liron 译者：[Chao-zhi](https://github.com/Chao-zhi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译，[Linux中国](https://linux.cn/) 荣誉推出


使用 Python 和 Asyncio 编写在线多用人游戏（二）

asyncio看不懂怎么用的，新模块

我选择js

![](/data/attachment/album/201609/18/114551xlyhloh0lxxcy9yn.jpg)

>
> 你在 Python 中用过异步编程吗？本文中我会告诉你怎样做，而且用一个[能工作的例子](http://snakepit-game.com/)来展示它：这是一个流行的贪吃蛇游戏，而且是为多人游戏而设计的。
>
>
>

介绍和理论部分参见“[第一部分 异步化](/article-7767-1.html)”。

* [游戏入口在此，点此体验](http://snakepit-game.com/)。

![](/data/attachment/album/201609/18/114717vzjjb8ryymlrsyng.gif)

### 3、编写游戏循环主体

游戏循环是每一个游戏的核心。它持续地运行以读取玩家的输入、更新游戏的状态，并且在屏幕上渲染游戏结果。在在线游戏中，游戏循环分为客户端和服务端两部分，所以一般有两个循环通过网络通信。通常客户端的角色是获取玩家输入，比如按键或者鼠标移动，将数据传输给服务端，然后接收需要渲染的数据。服务端处理来自玩家的所有数据，更新游戏的状态，执行渲染下一帧的必要计算，然后将结果传回客户端，例如游戏中对象的新位置。如果没有可靠的理由，不混淆客户端和服务端的角色是一件很重要的事。如果你在客户端执行游戏逻辑的计算，很容易就会和其它客户端失去同步，其实你的游戏也可以通过简单地传递客户端的数据来创建。

>
> 游戏循环的一次迭代称为一个<ruby> 嘀嗒 <rp>  （ </rp> <rt>  tick </rt> <rp>  ） </rp></ruby>。嘀嗒是一个事件，表示当前游戏循环的迭代已经结束，下一帧（或者多帧）的数据已经就绪。
>
>
>

在后面的例子中，我们使用相同的客户端，它使用 WebSocket 从一个网页上连接到服务端。它执行一个简单的循环，将按键码发送给服务端，并显示来自服务端的所有信息。[客户端代码戳这里](https://github.com/7WebPages/snakepit-game/blob/master/simple/index.html)。

#### 例子 3.1：基本游戏循环

* [例子 3.1 源码](https://github.com/7WebPages/snakepit-game/blob/master/simple/game_loop_basic.py)。

我们使用 [aiohttp](http://aiohttp.readthedocs.org/) 库来创建游戏服务器。它可以通过 asyncio 创建网页服务器和客户端。这个库的一个优势是它同时支持普通 http 请求和 websocket。所以我们不用其他网页服务器来渲染游戏的 html 页面。

下面是启动服务器的方法：

```
app = web.Application()
app["sockets"] = []

asyncio.ensure_future(game_loop(app))

app.router.add_route('GET', '/connect', wshandler)
app.router.add_route('GET', '/', handle)

web.run_app(app)

```

`web.run_app` 是创建服务主任务的快捷方法，通过它的 `run_forever()` 方法来执行 `asyncio` 事件循环。建议你查看这个方法的源码，弄清楚服务器到底是如何创建和结束的。

`app` 变量就是一个类似于字典的对象，它用于在所连接的客户端之间共享数据。我们使用它来存储连接的套接字的列表。随后会用这个列表来给所有连接的客户端发送消息。`asyncio.ensure_future()` 调用会启动主游戏循环的任务，每隔2 秒向客户端发送嘀嗒消息。这个任务会在同样的 asyncio 事件循环中和网页服务器并行执行。

有两个网页请求处理器：`handle` 是提供 html 页面的处理器；`wshandler` 是主要的 websocket 服务器任务，处理和客户端之间的交互。在事件循环中，每一个连接的客户端都会创建一个新的 `wshandler` 任务。这个任务会添加客户端的套接字到列表中，以便 `game_loop` 任务可以给所有的客户端发送消息。然后它将随同消息回显客户端的每个击键。

在启动的任务中，我们在 `asyncio` 的主事件循环中启动 worker 循环。任务之间的切换发生在它们之间任何一个使用 `await`语句来等待某个协程结束时。例如 `asyncio.sleep` 仅仅是将程序执行权交给调度器一段指定的时间；`ws.receive` 等待 websocket 的消息，此时调度器可能切换到其它任务。

在浏览器中打开主页，连接上服务器后，试试随便按下键。它们的键值会从服务端返回，每隔 2 秒这个数字会被游戏循环中发给所有客户端的嘀嗒消息所覆盖。

我们刚刚创建了一个处理客户端按键的服务器，主游戏循环在后台做一些处理，周期性地同时更新所有的客户端。

#### 例子 3.2: 根据请求启动游戏

* [例子 3.2 的源码](https://github.com/7WebPages/snakepit-game/blob/master/simple/game_loop_handler.py)

在前一个例子中，在服务器的生命周期内，游戏循环一直运行着。但是现实中，如果没有一个人连接服务器，空运行游戏循环通常是不合理的。而且，同一个服务器上可能有不同的“游戏房间”。在这种假设下，每一个玩家“创建”一个游戏会话（比如说，多人游戏中的一个比赛或者大型多人游戏中的副本），这样其他用户可以加入其中。当游戏会话开始时，游戏循环才开始执行。

在这个例子中，我们使用一个全局标记来检测游戏循环是否在执行。当第一个用户发起连接时，启动它。最开始，游戏循环没有执行，标记设置为 `False`。游戏循环是通过客户端的处理方法启动的。

```
  if app["game_is_running"] == False:
        asyncio.ensure_future(game_loop(app))

```

当 `game_loop()` 运行时，这个标记设置为 `True`；当所有客户端都断开连接时，其又被设置为 `False`。

#### 例子 3.3：管理任务

* [例子3.3源码](https://github.com/7WebPages/snakepit-game/blob/master/simple/game_loop_global.py)

这个例子用来解释如何和任务对象协同工作。我们把游戏循环的任务直接存储在游戏循环的全局字典中，代替标记的使用。在像这样的一个简单例子中并不一定是最优的，但是有时候你可能需要控制所有已经启动的任务。

```
    if app["game_loop"] is None or \
       app["game_loop"].cancelled():
        app["game_loop"] = asyncio.ensure_future(game_loop(app))

```

这里 `ensure_future()` 返回我们存放在全局字典中的任务对象，当所有用户都断开连接时，我们使用下面方式取消任务：

```
    app["game_loop"].cancel()

```

这个 `cancel()` 调用将通知调度器不要向这个协程传递执行权，而且将它的状态设置为已取消：`cancelled`，之后可以通过 `cancelled()` 方法来检查是否已取消。这里有一个值得一提的小注意点：当你持有一个任务对象的外部引用时，而这个任务执行中发生了异常，这个异常不会抛出。取而代之的是为这个任务设置一个异常状态，可以通过 `exception()` 方法来检查是否出现了异常。这种悄无声息地失败在调试时不是很有用。所以，你可能想用抛出所有异常来取代这种做法。你可以对所有未完成的任务显式地调用 `result()` 来实现。可以通过如下的回调来实现：

```
    app["game_loop"].add_done_callback(lambda t: t.result())

```

如果我们打算在我们代码中取消这个任务，但是又不想产生 `CancelError` 异常，有一个检查 `cancelled` 状态的点：

```
    app["game_loop"].add_done_callback(lambda t: t.result()
                                       if not t.cancelled() else None)

```

注意仅当你持有任务对象的引用时才需要这么做。在前一个例子，所有的异常都是没有额外的回调，直接抛出所有异常。

#### 例子 3.4：等待多个事件

* [例子 3.4 源码](https://github.com/7WebPages/snakepit-game/blob/master/simple/game_loop_wait.py)

在许多场景下，在客户端的处理方法中你需要等待多个事件的发生。除了来自客户端的消息，你可能需要等待不同类型事件的发生。比如，如果你的游戏时间有限制，那么你可能需要等一个来自定时器的信号。或者你需要使用管道来等待来自其它进程的消息。亦或者是使用分布式消息系统的网络中其它服务器的信息。

为了简单起见，这个例子是基于例子 3.1。但是这个例子中我们使用 `Condition` 对象来与已连接的客户端保持游戏循环的同步。我们不保存套接字的全局列表，因为只在该处理方法中使用套接字。当游戏循环停止迭代时，我们使用 `Condition.notify_all()` 方法来通知所有的客户端。这个方法允许在 `asyncio` 的事件循环中使用发布/订阅的模式。

为了等待这两个事件，首先我们使用 `ensure_future()` 来封装任务中这个可等待对象。

```
    if not recv_task:
        recv_task = asyncio.ensure_future(ws.receive())
    if not tick_task:
        await tick.acquire()
        tick_task = asyncio.ensure_future(tick.wait())

```

在我们调用 `Condition.wait()` 之前，我们需要在它后面获取一把锁。这就是我们为什么先调用 `tick.acquire()` 的原因。在调用 `tick.wait()` 之后，锁会被释放，这样其他的协程也可以使用它。但是当我们收到通知时，会重新获取锁，所以在收到通知后需要调用 `tick.release()` 来释放它。

我们使用 `asyncio.wait()` 协程来等待两个任务。

```
    done, pending = await asyncio.wait(
        [recv_task,
         tick_task],
        return_when=asyncio.FIRST_COMPLETED)

```

程序会阻塞，直到列表中的任意一个任务完成。然后它返回两个列表：执行完成的任务列表和仍然在执行的任务列表。如果任务执行完成了，其对应变量赋值为 `None`，所以在下一个迭代时，它可能会被再次创建。

#### 例子 3.5： 结合多个线程

* [例子 3.5 源码](https://github.com/7WebPages/snakepit-game/blob/master/simple/game_loop_thread.py)

在这个例子中，我们结合 `asyncio` 循环和线程，在一个单独的线程中执行主游戏循环。我之前提到过，由于 `GIL` 的存在，Python 代码的真正并行执行是不可能的。所以使用其它线程来执行复杂计算并不是一个好主意。然而，在使用 `asyncio` 时结合线程有原因的：当我们使用的其它库不支持 `asyncio` 时就需要。在主线程中调用这些库会阻塞循环的执行，所以异步使用他们的唯一方法是在不同的线程中使用他们。

我们使用 `asyncio` 循环的`run_in_executor()` 方法和 `ThreadPoolExecutor` 来执行游戏循环。注意 `game_loop()` 已经不再是一个协程了。它是一个由其它线程执行的函数。然而我们需要和主线程交互，在游戏事件到来时通知客户端。`asyncio` 本身不是线程安全的，它提供了可以在其它线程中执行你的代码的方法。普通函数有 `call_soon_threadsafe()`，协程有 `run_coroutine_threadsafe()`。我们在 `notify()` 协程中增加了通知客户端游戏的嘀嗒的代码，然后通过另外一个线程执行主事件循环。

```
def game_loop(asyncio_loop):
    print("Game loop thread id {}".format(threading.get_ident()))
    async def notify():
        print("Notify thread id {}".format(threading.get_ident()))
        await tick.acquire()
        tick.notify_all()
        tick.release()

    while 1:
        task = asyncio.run_coroutine_threadsafe(notify(), asyncio_loop)
        # blocking the thread
        sleep(1)
        # make sure the task has finished
        task.result()

```

当你执行这个例子时，你会看到 “Notify thread id” 和 “Main thread id” 相等，因为 `notify()` 协程在主线程中执行。与此同时 `sleep(1)` 在另外一个线程中执行，因此它不会阻塞主事件循环。

#### 例子 3.6：多进程和扩展

* [例子 3.6 源码](https://github.com/7WebPages/snakepit-game/blob/master/simple/game_loop_process.py)

单线程的服务器可能运行得很好，但是它只能使用一个 CPU 核。为了将服务扩展到多核，我们需要执行多个进程，每个进程执行各自的事件循环。这样我们需要在进程间交互信息或者共享游戏的数据。而且在一个游戏中经常需要进行复杂的计算，例如路径查找之类。这些任务有时候在一个游戏嘀嗒中没法快速完成。在协程中不推荐进行费时的计算，因为它会阻塞事件的处理。在这种情况下，将这个复杂任务交给其它并行执行的进程可能更合理。

最简单的使用多个核的方法是启动多个使用单核的服务器，就像之前的例子中一样，每个服务器占用不同的端口。你可以使用 `supervisord` 或者其它进程控制的系统。这个时候你需要一个像 `HAProxy` 这样的负载均衡器，使得连接的客户端分布在多个进程间。已经有一些可以连接 asyncio 和一些流行的消息及存储系统的适配系统。例如：

* [aiomcache](https://github.com/aio-libs/aiomcache) 用于 memcached 客户端
* [aiozmq](https://github.com/aio-libs/aiozmq) 用于 zeroMQ
* [aioredis](https://github.com/aio-libs/aioredis) 用于 Redis 存储，支持发布/订阅

你可以在 github 或者 pypi 上找到其它的软件包，大部分以 `aio` 开头。

使用网络服务在存储持久状态和交换某些信息时可能比较有效。但是如果你需要进行进程间通信的实时处理，它的性能可能不足。此时，使用标准的 unix 管道可能更合适。`asyncio` 支持管道，在`aiohttp`仓库有个 [使用管道的服务器的非常底层的例子](https://github.com/KeepSafe/aiohttp/blob/master/examples/mpsrv.py)。

在当前的例子中，我们使用 Python 的高层类库 [multiprocessing](https://docs.python.org/3.5/library/multiprocessing.html) 来在不同的核上启动复杂的计算，使用 `multiprocessing.Queue` 来进行进程间的消息交互。不幸的是，当前的 `multiprocessing` 实现与 `asyncio` 不兼容。所以每一个阻塞方法的调用都会阻塞事件循环。但是此时线程正好可以起到帮助作用，因为如果在不同线程里面执行 `multiprocessing` 的代码，它就不会阻塞主线程。所有我们需要做的就是把所有进程间的通信放到另外一个线程中去。这个例子会解释如何使用这个方法。和上面的多线程例子非常类似，但是我们从线程中创建的是一个新的进程。

```
def game_loop(asyncio_loop):
    # coroutine to run in main thread
    async def notify():
        await tick.acquire()
        tick.notify_all()
        tick.release()

    queue = Queue()

    # function to run in a different process
    def worker():
        while 1:
            print("doing heavy calculation in process {}".format(os.getpid()))
            sleep(1)
            queue.put("calculation result")

    Process(target=worker).start()

    while 1:
        # blocks this thread but not main thread with event loop
        result = queue.get()
        print("getting {} in process {}".format(result, os.getpid()))
        task = asyncio.run_coroutine_threadsafe(notify(), asyncio_loop)
        task.result()

```

这里我们在另外一个进程中运行 `worker()` 函数。它包括一个执行复杂计算并把计算结果放到 `queue` 中的循环，这个 `queue` 是 `multiprocessing.Queue` 的实例。然后我们就可以在另外一个线程的主事件循环中获取结果并通知客户端，就和例子 3.5 一样。这个例子已经非常简化了，它没有合理的结束进程。而且在真实的游戏中，我们可能需要另外一个队列来将数据传递给 `worker`。

有一个项目叫 [aioprocessing](https://github.com/dano/aioprocessing)，它封装了 `multiprocessing`，使得它可以和 `asyncio` 兼容。但是实际上它只是和上面例子使用了完全一样的方法：从线程中创建进程。它并没有给你带来任何方便，除了它使用了简单的接口隐藏了后面的这些技巧。希望在 Python 的下一个版本中，我们能有一个基于协程且支持 `asyncio` 的 `multiprocessing` 库。

>
> 注意！如果你从主线程或者主进程中创建了一个不同的线程或者子进程来运行另外一个 `asyncio` 事件循环，你需要显式地使用 `asyncio.new_event_loop()` 来创建循环，不然的话可能程序不会正常工作。
>
>
>

---

via: <https://7webpages.com/blog/writing-online-multiplayer-game-with-python-and-asyncio-writing-game-loop/>

作者：[Kyrylo Subbotin](https://7webpages.com/blog/writing-online-multiplayer-game-with-python-and-asyncio-writing-game-loop/) 译者：[chunyang-wen](https://github.com/chunyang-wen) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

（题图来自：[deviantart.com](http://azany.deviantart.com/art/Griffin-dawn-294055220)）


旅行时通过树莓派和 iPad Pro 备份图片

Summary: 我在很长的时间内一直在寻找一个旅行中备份图片的理想方法，把 SD 卡放进你的相机包会让你暴露在太多的风险之中。

我怎么觉得这个作者是闲的全身到处都在疼？？？

SD卡直接插到Surface pro不就得了，最多写个程序，自动识别自动复制。。。

带个iPad pro那么大个不嫌累，还加个树莓派+电池，还带读卡器这些一堆没用的。。累不累，还是闲得慌？

真蛋疼~

作者傻鸟，把简单的事情想复杂了，一台支持 OTG 的安卓设备，或者一台 windows 10 平板，就能很好地解决问题。<br />
最重要的是：相机别丢。这才是王道。

![](/data/attachment/album/201609/18/152757u15q711z5v5sd5w3.jpg)

*旅行中备份图片 - 组件*

### 介绍

我在很长的时间内一直在寻找一个旅行中备份图片的理想方法，把 SD 卡放进你的相机包会让你暴露在太多的风险之中：SD 卡可能丢失或者被盗，数据可能损坏或者在传输过程中失败。比较好的一个选择是复制到另外一个介质中，即使它也是个 SD 卡，并且将它放到一个比较安全的地方去，备份到远端也是一个可行的办法，但是如果去了一个没有网络的地方就不太可行了。

我理想的备份步骤需要下面的工具:

1. 用一台 iPad pro 而不是一台笔记本。我喜欢轻装旅行，我的大部分旅程都是商务相关的（而不是拍摄休闲的），我痛恨带着个人笔记本的时候还得带着商务本。而我的 iPad 却一直带着，这就是我为什么选择它的原因。
2. 用尽可能少的硬件设备。
3. 设备之间的连接需要很安全。我需要在旅馆和机场使用这套设备，所以设备之间的连接需要是封闭而加密的。
4. 整个过程应该是可靠稳定的，我还用过其他的路由器/组合设备，但是[效果不太理想](http://bit.ly/1MVVtZi)。

### 设备

我配置了一套满足上面条件并且在未来可以扩充的设备，它包含下面这些部件的使用:

1. [9.7 英寸的 iPad Pro](http://www.amazon.com/dp/B01D3NZIMA/?tag=movinelect0e-20)，这是本文写作时最强大、轻薄的 iOS 设备，苹果笔不是必需的，但是作为零件之一，当我在路上可以做一些编辑工作，所有的重活由树莓派做 ，其他设备只能通过 SSH 连接就行。
2. 安装了 Raspbian 操作系统[树莓派 3](http://www.amazon.com/dp/B01CD5VC92/?tag=movinelect0e-20)（LCTT 译注：Raspbian 是基于 Debian 的树莓派操作系统）。
3. 树莓派的 [Mini SD卡](http://www.amazon.com/dp/B010Q57T02/?tag=movinelect0e-20) 和 [盒子/外壳](http://www.amazon.com/dp/B01F1PSFY6/?tag=movinelect0e-20)。
4. [128G 的优盘](http://amzn.to/293kPqX)，对于我是够用了，你可以买个更大的。你也可以买个像[这样](http://amzn.to/290syFY)的移动硬盘，但是树莓派没法通过 USB 给移动硬盘提供足够的电量，这意味你需要额外准备一个[供电的 USB hub](http://amzn.to/290syFY) 以及电缆，这就破坏了我们让设备轻薄的初衷。
5. [SD 读卡器](http://amzn.to/290syFY)
6. [另外的 SD 卡](http://amzn.to/290syFY)，我会使用几个 SD 卡，在用满之前就会立即换一个，这样就会让我在一次旅途当中的照片散布在不同的 SD 卡上。

下图展示了这些设备之间如何相互连接。

![](/data/attachment/album/201609/18/152637hhmiflhfwy262hmf.jpg)

*旅行时照片的备份-流程图*

树莓派会作为一个安全的热点。它会创建一个自己的 WPA2 加密的 WIFI 网络，iPad Pro 会连入其中。虽然有很多在线教程教你如何创建 Ad Hoc 网络（计算机到计算机的单对单网络），还更简单一些，但是它的连接是不加密的，而且附件的设备很容易就能连接进去。因此我选择创建 WIFI 网络。

相机的 SD 卡通过 SD 读卡器插到树莓派 USB 端口之一，128G 的大容量优盘一直插在树莓派的另外一个 USB 端口上，我选择了一款[闪迪的](http://amzn.to/293kPqX)，因为体积比较小。主要的思路就是通过 Python 脚本把 SD 卡的照片备份到优盘上，备份过程是增量备份，每次脚本运行时都只有变化的（比如新拍摄的照片）部分会添加到备份文件夹中，所以这个过程特别快。如果你有很多的照片或者拍摄了很多 RAW 格式的照片，在就是个巨大的优势。iPad 将用来运行 Python 脚本，而且用来浏览 SD 卡和优盘的文件。

作为额外的好处，如果给树莓派连上一根能上网的网线（比如通过以太网口），那么它就可以共享互联网连接给那些通过 WIFI 连入的设备。

### 1. 树莓派的设置

这部分需要你卷起袖子亲自动手了，我们要用到 Raspbian 的命令行模式，我会尽可能详细的介绍，方便大家进行下去。

#### 安装和配置 Raspbian

给树莓派连接鼠标、键盘和 LCD 显示器，将 SD 卡插到树莓派上，按照[树莓派官网](https://www.raspberrypi.org/downloads/noobs/)的步骤安装 Raspbian。

安装完后，打开 Raspbian 的终端，执行下面的命令:

```
sudo apt-get update
sudo apt-get upgrade

```

这将升级机器上所有的软件到最新，我将树莓派连接到本地网络，而且为了安全更改了默认的密码。

Raspbian 默认开启了 SSH，这样所有的设置可以在一个远程的设备上完成。我也设置了 RSA 验证，但这是可选的功能，可以在[这里](https://www.raspberrypi.org/documentation/remote-access/ssh/passwordless.md)查看更多信息。

这是一个在 Mac 上在 [iTerm](https://www.iterm2.com/) 里建立 SSH 连接到树莓派上的截图[14](https://www.iterm2.com/)。（LCTT 译注：原文图丢失。）

#### 建立 WPA2 加密的 WIFI AP

安装过程基于[这篇文章](https://frillip.com/using-your-raspberry-pi-3-as-a-wifi-access-point-with-hostapd/)，根据我的情况进行了调整。

**1. 安装软件包**

我们需要安装下面的软件包：

```
sudo apt-get install hostapd
sudo apt-get install dnsmasq

```

hostapd 用来使用内置的 WiFi 来创建 AP，dnsmasp 是一个组合的 DHCP 和 DNS 服务其，很容易设置。

**2. 编辑 dhcpcd.conf**

通过以太网连接树莓派，树莓派上的网络接口配置由 `dhcpd` 控制，因此我们首先忽略这一点，将 `wlan0` 设置为一个静态的 IP。

用 `sudo nano /etc/dhcpcd.conf` 命令打开 dhcpcd 的配置文件，在最后一行添加上如下内容：

```
denyinterfaces wlan0

```

注意：它必须放在如果已经有的其它接口行**之上**。

**3. 编辑接口**

现在设置静态 IP，使用 `sudo nano /etc/network/interfaces` 打开接口配置文件，按照如下信息编辑`wlan0`部分：

```
allow-hotplug wlan0
iface wlan0 inet static
    address 192.168.1.1
    netmask 255.255.255.0
    network 192.168.1.0
    broadcast 192.168.1.255
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

```

同样，然后 `wlan1` 编辑如下：

```
#allow-hotplug wlan1
#iface wlan1 inet manual
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

```

重要： 使用 `sudo service dhcpcd restart` 命令重启 `dhcpd`服务，然后用 `sudo ifdown eth0; sudo ifup wlan0` 命令来重载`wlan0`的配置。

**4. 配置 Hostapd**

接下来，我们需要配置 hostapd，使用 `sudo nano /etc/hostapd/hostapd.conf` 命令创建一个新的配置文件，内容如下：

```
interface=wlan0

# Use the nl80211 driver with the brcmfmac driver
driver=nl80211

# This is the name of the network
ssid=YOUR_NETWORK_NAME_HERE

# Use the 2.4GHz band
hw_mode=g

# Use channel 6
channel=6

# Enable 802.11n
ieee80211n=1

# Enable QoS Support
wmm_enabled=1

# Enable 40MHz channels with 20ns guard interval
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]

# Accept all MAC addresses
macaddr_acl=0

# Use WPA authentication
auth_algs=1

# Require clients to know the network name
ignore_broadcast_ssid=0

# Use WPA2
wpa=2

# Use a pre-shared key
wpa_key_mgmt=WPA-PSK

# The network passphrase
wpa_passphrase=YOUR_NEW_WIFI_PASSWORD_HERE

# Use AES, instead of TKIP
rsn_pairwise=CCMP

```

配置完成后，我们需要告诉`dhcpcd` 在系统启动运行时到哪里寻找配置文件。 使用 `sudo nano /etc/default/hostapd` 命令打开默认配置文件，然后找到`#DAEMON_CONF=""` 替换成`DAEMON_CONF="/etc/hostapd/hostapd.conf"`。

**5. 配置 Dnsmasq**

自带的 dnsmasp 配置文件包含很多信息方便你使用它，但是我们不需要那么多选项，我建议把它移动到别的地方（而不要删除它），然后自己创建一个新文件：

```
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo nano /etc/dnsmasq.conf

```

粘贴下面的信息到新文件中：

```
interface=wlan0      # Use interface wlan0
listen-address=192.168.1.1 # Explicitly specify the address to listen on
bind-interfaces      # Bind to the interface to make sure we aren't sending things elsewhere
server=8.8.8.8       # Forward DNS requests to Google DNS
domain-needed        # Don't forward short names
bogus-priv           # Never forward addresses in the non-routed address spaces.
dhcp-range=192.168.1.50,192.168.1.100,12h # Assign IP addresses in that range  with a 12 hour lease time

```

**6. 设置 IPv4 转发**

最后我们需要做的事就是配置包转发，用 `sudo nano /etc/sysctl.conf` 命令打开 `sysctl.conf` 文件，将包含 `net.ipv4.ip_forward=1`的那一行之前的#号删除，它将在下次重启时生效。

我们还需要给连接到树莓派的设备通过 WIFI 分享互联网连接，做一个 `wlan0`和 `eth0` 之间的 NAT。我们可以参照下面的脚本来实现。

```
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

```

我命名这个脚本名为 `hotspot-boot.sh`，然后让它可以执行：

```
sudo chmod 755 hotspot-boot.sh

```

该脚本应该在树莓派启动的时候运行。有很多方法实现，下面是我实现的方式：

1. 把文件放到`/home/pi/scripts`目录下。
2. 输入`sudo nano /etc/rc.local`命令编辑 `rc.local` 文件，将运行该脚本的命令放到 `exit 0`之前。（更多信息参照[这里](https://www.raspberrypi.org/documentation/linux/usage/rc-local.md)）。

编辑后`rc.local`看起来像这样：

```
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

sudo /home/pi/scripts/hotspot-boot.sh &

exit 0

```

#### 安装 Samba 服务和 NTFS 兼容驱动

我们要安装下面几个软件来启用 samba 协议，使[文件浏览器](https://itunes.apple.com/us/app/filebrowser-access-files-on/id364738545?mt=8&uo=4&at=11lqkH)能够访问树莓派分享的文件夹，`ntfs-3g` 可以使我们能够访问移动硬盘中 ntfs 文件系统的文件。

```
sudo apt-get install ntfs-3g
sudo apt-get install samba samba-common-bin

```

你可以参照[这些文档](http://www.howtogeek.com/139433/how-to-turn-a-raspberry-pi-into-a-low-power-network-storage-device/)来配置 Samba。

重要提示：参考的文档介绍的是挂载外置硬盘到树莓派上，我们不这样做，是因为在这篇文章写作的时候，树莓派在启动时的 auto-mounts 功能同时将 SD 卡和优盘挂载到`/media/pi/`上，该文章有一些多余的功能我们也不会采用。

### 2. Python 脚本

树莓派配置好后，我们需要开发脚本来实际拷贝和备份照片。注意，这个脚本只是提供了特定的自动化备份进程，如果你有基本的 Linux/树莓派命令行操作的技能，你可以 ssh 进树莓派，然后创建需要的文件夹，使用`cp`或`rsync`命令拷贝你自己的照片从一个设备到另外一个设备上。在脚本里我们用`rsync`命令，这个命令比较可靠而且支持增量备份。

这个过程依赖两个文件，脚本文件自身和`backup_photos.conf`这个配置文件，后者只有几行包含被挂载的目的驱动器（优盘）和应该挂载到哪个目录，它看起来是这样的：

```
mount folder=/media/pi/
destination folder=PDRIVE128GB

```

重要提示：在这个符号`=`前后不要添加多余的空格，否则脚本会失效。

下面是这个 Python 脚本，我把它命名为`backup_photos.py`，把它放到了`/home/pi/scripts/`目录下，我在每行都做了注释可以方便的查看各行的功能。

```
#!/usr/bin/python3

import os
import sys
from sh import rsync

'''
脚本将挂载到 /media/pi 的 SD 卡上的内容复制到目的磁盘的同名目录下，目的磁盘的名字在 .conf文件里定义好了。

Argument:  label/name of the mounted SD Card.
'''

CONFIG_FILE = '/home/pi/scripts/backup_photos.conf'
ORIGIN_DEV = sys.argv[1]

def create_folder(path):

    print ('attempting to create destination folder: ',path)
    if not os.path.exists(path):
        try:
            os.mkdir(path)
            print ('Folder created.')
        except:
            print ('Folder could not be created. Stopping.')
            return
    else:
        print ('Folder already in path. Using that instead.')

confFile = open(CONFIG_FILE,'rU')
#重要：: rU 选项将以统一换行模式打开文件，
#所以 \n 和/或 \r 都被识别为一个新行。

confList = confFile.readlines()
confFile.close()

for line in confList:
    line = line.strip('\n')

    try:
        name , value = line.split('=')

        if name == 'mount folder':
            mountFolder = value
        elif name == 'destination folder':
            destDevice = value

    except ValueError:
        print ('Incorrect line format. Passing.')
        pass

destFolder = mountFolder+destDevice+'/'+ORIGIN_DEV
create_folder(destFolder)

print ('Copying files...')

# 取消这行备注将删除不在源处的文件
# rsync("-av", "--delete", mountFolder+ORIGIN_DEV, destFolder)
rsync("-av", mountFolder+ORIGIN_DEV+'/', destFolder)

print ('Done.')

```

### 3. iPad Pro 的配置

因为重活都由树莓派干了，文件不通过 iPad Pro 传输，这比我[之前尝试的一种方案](http://bit.ly/1MVVtZi)有巨大的优势。我们在 iPad 上只需要安装上 [Prompt2](https://itunes.apple.com/us/app/prompt-2/id917437289?mt=8&uo=4&at=11lqkH) 来通过 SSH 连接树莓派就行了，这样你既可以运行 Python 脚本也可以手动复制文件了。

![](/data/attachment/album/201609/18/152830zhhhhr6jxje8rh38.jpg)

*iPad 用 Prompt2 通过 SSH 连接树莓派*

因为我们安装了 Samba，我们可以以更图形化的方式访问连接到树莓派的 USB 设备，你可以看视频，在不同的设备之间复制和移动文件，[文件浏览器](https://itunes.apple.com/us/app/filebrowser-access-files-on/id364738545?mt=8&uo=4&at=11lqkH)对于这种用途非常完美。（LCTT 译注：原文视频丢失。）

### 4. 将它们结合在一起

我们假设`SD32GB-03`是连接到树莓派 USB 端口之一的 SD 卡的卷标，`PDRIVE128GB`是那个优盘的卷标，也连接到设备上，并在上面指出的配置文件中定义好。如果我们想要备份 SD 卡上的图片，我们需要这么做：

1. 给树莓派加电打开，将驱动器自动挂载好。
2. 连接树莓派配置好的 WIFI 网络。
3. 用 [Prompt2](https://itunes.apple.com/us/app/prompt-2/id917437289?mt=8&uo=4&at=11lqkH) 这个 app 通过 SSH 连接到树莓派。
4. 连接好后输入下面的命令：`python3 backup_photos.py SD32GB-03`

首次备份需要一些时间，这依赖于你的 SD 卡使用了多少容量。这意味着你需要一直保持树莓派和 iPad 设备连接不断，你可以在脚本运行之前通过 `nohup` 命令解决：

```
nohup python3 backup_photos.py SD32GB-03 &

```

![](/data/attachment/album/201609/18/152845q29bz0nll0ouhlut.png)

*运行完成的脚本如图所示*

### 未来的定制

我在树莓派上安装了 vnc 服务，这样我可以通过其它计算机或在 iPad 上用 [Remoter App](https://itunes.apple.com/us/app/remoter-pro-vnc-ssh-rdp/id519768191?mt=8&uo=4&at=11lqkH)连接树莓派的图形界面，我安装了 [BitTorrent Sync](https://getsync.com/) 用来远端备份我的图片，当然需要先设置好。当我有了可以运行的解决方案之后，我会补充我的文章。

你可以在下面发表你的评论和问题，我会在此页下面回复。

---

via: <http://www.movingelectrons.net/blog/2016/06/26/backup-photos-while-traveling-with-a-raspberry-pi.html>

作者：[Lenin](http://www.movingelectrons.net/blog/2016/06/26/backup-photos-while-traveling-with-a-raspberry-pi.html) 译者：[jiajia9linuxer](https://github.com/jiajia9linuxer) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Torvalds 2.0： Linus 之女谈计算机、大学、女权主义和提升技术界的多元化

典型的被洗脑的白左。。

Like father, like daughter.

长得真好看，无他

![Image by : Photo by Becky Svartström. Modified by Opensource.com. CC BY-SA 4.0](/data/attachment/album/201609/19/094634thjr1sg1wysp11j6.png)

*图片来源：照片来自 Becky Svartström， Opensource.com 修改*

Patricia Torvalds 暂时还不像她的父亲 Linus 一样闻名于 Linux 和开源领域。

![](/data/attachment/album/201609/19/094635fgaobhz0hheggg0h.png)

在她 18 岁的时候，Patricia 已经是一个有多项技术成就、拥有开源行业经验的女权主义者，而且她已经把目标放在进入杜克大学普拉特工程学院的新学期上了。当时她以实习生的身份在位于美国奥勒冈州伯特兰市的 [Puppet 实验室](https://puppetlabs.com/)工作。但不久后，她就将前往北卡罗纳州的达拉莫，开始秋季学期的大学学习。

在这次独家采访中，Patricia 谈到了使她对计算机科学与工程学感兴趣的原因（剧透警告：不是因为她的父亲），她所在高中学校在技术教学上所采取的“正确”方法，女权主义在她的生活中扮演的重要角色，以及对技术缺乏多元化的思考。

### 是什么使你对学习计算机科学与工程学发生兴趣？

我在技术方面的兴趣主要来自于高中时代。我曾一度想投身于生物学，这种想法一直维持到大约大学二年级的时候。大二结束以后，我在波特兰 [VA](http://www.va.gov/) 做网页设计实习生。与此同时，我参加了一个叫做“<ruby> 探索冒险家 <rp>  （ </rp> <rt>  Exploratory Ventures </rt> <rp>  ） </rp></ruby>”（XV）的工程学课程，在我大二学年的后期，我们把一个水下机器人送入了太平洋。但是，转折点大概是在我大三学年的中期被授予“[NCWIT 的计算机之理想](https://www.aspirations.org/)”奖的地区冠军和全国亚军的时候出现的（LCTT 译注：NCWIT - National Center for Women & IT，女性与 IT 国家中心）。

这个奖项的获得让我感觉到确立了自己的兴趣。当然，我认为最重要的部分是我加入到一个由所有获奖者组成的 Facebook 群。女孩们获奖很难想象，因此我们彼此非常支持。由于在 XV 和 [VA](http://www.va.gov/) 的工作，我在获奖前就已经确实对计算机科学发生了兴趣，但是和这些女孩们的交谈更加坚定了这份兴趣，使之更加强烈。再后来，后期大三、大四年级的时候执教 XV 也使我体会到工程学和计算机科学的乐趣。

### 你打算学习什么？你已经知道自己毕业后想干什么了吗？

我希望要么主修机械，要么是电子和计算机工程学，以及计算机科学，并且辅修女性学。毕业以后，我希望在一个支持社会公益或者为其创造技术的公司工作，或者自己开公司。

### 我的女儿在高中有一门 Visual Basic 的编程课。她是整个班上唯一的一个女生，并且以困扰和痛苦的经历结束了这门课程。你的经历是什么样的呢？

我的高中在高年级的时候开设了计算机科学的课程，我也学习了 Visual Basic！这门课不是很糟糕，但我的确是 20 多个人的班级里仅有的三四个女生之一。其他的计算机课程似乎也有相似的性别比例差异。然而，我所在的高中极其小，并且老师对技术包容性非常支持，所以我并没有感到困扰。希望在未来的一些年里这些课程会变得更加多样化。

### 你的学校做了哪些促进技术的举措？它们如何能够变得更好？

我的高中学校给了我们长时间接触计算机的机会，老师们会突然在不相关的课程上安排技术相关的任务，有几次我们还为社会实践课程建了一个网站，我认为这很棒，因为它使我们每一个人都能接触到技术。机器人俱乐部也很活跃并且资金充足，但是非常小，不过我不是其中的成员。学校的技术/工程学项目中一个非常重要的组成部分是一门叫做”<ruby> <a href="http://exploratoryventures.com/">  探索冒险家 </a> <rp>  （ </rp> <rt>  Exploratory Ventures </rt> <rp>  ） </rp></ruby>“（XV）的由学生自己教的工程学课程，这是一门需要亲自动手的课程，并且每年换一个工程学或者计算机科学方面的难题。我和我的一个同学在这儿教了两年，在课程结束以后，有学生上来告诉我他们对从事工程学或者计算机科学发生了兴趣。

然而，我的高中没有特别的关注于让年轻女性加入到这些课程中来，并且在人种上也没有呈现多样化。计算机的课程和俱乐部大量的主要成员都是男性白人学生。这的确应该需要有所改善。

### 在成长过程中，你如何在家运用技术？

老实说，小的时候，我使用我的上机时间（[我的父亲 Linus](https://plus.google.com/+LinusTorvalds/about) 设置了一个跟踪装置，当我们上网一个小时就会断线）来玩[尼奥宠物](http://www.neopets.com/)和或者相似的游戏。我想我本可以搞乱跟踪装置或者在不连接网络的情况下玩游戏，但我没有这样做。我有时候也会和我的父亲做一些小的科学项目，我还记得有一次我和他在电脑终端上打印出几千个“Hello world”。但是大多数时候，我都是和我的妹妹一起玩网络游戏，直到高中的时候才开始学习计算机。

### 你在高中学校的女权俱乐部很活跃，从这份经历中你学到了什么？现在对你来说什么女权问题是最重要的？

在高中二年级的后期，我和我的朋友一起建立了女权俱乐部。刚开始，我们受到了很多人对俱乐部的排斥，并且这从来就没有完全消失过。到我们毕业的时候，女权主义思想已经彻底成为了学校文化的一部分。我们在学校做的女权主义工作通常是在一些比较直接的方面，并集中于像着装要求这样一些问题。

就我个人来说，我更关注于<ruby> 新女性主义 <rp>  （ </rp> <rt>  intersectional feminism </rt> <rp>  ） </rp></ruby>，这是一种致力于（消除）其它方面压迫（比如，种族歧视和阶级压迫等）的女权主义。Facebook 上的 [Gurrilla Feminism](https://www.facebook.com/guerrillafeminism) 专页是新女性主义一个非常好的例子，并且我从中学到了很多。我目前管理着波特兰分会。

在技术多样性方面女权主义对我也非常重要，尽管作为一名和技术世界有很强联系的高年级白人女性，女权主义问题对我产生的影响相比其他人来说少得多，我所参与的新女性主义也是同样的。[《Model View Culture》](https://modelviewculture.com/)的出版非常鼓舞我，谢谢 Shanley Kane 所做的这一切。

### 你会给想教他们的孩子学习编程的父母什么样的建议？

老实说，从没有人推着我学习计算机科学或者工程学。正如我前面说的，在很长一段时间里，我想成为一名遗传学家。大二结束的那个夏天，我在 [VA](http://www.va.gov/) 做了一个夏天的网页设计实习生，这彻底改变了我之前的想法。所以我不知道我是否能够充分回答这个问题。

我的确认为真正的兴趣很重要。如果在我 12 岁的时候，我的父亲让我坐在一台电脑前，教我配置一台网站服务器，我认为我不会对计算机科学感兴趣。相反，我的父母给了我很多可以支配的自由时间让我去做自己想做的事情，绝大多数时候是我在为我的尼奥宠物游戏编写糟糕的 HTML 网站。比我小的妹妹们没有一个对工程学或计算机科学感兴趣，我的父母也不在乎。我感到很幸运的是我的父母给了我和我的妹妹们鼓励和资源去探索自己的兴趣。

仍然要讲的是，在我成长过程中我也常说未来职业生涯要“像我爹一样”，尽管那时我还不知道我父亲是干什么的，只知道他有一个很酷的工作。另外，中学的时候有一次我告诉我的父亲这件事，然后他没有发表什么看法只是告诉我高中的时候不要想这事。所以我猜想这从一定程度上鼓励了我。

### 对于开源社区的领导者们，你有什么建议给他们来吸引和维持更加多元化的贡献者？

我实际上在开源社区并不是特别积极和活跃，我更喜欢和其它女性讨论计算机。我是“[NCWIT 的计算机之理想](https://www.aspirations.org/)”成员之一，这是我对技术持久感到兴趣的一个重要方面，同样也包括 Facebook 的”[Ladies Storm Hackathons](https://www.facebook.com/groups/LadiesStormHackathons/)”群。

我认为对于吸引和留住那些天才而形形色色的贡献者，安全的空间很重要。我曾经看到过在一些开源社区有人发表关于女性歧视和种族主义的评论，当人们指出这一问题随后该人就被解职了。我认为要维持一个专业的社区必须就骚扰事件和不正当行为有一个高标准。当然，人们已经有、而且还会有关于在开源社区或其他任何社区能够表达什么意见的更多的观点。然而，如果社区领导人真的想吸引和留住形形色色的天才们，他们必须创造一个安全的空间并且以高标准要求社区成员们。

我也觉得一些社区领导者不明白多元化的价值。很容易觉得在技术上是唯才是举的，并且这个原因有一些是他们不在意技术上不处于中心位置的人，问题来自于发展的早期。他们争论如果一个人在自己的工作上做得很好，那么他的性别或者民族还有性取向这些情况都变得不重要了。这很容易反驳，但我不想看到为这些错误找的理由。我认为多元化的缺失是一个错误，我们应该为之负责并尽力去改善这件事。

---

via: <http://opensource.com/life/15/8/patricia-torvalds-interview>

作者：[Rikki Endsley](http://opensource.com/users/rikki-endsley) 译者：[ucasFL](https://github.com/ucasFL) 校对：[LinuxBars](https://github.com/LinuxBars), [wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译，[Linux中国](https://linux.cn/) 荣誉推出


4 个最好的 Linux 引导程序

Summary: 引导程序是存储在 MBR（主引导记录）或 GUID（全局唯一标识符）分区表中的一个小程序，用于帮助把操作系统装载到内存中。如果没有引导程序，那么你的操作系统将不能够装载到内存中。

应该是只有这四个吧

我在 PC 上一直用的 GRUB。LILO 和 Syslinux 在一些 U 盘系统或 CD 系统上用过。

WHAT FUCK？LILO这种古董级引导还能称“最好”？<br />
超级水文，跟那个软件包管理器一样，乱写

来自117.152.75.28的 Chrome 53.0|GNU/Linux 用户

How about systemd-boot ?

还有很多

wiki.archlinux.org/index.php/Category:Boot_loaders

科普一下 封面用的引导程序是CLOVER<br />
非常好用，界面还比较美观，主要用来引导Hackintosh的，也可以引导windows和linux

来自江苏南京的 Internet Explorer 11.0|Windows 7 用户

张知识。。

不是clover  是burg的一个皮肤

当你打开你的机器，开机自检（POST）成功完成后，BIOS（基本输入输出系统）立即定位所配置的引导介质，并从 MBR（主引导记录）或 GUID（全局唯一标识符）分区表读取一些命令，这是引导介质的最前面 512 个字节内容。主引导记录（MBR）中包含两个重要的信息集合，第一个是引导程序，第二个是分区表。

![](/data/attachment/album/201609/19/112241e3vhh33oh8zhgs6x.jpg)

### 什么是引导程序？

<ruby> 引导程序 <rp>  （ </rp> <rt>  Boot Loader </rt> <rp>  ） </rp></ruby>是存储在 MBR（主引导记录）或 GUID（全局唯一标识符）分区表中的一个小程序，用于帮助把操作系统装载到内存中。如果没有引导程序，那么你的操作系统将不能够装载到内存中。

有一些我们可以随同 Linux 安装到系统上的引导程序，在这篇文章里，我将简要地谈论几个最好的可以与 Linux 一同工作的 Linux 引导程序。

### 1. GNU GRUB

GNU GRUB 是一个非常受欢迎，也可能是用的最多的具有多重引导能力的 Linux 引导程序，它以原始的 Eirch Stefan Broleyn 发明的 GRUB（<ruby> 大一统引导程序 <rp>  （ </rp> <rt>  GRand Unified Bootlader </rt> <rp>  ） </rp></ruby>）为基础。GNU GRUB 增强了原来的 GRUB，带来了一些改进、新的特性和漏洞修复。

重要的是，GRUB 2 现在已经取代了 GRUB。值得注意的是，GRUB 这个名字被重新命名为 GRUB Legacy，但没有活跃开发，不过，它可以用来引导老的系统，因为漏洞修复依然继续。

GRUB 具有下面一些显著的特性：

* 支持多重引导
* 支持多种硬件结构和操作系统，比如 Linux 和 Windows
* 提供一个类似 Bash 的交互式命令行界面，从而用户可以运行 GRUB 命令来和配置文件进行交互
* 允许访问 GRUB 编辑器
* 支持设置加密口令以确保安全
* 支持从网络进行引导，以及一些次要的特性

访问主页: <https://www.gnu.org/software/grub/>

### 2. LILO

LILO （<ruby> Linux 引导程序 <rp>  （ </rp> <rt>  LInux LOader </rt> <rp>  ） </rp></ruby>）是一个简单但强大且非常稳定的 Linux 引导程序。由于 GRUB 有很大改善和增加了许多强大的特性，越来越受欢迎，因此 LILO 在 Linux 用户中已经不是很流行了。

当 LILO 引导的时候，单词“LILO”会出现在屏幕上，并且每一个字母会在一个特定的事件发生前后出现。然而，从 2015 年 12 月开始，LILO 的开发停止了，它有许多特性比如下面列举的：

* 不提供交互式命令行界面
* 支持一些错误代码
* 不支持网络引导（LCTT 译注：其变体 ELILO 支持 TFTP/DHCP 引导）
* 所有的文件存储在驱动的最开始 1024 个柱面上
* 面临 BTFS、GTP、RAID 等的限制

访问主页: <http://lilo.alioth.debian.org/>

### 3. BURG - 新的引导程序

基于 GRUB，BURG 是一个相对来说比较新的引导程序（LCTT 译注：已于 2011 年停止了开发）。由于 BURG 起源于 GRUB, 所以它带有一些 GRUB 主要特性。尽管如此, BURG 也提供了一些出色的特性，比如一种新的对象格式可以支持包括 Linux、Windows、Mac OS、 FreeBSD 等多种平台。

另外，BURG 支持可高度配置的文本和图标模式的引导菜单，计划增加的“流”支持未来可以不同的输入/输出设备一同工作。

访问主页: <https://launchpad.net/burg>

### 4. Syslinux

Syslinux 是一种能从光盘驱动器、网络等进行引导的轻型引导程序。Syslinux 支持诸如 MS-DOS 上的 FAT、 Linux 上的 ext2、ext3、ext4 等文件系统。Syslinux 也支持未压缩的单一设备上的 Btrfs。

注意由于 Syslinux 仅能访问自己分区上的文件，因此不具备多重文件系统引导能力。

访问主页: <http://www.syslinux.org/wiki/index.php?title=The_Syslinux_Project>

### 结论

一个引导程序允许你在你的机器上管理多个操作系统，并在某个的时间选择其中一个使用。没有引导程序，你的机器就不能够装载内核以及操作系统的剩余部分。

我们是否遗漏了任何一流的 Linux 引导程序？如果有请让我们知道，请在下面的评论表中填入值得推荐的 Linux 系统引导程序。

---

via: <http://www.tecmint.com/best-linux-boot-loaders/>

作者：[Aaron Kili](http://www.tecmint.com/best-linux-boot-loaders/) 译者：[ucasFL](https://github.com/ucasFL) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


DAISY : 一种 Linux 上可用的服务于视力缺陷者的文本格式

Summary: 如果你是盲人或像我一样有视力障碍，你可能经常需要各种软硬件才能做到视觉正常的人们视之为理所当然的事情。这其中之一就是阅读的印刷图书的专用格式：布莱叶盲文 Braille（假设你知道怎样阅读它）或特殊的文本格式例如 DAISY。

感谢他们！

![](/data/attachment/album/201609/19/233559bt5bebqbb5w15xqt.png)

*图片: 由Kate Ter Haar提供图片。 opensource.com 后期修饰。 CC BY-SA 2.0*

如果你是盲人或像我一样有视力障碍，你可能经常需要各种软硬件才能做到视觉正常的人们视之为理所当然的事情。这其中之一就是阅读的印刷图书的专用格式：<ruby> 布莱叶盲文 <rp>  （ </rp> <rt>  Braille </rt> <rp>  ） </rp></ruby>（假设你知道怎样阅读它）或特殊的文本格式例如 DAISY。

### DAISY 是什么？

DAISY 是<ruby> 数字化无障碍信息系统 <rp>  （ </rp> <rt>  Digital Accessible Information System </rt> <rp>  ） </rp></ruby>的缩写。 它是一种开放的标准，专用于帮助盲人阅读课本、杂志、报纸、小说，以及你想到的各种东西。 它由 [DAISY 联盟](http://www.daisy.org)创立于上世纪 90 年代中期，该联盟包括的组织们致力于制定出一套标准，可以让以这种方式标记的文本易于阅读、可以跳转、进行注释以及其它的文本操作，就像视觉正常的人能做的一样。

当前的 DAISY 3.0 版本发布于 2005 年中期，是一个完全重写了的标准。它创建的目的是更容易撰写遵守该规范的书籍。值得注意的是，DAISY 能够仅支持纯文本、或仅是录音（PCM wave 文件格式或者 MP3 格式）、或既有文本也有录音。特殊的软件能阅读这类书，并支持用户设置书签和目录导航，就像正常人阅读印刷书籍一样。

### DAISY 是怎样工作的呢？

DAISY，除开特殊的版本，它工作时有点像这样：你拥有自己的主向导文件（在 DAISY 2.02 中是 ncc.html），它包含书籍的元数据，比如作者姓名、版权信息、书籍页数等等。而在 DAISY 3.0 中这个文件是一个有效的 XML 文件，以及一个被强烈建议包含在每一本书中的 DTD（文档类型定义）文件。

在导航控制文件中，标记精确描述了各个位置——无论是文本导航中当前光标位置还是录音中的毫秒级定位，这让该软件可以跳到确切的位置，就像视力健康的人翻到某个章节一样。值得注意的是这种导航控制文件仅包含书中主要的、最大的书籍组成部分的位置。

更小的内容组成部分由 SMIL（<ruby> 同步多媒体集成语言 <rp>  （ </rp> <rt>  Synchronized Multimedia Integration Language </rt> <rp>  ） </rp></ruby>）文件处理。导航的层次很大程度上取决于书籍的标记的怎么样。这样设想一下，如果印刷书籍没有章节标题，你就需要花很多的时间来确定自己阅读的位置。如果一本 DAISY 格式的书籍被标记的很差，你可能只能转到书本的开头或者目录。如果书籍被标记的太差了（或者完全没有标记），你的 DAISY 阅读软件很可能会直接忽略它。

### 为什么需要专门的软件?

你可能会问，如果 DAISY 仅仅是 HTML、XML、录音文件，为什么还需要使用专门的软件进行阅读和操作。单纯从技术上而言，你并不需要。专业化的软件大多数情况下是为了方便。这就像在 Linux 操作系统中，一个简单的 Web 浏览器可以被用来打开并阅读书籍。如果你在一本 DAISY 3 的书中点击 XML 文件，软件通常做的就是读取那些你赋予访问权限的书籍的名称，并建立一个列表让你点击选择要打开的书。如果书籍被标记的很差，它不会显示在这份清单中。

创建 DAISY 则完全是另一件事了，通常需要专门的软件，或需要拥有足够的专业知识来修改一个通用的软件以达到这样的目的。

### 结语

幸运的是，DAISY 是一个已确立的标准。虽然它在阅读方面表现的很棒，但是需要特殊软件来生产它使得视力缺陷者孤立于正常人眼中的世界，在那里人们可以以各种格式去阅读他们电子化书籍。这就是 DAISY 联盟在 EPUB 格式取得了 DAISY 成功的原因，它的第 3 版支持一种叫做“媒体覆盖”的规范，基本上来说是在 EPUB 电子书中可选增加声频或视频。由于 EPUB 和 DAISY 共享了很多 XML 标记，一些能够阅读 DAISY 的软件能够看到 EPUB 电子书但不能阅读它们。这也就意味着只要网站为我们换到这种开放格式的书籍，我们将会有更多可选的软件来阅读我们的书籍。

---

via: <https://opensource.com/life/16/5/daisy-linux-compatible-text-format-visually-impaired>

作者：[Kendell Clark](https://opensource.com/users/kendell-clark) 译者：[theArcticOcean](https://github.com/theArcticOcean) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译，[Linux中国](https://linux.cn/) 荣誉推出


在 Kali Linux 环境下设置蜜罐

Summary: 在这篇短文中我们将讲解如何在 Kali Linux 环境下设置蜜罐。如果你还不知道什么是蜜罐（honeypot），“蜜罐是一种计算机安全机制，其设置用来发现、转移、或者以某种方式，抵消对信息系统的非授权尝试。"

学习一下

学习一下

get

Pentbox 是一个包含了许多可以使渗透测试工作变得简单流程化的工具的安全套件。它是用 Ruby 编写并且面向 GNU / Linux，同时也支持 Windows、MacOS 和其它任何安装有 Ruby 的系统。在这篇短文中我们将讲解如何在 Kali Linux 环境下设置蜜罐。如果你还不知道什么是<ruby> 蜜罐 <rp>  （ </rp> <rt>  honeypot </rt> <rp>  ） </rp></ruby>，“蜜罐是一种计算机安全机制，其设置用来发现、转移、或者以某种方式，抵消对信息系统的非授权尝试。”

![](/data/attachment/album/201609/20/112531mgnlsxt2iz2457d2.jpg)

### 下载 Pentbox：

在你的终端中简单的键入下面的命令来下载 pentbox-1.8。

```
root@kali:~# wget http://downloads.sourceforge.net/project/pentbox18realised/pentbox-1.8.tar.gz

```

![](/data/attachment/album/201609/20/112543dldhs4vaz43v5vwd.jpg)

### 解压 pentbox 文件

使用如下命令解压文件：

```
root@kali:~# tar -zxvf pentbox-1.8.tar.gz

```

![](/data/attachment/album/201609/20/112543e9kriozxxii3ox77.jpg)

### 运行 pentbox 的 ruby 脚本

改变目录到 pentbox 文件夹：

```
root@kali:~# cd pentbox-1.8/

```

![](/data/attachment/album/201609/20/112544ivlmuuzuuivsvcuh.jpg)

使用下面的命令来运行 pentbox：

```
root@kali:~# ./pentbox.rb

```

![](/data/attachment/album/201609/20/112544onoobna2b07yp0ba.jpg)

### 设置一个蜜罐

使用选项 2 (Network Tools) 然后是其中的选项 3 (Honeypot)。

![](/data/attachment/album/201609/20/112545gitojooi678ab3ad.jpg)

完成让我们执行首次测试，选择其中的选项 1 (Fast Auto Configuration)

![](/data/attachment/album/201609/20/112545aif0lzhcbozquoco.jpg)

这样就在 80 端口上开启了一个蜜罐。打开浏览器并且打开链接 <http://192.168.160.128> （这里的 192.168.160.128 是你自己的 IP 地址。）你应该会看到一个 Access denied 的报错。

![](/data/attachment/album/201609/20/112546n68j4j8ki9a02iik.jpg)

并且在你的终端应该会看到 “HONEYPOT ACTIVATED ON PORT 80” 和跟着的 “INTRUSION ATTEMPT DETECTED”。

![](/data/attachment/album/201609/20/112546aarctud3xzx3t0t3.jpg)

现在，如果你在同一步选择了选项 2 (Manual Configuration), 你应该看见更多的其它选项：

![](/data/attachment/album/201609/20/112547rvdqa35h1xdvo55f.jpg)

执行相同的步骤但是这次选择 22 端口 (SSH 端口)。接着在你家里的路由器上做一个端口转发，将外部的 22 端口转发到这台机器的 22 端口上。或者，把这个蜜罐设置在你的云端服务器的一个 VPS 上。

你将会被有如此多的机器在持续不断地扫描着 SSH 端口而震惊。 你知道你接着应该干什么么？ 你应该黑回它们去！桀桀桀！

如果视频是你的菜的话，这里有一个设置蜜罐的视频：

---

via: <https://www.blackmoreops.com/2016/05/06/setup-honeypot-in-kali-linux/>

作者：<blackmoreops.com> 译者：[wcnnbdk1](https://github.com/wcnnbdk1) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Googler：现在可以 Linux 终端下进行 Google 搜索了！

能在国内用吧？

命令行下搭配proxychains.

会不会有人改写一个baiduer………

来自117.136.81.220的 Sina Weibo 6.9|Android 5.0 用户

其实可以直接 w3m 或 lynx。

作为一个人类，我要对你们哪些喜欢在终端下玩弄奇技淫巧的人作出谴责。鼓捣这些反人类的东西是拖社会主义的建设的后腿！在终端中google比你随手拿起手机google一下速度快么？程序员已经到了android手机删了gui用终端打电话的地步了吗？

gsm call 138XXXXXXXX

然而无论用哪个都访问不了 →_→

[ERROR] Failed to connect to www\.google\.com: [Errno 101] Network is unreachable.

怎么感觉有点自虐呢？

一般般，我还真的以为本身就有呢！

![](/data/attachment/album/201609/20/134318mxwqxhofx8yj8jcc.jpg)

一个小问题：你每天做什么事？当然了，好多事情，但是我可以指出一件事，你几乎每天（如果不是每天）都会用 Google 搜索，我说的对吗？（LCTT 译注：Google 是啥？/cry ）

现在，如果你是一位 Linux 用户（我猜你也是），这里有另外一个问题：如果你甚至不用离开终端就可以进行 Google 搜索那岂不是相当棒？甚至不用打开一个浏览器窗口？

如果你是一位类 [\*nix](https://en.wikipedia.org/wiki/Unix-like) 系统的狂热者而且也是喜欢终端界面的人，我知道你的答案是肯定的，而且我认为，接下来你也将喜欢上我今天将要介绍的这个漂亮的小工具。它被称做 Googler。

### Googler：在你 linux 终端下的 google

Googler 是一个简单的命令行工具，它用于直接在命令行窗口中进行 google 搜索，Googler 主要支持三种类型的 Google 搜索：

* Google 搜索：简单的 Google 搜索，和在 Google 主页搜索是等效的。
* Google 新闻搜索：Google 新闻搜索，和在 Google News 中的搜索一样。
* Google 站点搜索：Google 从一个特定的网站搜索结果。

Googler 用标题、链接和网页摘要来显示搜索结果。搜索出来的结果可以仅通过两个按键就可以在浏览器里面直接打开。

![](/data/attachment/album/201609/20/134338rz5ei8is5x5a5lme.png)

### 在 Ubuntu 下安装 Googler

先让我们进行软件的安装。

首先确保你的 python 版本大于等于 3.3，可以用以下命令查看。

```
python3 --version

```

如果不是的话，就更新一下。Googler 要求 python 版本 3.3 及以上运行。

虽然 Googler 现在还不能在 Ununtu 的软件库中找到，我们可以很容易地从 GitHub 仓库中安装它。我们需要做的就是运行以下命令：

```
cd /tmp
git clone https://github.com/jarun/googler.git
cd googler
sudo make install
cd auto-completion/bash/
sudo cp googler-completion.bash /etc/bash_completion.d/

```

这样 Googler 就带着命令自动完成特性安装完毕了。

### 特点 & 基本用法

如果我们快速浏览它所有的特点，我们会发现 Googler 实际上是一个十分强大的工具，它的一些主要特点就是：

#### 交互界面

在终端下运行以下命令：

```
googler

```

交互界面就会被打开，Googler 的开发者 [Arun Prakash Jana](https://github.com/jarun) 称之为<ruby> 全向提示符 <rp>  （ </rp> <rt>  omniprompt </rt> <rp>  ） </rp></ruby>，你可以输入 `?` 去寻找可用的命令参数：

![](/data/attachment/album/201609/20/134349pqc54iiij7zg0i9s.png)

在提示符处，输入任何搜索词汇关键字去开始搜索，然后你可以输入`n`或者`p`导航到搜索结果的后一页和前一页。

要在浏览器窗口中打开搜索结果，直接输入搜索结果的编号，或者你可以输入 `o` 命令来打开这个搜索网页。

#### 新闻搜索

如果你想去搜索新闻，直接以`N`参数启动 Googler：

```
googler -N

```

随后的搜索将会从 Google News 抓取结果。

#### 站点搜索

如果你想从某个特定的站点进行搜索，以`w 域名`参数启动 Googler：

```
googler -w itsfoss.com

```

随后的搜索会只从这个博客中抓取结果！

#### 手册页

运行以下命令去查看 Googler 的带着各种用例的手册页：

```
man googler

```

#### 指定国家/地区的 Google 搜索引擎

```
googler -c in "hello world"

```

上面的示例命令将会开始从 Google 的印度域名搜索结果（in 代表印度）

还支持：

* 通过时间和语言偏好来过滤搜索结果
* 支持 Google 查询关键字，例如：`site:example.com` 或者 `filetype:pdf` 等等
* 支持 HTTPS 代理
* Shell 命令自动补全
* 禁用自动拼写纠正

这里还有更多特性。你可以用 Googler 去满足你的需要。

Googler 也可以和一些基于文本的浏览器整合在一起（例如：[elinks](http://elinks.or.cz/)、[links](http://links.twibright.com/)、[lynx](http://lynx.browser.org/)、w3m 等），所以你甚至都不用离开终端去浏览网页。在 [Googler 的 GitHub 项目页](https://github.com/jarun/googler#faq)可以找到指导。

如果你想看一下 Googler 不同的特性的视频演示，方便的话你可以查看 GitHub 项目页附带的终端记录演示页： [jarun/googler v2.7 quick demo](https://asciinema.org/a/85019)。

### 对于 Googler 的看法？

尽管 googler 可能并不是对每个人都是必要和渴望的，对于一些不想打开浏览器进行 google 搜索或者就是想泡在终端窗口里面的人来说，这是一个很棒的工具。你认为呢？

---

via: <https://itsfoss.com/review-googler-linux/>

作者：[Munif Tanjim](https://itsfoss.com/author/munif/) 译者：[LinuxBars](https://github.com/LinuxBars) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


使用 Python 和 Asyncio 编写在线多人游戏（三）

 ![](/data/attachment/album/201609/20/152441d6zf0gfh0kivkfym.jpg)

>
> 在这个系列中，我们基于多人游戏 [贪吃蛇](http://snakepit-game.com/) 来制作一个异步的 Python 程序。上一篇文章聚焦于[编写游戏循环](/article-7784-1.html)上，而本系列第 1 部分则涵盖了如何[异步化](/article-7767-1.html)。
>
>
>

* 代码戳[这里](https://github.com/7WebPages/snakepit-game)

[![](/data/attachment/album/201609/20/152543iw8yqfmyzw0ze90b.gif)](https://github.com/7WebPages/snakepit-game)

### 4、制作一个完整的游戏

![](/data/attachment/album/201609/20/152546h2rxum7diizxymdi.gif)

#### 4.1 工程概览

在此部分，我们将回顾一个完整在线游戏的设计。这是一个经典的贪吃蛇游戏，增加了多玩家支持。你可以自己在 （<http://snakepit-game.com>） 亲自试玩。源码在 GitHub 的这个[仓库](https://github.com/7WebPages/snakepit-game)。游戏包括下列文件：

* [server.py](https://github.com/7WebPages/snakepit-game/blob/master/server.py) - 处理主游戏循环和连接。
* [game.py](https://github.com/7WebPages/snakepit-game/blob/master/game.py) - 主要的 `Game` 类。实现游戏的逻辑和游戏的大部分通信协议。
* [player.py](https://github.com/7WebPages/snakepit-game/blob/master/player.py) - `Player` 类，包括每一个独立玩家的数据和蛇的展现。这个类负责获取玩家的输入并相应地移动蛇。
* [datatypes.py](https://github.com/7WebPages/snakepit-game/blob/master/datatypes.py) - 基本数据结构。
* [settings.py](https://github.com/7WebPages/snakepit-game/blob/master/settings.py) - 游戏设置，在注释中有相关的说明。
* [index.html](https://github.com/7WebPages/snakepit-game/blob/master/index.html) - 客户端所有的 html 和 javascript代码都放在一个文件中。

#### 4.2 游戏循环内窥

多人的贪吃蛇游戏是个用于学习十分好的例子，因为它简单。所有的蛇在每个帧中移动到一个位置，而且帧以非常低的频率进行变化，这样就可以让你就观察到游戏引擎到底是如何工作的。因为速度慢，对于玩家的按键不会立马响应。按键先是记录下来，然后在一个游戏循环迭代的最后计算下一帧时使用。

>
> 现代的动作游戏帧频率更高，而且通常服务端和客户端的帧频率是不相等的。客户端的帧频率通常依赖于客户端的硬件性能，而服务端的帧频率则是固定的。一个客户端可能根据一个游戏“嘀嗒”的数据渲染多个帧。这样就可以创建平滑的动画，这个受限于客户端的性能。在这个例子中，服务端不仅传输物体的当前位置，也要传输它们的移动方向、速度和加速度。客户端的帧频率称之为 FPS（<ruby> 每秒帧数 <rp>  （ </rp> <rt>  frames per second </rt> <rp>  ） </rp></ruby>），服务端的帧频率称之为 TPS（<ruby> 每秒滴答数 <rp>  （ </rp> <rt>  ticks per second </rt> <rp>  ） </rp></ruby>）。在这个贪吃蛇游戏的例子中，二者的值是相等的，在客户端显示的一帧是在服务端的一个“嘀嗒”内计算出来的。
>
>
>

我们使用类似文本模式的游戏区域，事实上是 html 表格中的一个字符宽的小格。游戏中的所有对象都是通过表格中的不同颜色字符来表示。大部分时候，客户端将按键的码发送至服务端，然后每个“滴答”更新游戏区域。服务端一次更新包括需要更新字符的坐标和颜色。所以我们将所有游戏逻辑放置在服务端，只将需要渲染的数据发送给客户端。此外，我们通过替换通过网络发送的数据来减少游戏被破解的概率。

#### 4.3 它是如何运行的？

这个游戏中的服务端出于简化的目的，它和例子 3.2 类似。但是我们用一个所有服务端都可访问的 `Game` 对象来代替之前保存了所有已连接 websocket 的全局列表。一个 `Game` 实例包括一个表示连接到此游戏的玩家的 `Player` 对象的列表（在 `self._players` 属性里面），以及他们的个人数据和 websocket 对象。将所有游戏相关的数据存储在一个 `Game` 对象中，会方便我们增加多个游戏房间这个功能——如果我们要增加这个功能的话。这样，我们维护多个 `Game` 对象，每个游戏开始时创建一个。

客户端和服务端的所有交互都是通过编码成 json 的消息来完成。来自客户端的消息仅包含玩家所按下键码对应的编号。其它来自客户端消息使用如下格式：

```
[command, arg1, arg2, ... argN ]

```

来自服务端的消息以列表的形式发送，因为通常一次要发送多个消息 （大多数情况下是渲染的数据）：

```
[[command, arg1, arg2, ... argN ], ... ]

```

在每次游戏循环迭代的最后会计算下一帧，并且将数据发送给所有的客户端。当然，每次不是发送完整的帧，而是发送两帧之间的变化列表。

注意玩家连接上服务端后不是立马加入游戏。连接开始时是<ruby> 观望者 <rp>  （ </rp> <rt>  spectator </rt> <rp>  ） </rp></ruby>模式，玩家可以观察其它玩家如何玩游戏。如果游戏已经开始或者上一个游戏会话已经在屏幕上显示 “game over” （游戏结束），用户此时可以按下 “Join”（参与），来加入一个已经存在的游戏，或者如果游戏没有运行（没有其它玩家）则创建一个新的游戏。后一种情况下，游戏区域在开始前会被先清空。

游戏区域存储在 `Game._field` 这个属性中，它是由嵌套列表组成的二维数组，用于内部存储游戏区域的状态。数组中的每一个元素表示区域中的一个小格，最终小格会被渲染成 html 表格的格子。它有一个 `Char` 的类型，是一个 `namedtuple` ，包括一个字符和颜色。在所有连接的客户端之间保证游戏区域的同步很重要，所以所有游戏区域的更新都必须依据发送到客户端的相应的信息。这是通过 `Game.apply_render()` 来实现的。它接受一个 `Draw` 对象的列表，其用于内部更新游戏区域和发送渲染消息给客户端。

>
> 我们使用 `namedtuple` 不仅因为它表示简单数据结构很方便，也因为用它生成 json 格式的消息时相对于 `dict` 更省空间。如果你在一个真实的游戏循环中需要发送复杂的数据结构，建议先将它们序列化成一个简单的、更短的格式，甚至打包成二进制格式（例如 bson，而不是 json），以减少网络传输。
>
>
>

`Player` 对象包括用 `deque` 对象表示的蛇。这种数据类型和 `list` 相似，但是在两端增加和删除元素时效率更高，用它来表示蛇很理想。它的主要方法是 `Player.render_move()`，它返回移动玩家的蛇至下一个位置的渲染数据。一般来说它在新的位置渲染蛇的头部，移除上一帧中表示蛇的尾巴的元素。如果蛇吃了一个数字变长了，在相应的多个帧中尾巴是不需要移动的。蛇的渲染数据在主类的 `Game.next_frame()` 中使用，该方法中实现所有的游戏逻辑。这个方法渲染所有蛇的移动，检查每一个蛇前面的障碍物，而且生成数字和“石头”。每一个“嘀嗒”，`game_loop()` 都会直接调用它来生成下一帧。

如果蛇头前面有障碍物，在 `Game.next_frame()` 中会调用 `Game.game_over()`。它后通知所有的客户端那个蛇死掉了 （会调用 `player.render_game_over()` 方法将其变成石头），然后更新表中的分数排行榜。`Player` 对象的 `alive` 标记被置为 `False`，当渲染下一帧时，这个玩家会被跳过，除非他重新加入游戏。当没有蛇存活时，游戏区域会显示 “game over” （游戏结束）。而且，主游戏循环会停止，设置 `game.running` 标记为 `False`。当某个玩家下次按下 “Join” （加入）时，游戏区域会被清空。

在渲染游戏的每个下一帧时也会产生数字和石头，它们是由随机值决定的。产生数字或者石头的概率可以在 `settings.py` 中修改成其它值。注意数字的产生是针对游戏区域每一个活的蛇的，所以蛇越多，产生的数字就越多，这样它们都有足够的食物来吃掉。

#### 4.4 网络协议

从客户端发送消息的列表：

| 命令 | 参数 | 描述 |
| --- | --- | --- |
| new\_player | [name] | 设置玩家的昵称 |
| join |  | 玩家加入游戏 |

从服务端发送消息的列表：

| 命令 | 参数 | 描述 |
| --- | --- | --- |
| handshake | [id] | 给一个玩家指定 ID |
| world | [[(char, color), ...], ...] | 初始化游戏区域（世界地图） |
| reset\_world |  | 清除实际地图，替换所有字符为空格 |
| render | [x, y, char, color] | 在某个位置显示字符 |
| p\_joined | [id, name, color, score] | 新玩家加入游戏 |
| p\_gameover | [id] | 某个玩家游戏结束 |
| p\_score | [id, score] | 给某个玩家计分 |
| top\_scores | [[name, score, color], ...] | 更新排行榜 |

典型的消息交换顺序：

| 客户端 -> 服务端 | 服务端 -> 客户端 | 服务端 -> 所有客户端 | 备注 |
| --- | --- | --- | --- |
| new\_player |  |  | 名字传递给服务端 |
|  | handshake |  | 指定 ID |
|  | world |  | 初始化传递的世界地图 |
|  | top\_scores |  | 收到传递的排行榜 |
| join |  |  | 玩家按下“Join”，游戏循环开始 |
|  |  | reset\_world | 命令客户端清除游戏区域 |
|  |  | render, render, ... | 第一个游戏“滴答”，渲染第一帧 |
| (key code) |  |  | 玩家按下一个键 |
|  |  | render, render, ... | 渲染第二帧 |
|  |  | p\_score | 蛇吃掉了一个数字 |
|  |  | render, render, ... | 渲染第三帧 |
|  |  |  | ... 重复若干帧 ... |
|  |  | p\_gameover | 试着吃掉障碍物时蛇死掉了 |
|  |  | top\_scores | 更新排行榜（如果需要更新的话） |

### 5. 总结

说实话，我十分享受 Python 最新的异步特性。新的语法做了改善，所以异步代码很容易阅读。可以明显看出哪些调用是非阻塞的，什么时候发生 greenthread 的切换。所以现在我可以宣称 Python 是异步编程的好工具。

SnakePit 在 7WebPages 团队中非常受欢迎。如果你在公司想休息一下，不要忘记给我们在 [Twitter](https://twitter.com/7WebPages) 或者 [Facebook](https://www.facebook.com/7WebPages/) 留下反馈。

---

via: <https://7webpages.com/blog/writing-online-multiplayer-game-with-python-and-asyncio-part-3/>

作者：[Kyrylo Subbotin](https://7webpages.com/blog/writing-online-multiplayer-game-with-python-and-asyncio-part-3/) 译者：[chunyang-wen](https://github.com/chunyang-wen) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

（题图来自：[wallpaperinhd.net](http://www.wallpaperinhd.net/preview/3766/2880x1800/dragon-(1252x848)-wallpaper.html)）


如何在 Ubuntu 16.04 和 Fedora 22-24 上安装最新的 XFCE 桌面？

Summary: Xfce 是一款针对 Linux 系统的现代化轻型开源桌面环境，它在其他的类 Unix 系统上，比如 Mac OS X、 Solaries、 *BSD 以及其它几种上也能工作得很好。它非常快并以简洁而优雅的用户界面展现了用户友好性。

不得不说，XFCE 同 gnome 和 kde 相比，一致性做的不够好。

一致性是什么意思

安装xfce不难，难的是如何调教的好看，只有xubuntu的视觉效果令人满意

我就想要开箱即用的感觉。

Mac OS X 上怎么装xfce?

我也想知道

是指的 xfce 可以用很多 GNOME 软件吗？

xfce已经停止开发多年了,看了标题我还以为"最新的xfce桌面"又更新了

去年2月还更新了4.12，http://www.xfce.org/about/news/?post=1425081600 并没有停止开发。

这么丑的桌面不要发了好吗

来自云南玉溪的 Microsoft Edge 14.14393|Windows 10 用户

Xfce 是一款针对 Linux 系统的现代化[轻型开源桌面环境](http://www.tecmint.com/best-linux-desktop-environments/)，它在其他的类 Unix 系统上，比如 Mac OS X、 Solaries、 \*BSD 以及其它几种上也能工作得很好。它非常快并以简洁而优雅的用户界面展现了用户友好性。

在服务器上安装一个桌面环境有时还是有用的，因为某些应用程序可能需要一个桌面界面，以便高效而可靠的管理。 Xfce 的一个卓越的特性是其内存消耗等系统资源占用率很低，因此，如果服务器需要一个桌面环境的话它会是首选。

![](/data/attachment/album/201609/21/090507ifxynz2r53oz2xr3.jpg)

### Xfce 桌面的功能特性

另外，它的一些值得注意的组件和功能特性列在下面：

* Xfwm 窗口管理器
* Thunar 文件管理器
* 用户会话管理器：用来处理用户登录、电源管理之类
* 桌面管理器：用来设置背景图片、桌面图标等等
* 应用管理器
* 它的高度可连接性以及一些其他次要功能特性

Xfce 的最新稳定发行版是 Xfce 4.12，它所有的功能特性和与旧版本的变化都列在了[这儿](https://www.xfce.org/about/news/?post=1425081600)。

#### 在 Ubuntu 16.04 上安装 Xfce 桌面

Linux 发行版，比如 Xubuntu、Manjaro、OpenSUSE、Fedora Xfce Spin、Zenwalk 以及许多其他发行版都提供它们自己的 Xfce 桌面安装包，但你也可以像下面这样安装最新的版本。

```
$ sudo apt update
$ sudo apt install xfce4

```

等待安装过程结束，然后退出当前会话，或者你也可以选择重启系统。在登录界面，选择 Xfce 桌面，然后登录，截图如下：

![](/data/attachment/album/201609/21/072158rg0kcrnc9lk9ydkn.png)

![](/data/attachment/album/201609/21/072159waqma1atzcdmdqac.png)

#### 在 Fedora 22-24 上安装 Xfce 桌面

如果你已经有一个安装好的 Linux 发行版 Fedora，想在上面安装 xfce 桌面，那么你可以使用如下所示的 yum 或 dnf 命令。

```
-------------------- 在 Fedora 22 上 --------------------
# yum install @xfce
-------------------- 在 Fedora 23-24 上 --------------------
# dnf install @xfce-desktop-environment

```

安装 Xfce 以后，你可以从会话菜单选择 Xfce 登录或者重启系统。

![](/data/attachment/album/201609/21/072200r5pwc975m7py963p.png)

![](/data/attachment/album/201609/21/072200qvh2wh2cwivba5w3.png)

如果你不再想要 Xfce 桌面留在你的系统上，那么可以使用下面的命令来卸载它：

```
-------------------- 在 Ubuntu 16.04 上 --------------------
$ sudo apt purge xfce4
$ sudo apt autoremove
-------------------- 在 Fedora 22 上 --------------------
# yum remove @xfce
-------------------- 在 Fedora 23-24 上 --------------------
# dnf remove @xfce-desktop-environment

```

在这个简单的入门指南中，我们讲解了如何安装最新版 Xfce 桌面的步骤，我相信这很容易掌握。如果一切进行良好，你可以享受一下使用 Xfce —— 这个 [Linux 系统上最佳桌面环境](http://www.tecmint.com/best-linux-desktop-environments/)之一。

此外，如果你再次回来，你可以通过下面的反馈表单和我们始终保持联系。

---

via: <http://www.tecmint.com/install-xfce-desktop-in-ubuntu-fedora/>

作者：[Aaron Kili](http://www.tecmint.com/author/aaronkili/) 译者：[ucasFL](https://github.com/ucasFL) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

（题图来自：[deviantart.com](http://ramblgyrl.deviantart.com/art/Xfce-Desktop-w-Conky-441738134)）


Linus Torvalds 透露他编程最喜欢使用的笔记本

Summary: 我能说这是大神代言的产品吗——是戴尔 XPS 13 开发者版。

Yoga 900我会很喜欢，也觉得GNOME3挺好用。不过能有个全键的上推屏幕键盘就更好了。

翻译的处女作，未来还有好长路要走……

高分屏慎用GNOME的scale设置，我就是在我的Thinkpad W520高分屏版上设置缩放尺度，结果每次按钮都跑到屏幕外面改不回来了，想尝试的同学，上面那个命令行很救命~

嗯，我突然发现我的X220实在是落伍到了极点了，不过...只是办公也没有什么问题啊，就这样用吧。

开始没想起，看到你这个回复时，我想起当初在 1080P 全高清电视机摆弄 Ubuntu 14.04 时，在控制面板(当然这不是 Ubuntu 下的叫法)设置缩放比例不当，藉着自己在 Windows 下改注册表命令 reg 的经验，开个 tty，摸索着用 gsettings 把缩放比改回去了。

我只想说  Firefox 和 Chrome 真的很好用

图片上是ubuntu啊。

小编找的图吧，林大爷用fedora/gnome

xps13 developer预装ubuntu14lts

这广告效果不错

不是，原文用的图。要么是 Linus 的，要么是原文作者的。

哈哈哈哈哈哈哈哈

这个广告打的清新脱俗啊

哈哈哈，我充分怀疑 ZDNET 收了广告费。

不知道林大爷打字的时候光标会不会乱飞。毕竟16.04已经没有"disable trackpad while typing"选项了。

不会。<br />
因为他就不用Ubuntu，Fedora没有16.04

我能说这是大神代言的产品吗——是戴尔 XPS 13 开发者版。

>
> 是戴尔 XPS 13 开发者版。下面就是原因。
>
>
>

我最近和一些 Linux 开发者讨论了对于严谨的程序员来说，最好的笔记本是什么样的问题。结果，我从这些程序员的观点中筛选出了多款笔记本电脑。那么依我之见赢家是谁呢？就是戴尔 XPS 13 开发者版。和我观点一样的大有人在。Linux的缔造者 Linus Torvalds 也认同这个观点。对于他来说，戴尔 XPS 13 开发者版大概是最好的笔记本电脑了。

![Linus Torvalds new favorite laptop is the Dell XPS 13 Developer Edition.](/data/attachment/album/201609/21/100913radte8zg7nf2dxox.jpg)

Torvalds 的需求可能和你的不同。

在 Google+ 上，Torvalds 解释道，“第一：[我从来不把笔记本当成台式机的替代品](https://plus.google.com/+LinusTorvalds/posts/VZj8vxXdtfe)，并且，我每年旅游不了几次。所以对于我来说，笔记本是一个相当专用的东西，并不是每日（甚至每周）都要使用，因此，主要的标准不是那种“差不多每天都使用”的标准，而是非常适合于旅游时使用。”

因此，对于 Torvalds 来说，“我最后比较关心的一点是它是相当的小和轻，因为在会议上我可能一整天都需要带着它。我同样需要一个好的屏幕，因为到目前为止，我主要是在桌子上使用它，我希望文字的显示小而且清晰。”

戴尔的显示器是由 Intel's Iris 540 GPU 支持的。在我的印象中，它表现的非常的不错。

Iris 驱动了 13.3 英寸的 3200×1800 的显示屏。每英寸有 280 像素，比我喜欢的 [2015 年的 Chromebook Pixel](http://www.zdnet.com/article/the-best-chromebook-ever-the-chromebook-pixel-2015/) 多了 40 个像素，比 [Retina 屏的 MacBook Pro](http://www.zdnet.com/product/apple-15-inch-macbook-pro-with-retina-display-mid-2015/) 还要多 60 个像素。

然而，要让上面说的硬件配置在 [Gnome](https://www.gnome.org/) 桌面上玩好也不容易。正如 Torvalds 在另一篇文章解释的那样，它“[和我的桌面电脑有一样的分辨率](https://plus.google.com/+LinusTorvalds/posts/d7nfnWSXjfD)，但是，显然因为笔记本的显示屏更小，Gnome 桌面似乎自己做了个艰难的决定，认为我需要 2 倍的自动缩放比例，这简直愚蠢到炸裂（例如窗口显示，图标等）。”

解决方案？你不用想着在用户界面里面找了。你需要在 shell下运行：`gsettings set org.gnome.desktop.interface scaling-factor 1`。

Torvalds 或许使用 Gnome 桌面，但是他不是很喜欢 Gnome 3.x 系列。这一点上我跟他没有不同意见。这就是为什么我使用 [Cinnamon](http://www.zdnet.com/article/how-to-customise-your-linux-desktop-cinnamon/) 来代替。

他还希望“一个相当强大的 CPU，因为当我旅游的时候，我依旧需要编译 Linux 内核很多次。我并不会像在家那样每次 pull request 都进行一次完整的“make allmodconfig”编译，但是我希望可以比我以前的笔记本多编译几次，实际上，这（也包括屏幕）应该是我想升级的主要原因。”

Linus 没有描述他的 XPS 13 的细节，但是我测评过的那台是一个高端机型。它带有双核 2.2GHz 的第 6 代英特尔的酷睿 i7-6550U Skylake 处理器，16GBs DDR3 内存，以及一块半 TB （500GB）的 PCIe 固态硬盘（SSD）。我可以肯定，Torvalds 的系统至少是精良装备。”

一些你或许会关注的特征没有在 Torvalds 的清单中：

>
> “我不会关心的是触摸屏，因为我的手指相对于我所看到的文字是又大又笨拙（我也无法处理污渍：也许我的手指特别油腻，但是我真的不想碰那些屏幕）。
>
>
> 我并不十分关心那些“一整天的电池续航”，因为坦率的讲，我不记得上次没有接入电源时什么时候了。我可能着急忙慌而忘记插电，但它不是一个天大的问题。现在电池的寿命“超过两小时”，我只是不那么在乎了。”
>
>
>

戴尔声称，XPS 13，搭配 56 瓦小时的 4 芯电池，拥有 12 小时的电池续航。以我的使用经验它已经很好的用过了 10 个小时。我从没有尝试过把电量完全耗完是什么状态。

Torvalds 也没有遇到 Intel 的 Wi-Fi 设备问题。非开发者版使用 Broadcom 的芯片设备，已经被 Windows 和 Linux 用户发现了一些问题。戴尔的技术支持对于我来解决这些问题非常有帮助。

一些用户在使用 XPS 13 触摸板的时候，遇到了问题。Torvalds 和我都几乎没有什么困扰。Torvalds 写到，“XPS13 触摸板对于我来说运行的非常好。这可能只是个人喜好，但它操作起来比较流畅，响应比较快。”

不过，尽管 Torvalds 喜欢 XPS 13，他同时也钟情于最新版的联想 X1 Carbon、惠普 Spectre 13 x360，和去年的联想 Yoga 900。至于我？我喜欢 XPS 13 开发者版。至于价钱，我以前测评过的型号是 $1949.99，可能刷你的信用卡就够了。

因此，如果你希望像世界上顶级的程序员之一一样开发的话，Dell XPS 13 开发者版对得起它的价格。

---

via: <http://www.zdnet.com/article/linus-torvalds-reveals-his-favorite-programming-laptop/>

作者：[Steven J. Vaughan-Nichols](http://www.zdnet.com/meet-the-team/us/steven-j-vaughan-nichols/)  译者：[yangmingming](https://github.com/yangmingming) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


适用于所有发行版的 Linux 应用程序——是否真的有好处呢？

Summary: 虽然关于此问题有着不同的想法，但是有一个被大家共同接受的观点是：捆绑应用对于填补 Linux 生态系统有着其独到的作用。

看看UNIX的失败。值得Linux思考。

很简单，两种方式并行就可以咯。然后不同的用户可以选择不同的方式，或者说不同类型的用户可以在自己的电脑上以不同比例使用两种方式来安装这种软件。又或者对不同类型的软件使用不同的方式，常用的，使用包依赖的方式安装，不常用或偶尔用的或者昂贵的版权类的软件，可以使用捆绑式安装方式。

WIN在这方面的成功也值得LINUX思考

然而linux这么多年了，还在考虑，考虑

![](/data/attachment/album/201609/21/123327e17d67ni8omytxn7.jpg)

让我们回顾一下 Linux 社区最新的愿景——推动去中心化的应用来解决发行版的碎片化。

继上周的文章：“[Snap、Flatpak 这种通吃所有发行版的打包方式真的有用吗？](/article-7783-1.html)” 之后，一系列新观点浮出水面，其中可能包含关于这样应用是否有用的重要信息。

### 缺点

就这个话题在[这里](http://www.proli.net/2016/06/25/gnulinux-bundled-application-ramblings/)的评论，一个叫 Till 的 [Gentoo](http://www.iwillfolo.com/5-reasons-use-gentoo-linux/) 使用者，对于上一次我们未能完全解释的问题给出了一些新的观点。

对于上一次我们选择仅仅称之为膨胀的的东西，Till 从另一方面做了剖析膨胀将来的发展，这可以帮助我们更好的理解它的组成和其影响。

这些被称之为“捆绑应用”的应用程序能够工作在所有发行版上的机制是——将它依赖的库都包含在它们的应用软件之中，Till 说：

>
> “捆绑应用装载了大量的并不被应用开发者所维护的软件。如果其中的某个函数库被发现了一个安全问题而需要更新的话，你得为每一个独立的应用程序安装更新来确保你的系统安全。”
>
>
>

本质上，Till 提出了一个**重要的安全问题**。但是它并不仅仅与安全有关系，它还关系到许多方面，比如说系统维护、原子更新等等。

此外，如果我们进一步假设：依赖的开发者们也许会合作，将他们的软件与使用它的应用程序一起发布（一种理想状况），但这将导致整个平台的开发整体放缓。

另一个将会导致的问题是**透明的依赖关系变得模糊**，就是说，如果你想知道一个应用程序捆绑了哪些依赖关系，你必须依靠开发者发布这些数据。

或者就像 Till 说的：“比如说像某某包是否已经包含了更新的某函数库这样的问题将会是你每天需要面对的。”

与之相反，对于 Linux 现行的标准的包管理方法（包括二进制包和源码包），你能够很容易的注意到哪些函数库已经在系统中更新了。

并且，你也可以很轻松的知道其它哪些应用使用了这个函数库，这就将你从繁琐的单独检查每一个应用程序的工作中解救了出来。

其他可能由膨胀导致的缺点包括：**更大的包体积**（每一个应用程序捆绑了依赖），**更高的内存占用**（没有共享函数库），并且，**少了一个包过滤机制**来防止恶意软件：发行版的包维护者也充当了一个在开发者和用户之间的过滤者，他保障了用户获得高质量的软件。

而在捆绑应用中就不再是这种情况了。

最后一点，Till 声称，尽管在某些情况下很有用，但是在大多数情况下，**捆绑应用程序将弱化自由软件在发行版中的地位**（专有软件供应商将被能够发布他们的软件而不用把它放到公共软件仓库中）。

除此之外，它引出了许多其他问题。很多问题都可以简单归结到开发人员身上。

### 优点

相比之下,另一个名叫 Sven 的人的评论试图反驳目前普遍反对使用捆绑应用程序的观点，从而证明和支持使用它。

“浪费空间？”——Sven 声称在当今世界我们有**很多其他事情在浪费磁盘空间**，比如电影存储在硬盘上、本地安装等等……

最终，这些事情浪费的空间要远远多于仅仅“ 100 MB 而你每天都要使用的程序。……因此浪费空间的说法实在很荒谬。”

“浪费运行内存？”——主要的观点有：

* **共享库浪费的内存要远远少于程序的运行时数据所占用的**。
* 而今运行**内存已经很便宜**了。

“安全梦魇”——不是每个应用程序的运行**真正的要注重安全**。

而且，**许多应用程序甚至从来没有过任何安全更新**，除非在“滚动更新的发行版”。

除了 Sven 这种从实用出发的观点以外，Till 其实也指出了捆绑应用在一些情况下也有着其优点：

* 专有软件的供应商想要保持他们的代码游离于公共仓库之外将更加容易。
* 没有被你的发行版打包进去的小众应用程序将变得更加可行。
* 在没有 Beta 包的二进制发行版中测试应用将变得简单。
* 将用户从复杂的依赖关系中解放出来。

### 最后的思考

虽然关于此问题有着不同的想法，但是有一个被大家共同接受的观点是：**捆绑应用对于填补 Linux 生态系统有着其独到的作用。**

虽然如此，它的定位，不论是主流的还是边缘的，都变得愈发清晰，至少理论上是这样。

想要尽可能优化其系统的用户，在大多数情况下应该要避免使用捆绑应用。

而讲究易用性、尽可能在维护系统上少费劲的用户，可能应该会感觉这种新应用十分舒爽。

---

via: <http://www.iwillfolo.com/linux-applications-that-works-on-all-distributions-are-they-any-good/>

作者：[Editorials](http://www.iwillfolo.com/category/editorials/) 译者：[Chao-zhi](https://github.com/Chao-zhi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译，[Linux中国](https://linux.cn/) 荣誉推出


在 WordPress 下如何通过 Markdown 来提高工作效率

Markdown 套件可以看看 WP Githuber MD 这支插件

主要套色是所见及所得，图片随便复制贴上 (可传到 Imgur 图床)

支援程式码语法高亮

支援 KaTeX

也支援热门的 mermaid.js 等序列图、画流程图的套件。

希望对您有帮助。

![](/data/attachment/album/201609/22/134344im0194foc8mks5a5.jpg)

Markdown 是一种简单的标记语言，旨在帮助你花费更小的代价来格式化纯文本文档。在 WordPress 下你可以使用 HTML 或者可视化编辑器来格式化你的文档，但是使用 markdown 可以让格式化文档变得更加容易，而且你随时可以导出成很多种格式，包括（但不限于）HTML。

WordPress 没有原生的 markdown 的支持，但是，如果你希望的话，在你的网站上有多种插件可以添加这种功能。

在这个教程中，我将会演示如何使用流行的 WP-Markdown 插件为 WordPress 网站添加 markdown 支持。

### 安装

导航到 “Plugins -> Add New”，然后在提供的搜索框中输入 “[wp-markdown](https://wordpress.org/plugins/wp-markdown/)” 就可以直接安装。插件应该会出现在列表中的第一个。单击 “Install Now” 进行安装。

![](/data/attachment/album/201609/22/134404cjd5ovgmokkna54g.png)

### 配置

当你已经安装了这个插件并且激活它之后，导航到 “Settings -> Writing” 并向下滚动，直到 markdown 选项。

你可以启用文章、页面和评论中对于 markdown 的支持。如果你刚刚开始学习 markdown 语法的话，那么你也可以在文章编辑器或者评论的地方启用一个帮助栏，这可以使你更方便一些。

![](/data/attachment/album/201609/22/134503oe050jhvxqv304u0.png)

如果在你的博客文章中包括代码片段的话，那么启用 “Prettify syntax highlighter” 将会让你的代码片段自动语法高亮。

一旦对于你的选择感觉满意的话，那么就单击 “Save Changes” 来保存你的设置吧。

### 使用 Markdown 来写你的文章

当你在自己网站中启用了 markdown 的支持，你就可以立马开始使用了。

通过 “Posts -> Add New” 创建一篇新的文章。你将会注意到默认的可视化及纯文本编辑器已经被 markdown 编辑器所替代。

如果你在配置选项中没有启用 markdown 的帮助栏，你将不会看到 markdown 格式化后的实时预览。然而，只要你的语法是正确的，当你保存或者发布文章的时候，你的 markdown 就会转换成正确的 HTML。

然而，如果你是 markdown 的初学者的话，实时预览这一特征对你会很重要，只需要简单的回到刚才的设置中启用帮助栏选项，你就可以在你的文章底部看到一块漂亮的实时预览区域。另外，你也可以在顶部看到很多按钮，它们将帮助你在文章中快速的插入 markdown 格式。

![](/data/attachment/album/201609/22/134526s4av9fufxlf33nfn.png)

### 结语

正如你所看到的那样，在 WordPress 网站上添加 markdown 支持确实容易，你将只需要花费几分钟的时间就可以了。如果对于 markdown 你全然不知的话，或许你也可以查看我们的 [markdown 备忘录](https://www.maketecheasier.com/productive-with-markdown-cheatsheet/)，它将对于 markdown 语法提供一个全面的参考。

---

via: <https://www.maketecheasier.com/use-markdown-in-wordpress/>

作者：[Ayo Isaiah](https://www.maketecheasier.com/author/ayoisaiah/) 译者：[yangmingming](https://github.com/yangmingming) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Taskwarrior：Linux 下一个很棒的命令行 TODO 工具

Summary: Taskwarrior 是 Ubuntu/Linux 下一个简单而直接的基于命令行的 TODO 工具。这个开源软件是我曾用过的最简单的基于命令行的工具之一。Taskwarrior 可以帮助你更好地组织你自己，而不用安装笨重的新工具——这有时丧失了 TODO 工具的目的。

Taskwarrior 是 Ubuntu/Linux 下一个简单而直接的基于命令行的 TODO 工具。这个开源软件是我曾用过的最简单的[基于命令行的工具](http://www.techdrivein.com/search/label/Terminal)之一。Taskwarrior 可以帮助你更好地组织你自己，而不用安装笨重的新工具——这有时丧失了 TODO 工具的目的。

![](/data/attachment/album/201609/22/175500vbjt8m346t992ltj.png)

### Taskwarrior：一个基于简单的基于命令行帮助完成任务的TODO工具

Taskwarrior是一个开源、跨平台、基于命令行的 TODO 工具，它帮你在终端中管理你的 to-do 列表。这个工具让你可以轻松地添加任务、展示列表、移除任务。而且，在你的默认仓库中就有，不用安装新的 PPA。在 Ubuntu 16.04 LTS 或者相似的发行版中。在终端中按照如下步骤安装 Taskwarrior。

```
sudo apt-get install task

```

简单的用如下：

```
$ task add Read a book
Created task 1.
$ task add priority:H Pay the bills
Created task 2.

```

我使用上面截图中的同样一个例子。是的，你可以设置优先级（H、L 或者 M）。并且你可以使用‘task’或者‘task next’命令来查看你最新创建的 to-do 列表。比如：

```
$ task next

ID Age P Description                      Urg
-- --- - -------------------------------- ----
 2 10s H Pay the bills                     6
 1 20s   Read a book                       0

```

完成之后，你可以使用 ‘task 1 done’ 或者 ‘task 2 done’ 来清除列表。[可以在这里](https://taskwarrior.org/docs/)找到更加全面的命令和使用案例。同样，Taskwarrior 是跨平台的，这意味着不管怎样，你都可以找到一个[满足你需求](https://taskwarrior.org/download/)的版本。如果你需要的话，这里甚至有[一个安卓版](https://taskwarrior.org/news/news.20160225.html)。祝您用得开心！

---

via: <http://www.techdrivein.com/2016/09/taskwarrior-command-line-todo-app-linux.html>

作者：[Manuel Jose](http://www.techdrivein.com/2016/09/taskwarrior-command-line-todo-app-linux.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+techdrivein+%28Tech+Drive-in%29)  译者：[geekpi](https://github.com/geekpi) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


Git 系列（六）：如何搭建你自己的 Git 服务器

我用Gogs架的，比这个简单多啦。  github.com/gogits/gogs

太复杂了

看这个

github.com/sameersbn/docker-gitlab

![](/data/attachment/album/201609/23/064707gewg8xhse8oygghg.jpg)

现在我们将要学习如何搭建 git 服务器，如何编写自定义的 Git 钩子来在特定的事件触发相应的动作（例如通知），或者是发布你的代码到一个站点。

直到现在，我们主要讨论的还是以一个使用者的身份与 Git 进行交互。这篇文章中我将讨论 Git 的管理，并且设计一个灵活的 Git 框架。你可能会觉得这听起来是 “高阶 Git 技术” 或者 “只有狂热粉才能阅读”的一句委婉的说法，但是事实是这里面的每个任务都不需要很深的知识或者其他特殊的训练，就能基本理解 Git 的工作原理，有可能需要一丁点关于 Linux 的知识。

### 共享 Git 服务器

创建你自己的共享 Git 服务器意外地简单，而且在很多情况下，遇到的这点麻烦是完全值得的。不仅仅是因为它保证你有权限查看自己的代码，它还可以通过扩展为 Git 的使用敞开了一扇大门，例如个人 Git 钩子、无限制的数据存储、和持续集成与分发（CI & CD）。

如果你知道如何使用 Git 和 SSH，那么你已经知道怎么创建一个 Git 服务器了。Git 的设计方式，就是让你在创建或者 clone 一个仓库的时候，就完成了一半服务器的搭建。然后允许用 SSH 访问仓库，而且任何有权限访问的人都可以使用你的仓库作为 clone 的新仓库的基础。

但是，这是一个小的<ruby> 点对点环境 <rp>  （ </rp> <rt>  ad-hoc </rt> <rp>  ） </rp></ruby>。按照一些方案你可以创建一些带有同样的功能的设计优良的 Git 服务器，同时有更好的拓展性。

首要之事：确认你的用户们，现在的用户以及之后的用户都要考虑。如果你是唯一的用户那么没有任何改动的必要。但是如果你试图邀请其他的代码贡献者使用，那么你应该允许一个专门的分享系统用户给你的开发者们。

假定你有一个可用的服务器（如果没有，这不成问题，Git 会帮忙解决，CentOS 的 [树莓派 3](https://wiki.centos.org/SpecialInterestGroup/AltArch/Arm32/RaspberryPi3) 是个不错的开始），然后第一步就是只允许使用 SSH 密钥认证的 SSH 登录。这比使用密码登录安全得多，因为这可以免于暴力破解，也可以通过直接删除用户密钥而禁用用户。

一旦你启用了 SSH 密钥认证，创建 `gituser` 用户。这是给你的所有授权的用户们的公共用户：

```
$ su -c 'adduser gituser'

```

然后切换到刚创建的 `gituser` 用户，创建一个 `~/.ssh` 的框架，并设置好合适的权限。这很重要，如果权限设置得太开放会使自己所保护的 SSH 没有意义。

```
$ su - gituser
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys

```

`authorized_keys` 文件里包含所有你的开发者们的 SSH 公钥，你开放权限允许他们可以在你的 Git 项目上工作。他们必须创建他们自己的 SSH 密钥对然后把他们的公钥给你。复制公钥到 gituser 用户下的 `authorized_keys` 文件中。例如，为一个叫 Bob 的开发者，执行以下命令：

```
$ cat ~/path/to/id_rsa.bob.pub >> /home/gituser/.ssh/authorized_keys

```

只要开发者 Bob 有私钥并且把相对应的公钥给你，Bob 就可以用 `gituser` 用户访问服务器。

但是，你并不是想让你的开发者们能使用服务器，即使只是以 `gituser` 的身份访问。你只是想给他们访问 Git 仓库的权限。因为这个特殊的原因，Git 提供了一个限制的 shell，准确的说是 `git-shell`。以 root 身份执行以下命令，把 `git-shell` 添加到你的系统中，然后设置成 `gituser` 用户的默认 shell。

```
# grep git-shell /etc/shells || su -c "echo `which git-shell` >> /etc/shells"
# su -c 'usermod -s git-shell gituser'

```

现在 `gituser` 用户只能使用 SSH 来 push 或者 pull Git 仓库，并且无法使用任何一个可以登录的 shell。你应该把你自己添加到和 `gituser` 一样的组中，在我们的样例服务器中这个组的名字也是 `gituser`。

举个例子：

```
# usermod -a -G gituser seth

```

仅剩下的一步就是创建一个 Git 仓库。因为没有人能在服务器上直接与 Git 交互（也就是说，你之后不能 SSH 到服务器然后直接操作这个仓库），所以创建一个空的仓库 。如果你想使用这个放在服务器上的仓库来完成工作，你可以从它的所在处 `clone` 下来，然后在你的 home 目录下进行工作。

严格地讲，你不是必须创建这个空的仓库；它和一个正常的仓库一样工作。但是，一个空的仓库没有工作分支（working tree） （也就是说，使用 `checkout` 并没有任何分支显示）。这很重要，因为不允许远程使用者们 `push` 到一个有效的分支上（如果你正在 `dev` 分支工作然后突然有人把一些变更 `push` 到你的工作分支，你会有怎么样的感受？）。因为一个空的仓库可以没有有效的分支，所以这不会成为一个问题。

你可以把这个仓库放到任何你想放的地方，只要你想要放开权限给用户和用户组，让他们可以在仓库下工作。千万不要保存目录到比如说一个用户的 home 目录下，因为那里有严格的权限限制。保存到一个常规的共享地址，例如 `/opt` 或者 `/usr/local/share`。

以 root 身份创建一个空的仓库：

```
# git init --bare /opt/jupiter.git
# chown -R gituser:gituser /opt/jupiter.git
# chmod -R 770 /opt/jupiter.git

```

现在任何一个用户，只要他被认证为 `gituser` 或者在 `gituser` 组中，就可以从 jupiter.git 库中读取或者写入。在本地机器尝试以下操作：

```
$ git clone gituser@example.com:/opt/jupiter.git jupiter.clone
Cloning into 'jupiter.clone'...
Warning: you appear to have cloned an empty repository.

```

谨记：开发者们**一定**要把他们的 SSH 公钥加入到 `gituser` 用户下的 `authorized_keys` 文件里，或者说，如果他们有服务器上的用户（如果你给了他们用户），那么他们的用户必须属于 `gituser` 用户组。

### Git 钩子

运行你自己的 Git 服务器最赞的一件事之一就是可以使用 Git 钩子。Git 托管服务有时提供一个钩子类的接口，但是他们并不会给你真正的 Git 钩子来让你访问文件系统。Git 钩子是一个脚本，它将在一个 Git 过程的某些点运行；钩子可以运行在当一个仓库即将接收一个 `commit` 时、或者接受一个 `commit` 之后，或者即将接收一次 `push` 时，或者一次 `push` 之后等等。

这是一个简单的系统：任何放在 `.git/hooks` 目录下的脚本、使用标准的命名体系，就可按设计好的时间运行。一个脚本是否应该被运行取决于它的名字； `pre-push` 脚本在 `push` 之前运行，`post-receive` 脚本在接受 `commit` 之后运行等等。这或多或少的可以从名字上看出来。

脚本可以用任何语言写；如果在你的系统上有可以执行的脚本语言，例如输出 ‘hello world’ ，那么你就可以这个语言来写 Git 钩子脚本。Git 默认带了一些例子，但是并不有启用。

想要动手试一个？这很简单。如果你没有现成的 Git 仓库，首先创建一个 Git 仓库：

```
$ mkdir jupiter
$ cd jupiter
$ git init .

```

然后写一个 “hello world” 的 Git 钩子。因为我为了支持老旧系统而使用 tsch，所以我仍然用它作为我的脚本语言，你可以自由的使用自己喜欢的语言（Bash，Python，Ruby，Perl，Rust，Swift，Go）：

```
$ echo "#\!/bin/tcsh" > .git/hooks/post-commit
$ echo "echo 'POST-COMMIT SCRIPT TRIGGERED'" >> ~/jupiter/.git/hooks/post-commit
$ chmod +x ~/jupiter/.git/hooks/post-commit

```

现在测试它的输出：

```
$ echo "hello world" > foo.txt
$ git add foo.txt
$ git commit -m 'first commit'
! POST-COMMIT SCRIPT TRIGGERED
[master (root-commit) c8678e0] first commit
1 file changed, 1 insertion(+)
create mode 100644 foo.txt

```

现在你已经实现了：你的第一个有功能的 Git 钩子。

### 有名的 push-to-web 钩子

Git 钩子最流行的用法就是自动 `push` 更改的代码到一个正在使用中的产品级 Web 服务器目录下。这是摆脱 FTP 的很好的方式，对于正在使用的产品保留完整的版本控制，整合并自动化内容的发布。

如果操作正确，网站发布工作会像以前一样很好的完成，而且在某种程度上，很精准。Git 真的好棒。我不知道谁最初想到这个主意，但是我是从 Emacs 和 Git 方面的专家，IBM 的 Bill von Hagen 那里第一次听到它的。他的文章包含关于这个过程的权威介绍：[Git 改变了分布式网页开发的游戏规则](http://www.ibm.com/developerworks/library/wa-git/)。

### Git 变量

每一个 Git 钩子都有一系列不同的变量对应触发钩子的不同 Git 行为。你需不需要这些变量，主要取决于你写的程序。如果你只是需要一个当某人 push 代码时候的通用邮件通知，那么你就不需要什么特殊的东西，甚至也不需要编写额外的脚本，因为已经有现成的适合你的样例脚本。如果你想在邮件里查看 `commit` 信息和 `commit` 的作者，那么你的脚本就会变得相对麻烦些。

Git 钩子并不是被用户直接执行，所以要弄清楚如何收集可能会混淆的重要信息。事实上，Git 钩子脚本类似于其他的脚本，像 BASH、Python、C++ 等等一样从标准输入读取参数。不同的是，我们不会给它提供这个输入，所以，你在使用的时候，需要知道可能的输入参数。

在写 Git 钩子之前，看一下 Git 在你的项目目录下 `.git/hooks` 目录中提供的一些例子。举个例子，在这个 `pre-push.sample` 文件里，注释部分说明了如下内容：

```
# $1 -- 即将 push 的远程仓库的名字
# $2 -- 即将 push 的远程仓库的 URL
# 如果 push 的时候，并没有一个命名的远程仓库，那么这两个参数将会一样。
#
# 提交的信息将以下列形式按行发送给标准输入
# <local ref> <local sha1> <remote ref> <remote sha1>

```

并不是所有的例子都是这么清晰，而且关于钩子获取变量的文档依旧缺乏（除非你去读 Git 的源码）。但是，如果你有疑问，你可以从线上[其他用户的尝试中](https://www.analysisandsolutions.com/code/git-hooks-summary-cheat-sheet.htm)学习，或者你只是写一些基本的脚本，比如 `echo $1, $2, $3` 等等。

### 分支检测示例

我发现，对于生产环境来说有一个共同的需求，就是需要一个只有在特定分支被修改之后，才会触发事件的钩子。以下就是如何跟踪分支的示例。

首先，Git 钩子本身是不受版本控制的。 Git 并不会跟踪它自己的钩子，因为对于钩子来说，它是 Git 的一部分，而不是你仓库的一部分。所以，Git 钩子可以监控你的 Git 服务器上的一个空仓库的 `commit` 记录和 `push` 记录，而不是你本地仓库的一部分。

我们来写一个 `post-receive`（也就是说，在 `commit` 被接受之后触发）钩子。第一步就是需要确定分支名：

```
#!/bin/tcsh

foreach arg ( $< )
  set argv = ( $arg )
  set refname = $1
end

```

这个 for 循环用来读入第一个参数 `$1` ，然后循环用第二个参数 `$2` 去覆盖它，然后用第三个参数 `$3` 再这样。在 Bash 中有一个更好的方法，使用 `read` 命令，并且把值放入数组里。但是，这里是 tcsh，并且变量的顺序可以预测的，所以，这个方法也是可行的。

当我们有了 commit 记录的 `refname`，我们就能使用 Git 去找到这个分支的供人看的名字：

```
set branch = `git rev-parse --symbolic --abbrev-ref $refname`
echo $branch #DEBUG

```

然后把这个分支名和我们想要触发的事件的分支名关键字进行比较：

```
if ( "$branch" == "master" ) then
  echo "Branch detected: master"
  git \
    --work-tree=/path/to/where/you/want/to/copy/stuff/to \
    checkout -f $branch || echo "master fail"
else if ( "$branch" == "dev" ) then
  echo "Branch detected: dev"
  Git \
    --work-tree=/path/to/where/you/want/to/copy/stuff/to \
    checkout -f $branch || echo "dev fail"
  else
    echo "Your push was successful."
    echo "Private branch detected. No action triggered."
endif

```

给这个脚本分配可执行权限：

```
$ chmod +x ~/jupiter/.git/hooks/post-receive

```

现在，当一个用户提交到服务器的 master 分支，那些代码就会被复制到一个生产环境的目录，提交到 dev 分支则会被复制到另外的地方，其他分支将不会触发这些操作。

同时，创造一个 `pre-commit` 脚本也很简单。比如，判断一个用户是否在他们不该 `push` 的分支上 `push` 代码，或者对 commit 信息进行解析等等。

Git 钩子也可以变得复杂，而且它们因为 Git 的工作流的抽象层次不同而变得难以理解，但是它们确实是一个强大的系统，让你能够在你的 Git 基础设施上针对所有的行为进行对应的操作。如果你是一个 Git 重度用户，或者一个全职 Git 管理员，那么 Git 钩子是值得学习的，只有当你熟悉这个过程，你才能真正掌握它。

在我们这个系列下一篇也是最后一篇文章中，我们将会学习如何使用 Git 来管理非文本的二进制数据，比如音频和图片。

---

via: <https://opensource.com/life/16/8/how-construct-your-own-git-server-part-6>

作者：[Seth Kenlon](https://opensource.com/users/seth) 译者：[maywanting](https://github.com/maywanting) 校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出