2016年10月

10 月 4 日,KDE 项目发布了其最新的桌面环境 KDE 5.8,它是面向 GNU/Linux 发行版的流行的现代桌面环境。

经过几个月的开发和几个版本的迭代,KDE 5.8 带着若干新功能闪亮登场,取代了之前的 5.7 系列——虽然 5.7 才于 9 月 13 日发布了其第五个维护版本。KDE 5.8 是一个长期支持版本(LTS),它会一直支持到 2018 年。

今天,KDE 发布了其旗舰产品 Plasma 的首个 LTS 版本”,公告中称,“这标志着它的开发人员和设计师们认为它已经可以推荐给普罗大众了。如果你以前体验过 KDE,但是由于种种原因弃之而去,那么现在是你该重新考虑回来的时候了。Plasma 是一个初看简单,实则强大的桌面环境!”

(注,虽然 KDE 3.5 发布于 2005 年 11 月 29 日,而下一个版本 4.0 在 2008 年 1 月 11 日才发布,但是 KDE Plasma 5.8 是官方认可的第一个 LTS 版本)

KDE 主要功能

新版本的 KDE 的主要功能包括:支持桌面小工具;新的系统级搜索功能可以让用户在 KDE 桌面里面搜索任何东西,包括应用、音乐、视频、文件、目录等等;此外还有很多新的东西,包括桌面墙纸、小工具、桌面效果、窗口风格,以及丰富的定制能力。

桌面小工具

桌面小工具

放在你桌面上的有用小工具可以让你及时关注每天的天气,休息的时候可以欣赏漫画,或者简单的用来做做计算。

各种新鲜热辣的装饰素材

各种新鲜热辣的装饰素材

用下载的墙纸、窗口风格、小工具、桌面效果和大量的其它装饰素材打扮你的桌面。我们提供了一个 KDE 商店,可供你在海量的素材中进行选择。

桌面搜索

桌面搜索

Plasma 可以让你在桌面上搜索应用、文件夹、音乐、视频、文件等等你任何想找的东西。

统一的外观

统一的外观

Plasma 的默认 Breeze 主题将各种可视组件的外观打造为一致的风格,这包括用 Qt 4、Qt 5、GTK 2、GTK 3 等等开发的应用,甚至还包括 LibreOffice。

与手机集成

与手机集成

使用 KDE Connect 你可以在桌面上接到短信提醒、可以轻松传输文件、在接到电话时自动静默音乐,甚至将你的手机当成一个遥控器。

无尽的定制可能性

无尽的定制可能性

Plasma 以简洁为本,但是你可以用各种小工具、面板、屏幕和风格来定制它。

KDE 5.8 中的新变化

KDE 完美打造了从开机到关机的整个过程、支持从右向左文字、简化了全局快捷键、改进了许多小应用、修复了多屏支持的问题、更好的支持了坞站和投影仪、增强了 KWin 窗口管理器、新的默认字体、Kirigami 界面更舒适,以及更好的 Wayland 支持!

从启动到关机的一致体验

从启动到关机的一致体验

这个版本带来了全新的登录屏设计,从开机到关闭,给你一个完整的 Breeze 体验。布局经过精细打磨,更适合作为团体或公司办公用的计算机使用。它更加顺滑,也支持更多的定制能力,比如说,所有的 Plasma 插件,比如幻灯片小工具或动画墙纸小工具现在都可以放在锁屏上了。

支持从右向左的语言

支持从右向左的语言

对希伯来语和阿拉伯语这样从右向左书写的语言的支持进行了极大改进。面板内容、桌面和配置对话框会如镜面般反射过来。Plasma 的边栏,比如小工具栏、窗口切换器、活动管理群都放在了屏幕右侧。

改进的应用

媒体播放器的上下文菜单

重写了虚拟桌面切换器(即 Pager)和窗口列表应用,使用了我们在 5.7 中引入的新任务管理器后端,这可以让它们使用同任务管理器一样的数据,从而降低了内存占用并提升了性能。在多屏幕时,虚拟桌面切换器现在也可以设置为仅显示在当前屏幕上,现在它与活动切换器应用大部分代码都相同。

任务管理器在这个版本中有了更多的用处。以前仅在任务管理器提示菜单中可用的媒体控制器现在也可以在上下文菜单中访问了。此外,在拖放操作中可以将窗口拖到前端,将文件拖入任务管理器中会以其关联的应用打开。分组窗口的弹窗现在可以使用键盘进行导航,并且其标签的文字渲染也进行了改进。

简化的全局快捷键

全局快捷键设置

全局快捷键的配置现在针对应用启动后最常用的任务进行了简化。跳转功能是在前一个版本中增加的,全局快捷键现在可以配置跳转到一个应用内的特定功能上。

由于我们在 Wayland 方面的突破,现在可以提供称之为“ 修饰快捷键 modifier-only shortcuts ”的功能,它可以让你只需要按下 Alt 键(或 Meta 键)就可以打开应用菜单。由于这个功能很受欢迎,所以被移植回 X11 会话中了。

其他改进

Plasma Discover 的新界面

这个版本修复了多屏支持方面许多问题,并在 Qt 5.6.1 的支持下显著提升了坞站和投影仪的体验。

Plasma 的窗口管理器 KWin 现在通过 llvmpipe 进行 合成 compositing ,更易于用在少见的硬件和嵌入式设备上。对于要求关闭合成的应用现在有了标准化而广泛使用的界面,移除了“ 非重定向全屏 Unredirect Fullscreen ”选项,它通常会导致一些稳定性问题,因为很多驱动已经不支持它了。

我们的跨平台 UI 组件 Kirigami 现在已经发布,你可以试试看我们用它重新打造的 Plasma Discover。

我们也换了新的默认字体,来自 Google 的 Noto 字体包括了 Unicode 标准中的所有字符,而我们的等宽字体修饰非常适合于程序员和面向终端的用户。

Wayland 支持

Wayland 之上的 Plasma 现在支持 GTK+

在过去几个月当中,在 Wayland 上运行 Plasma 经历了漫长的工作。虽然我们的长期支持的范围并不包括快速发展的 Wayland 方面,不过我们认为它可以经受更多的测试了。虽然仍然有一些小问题和功能缺失,但是现在我们希望你可以试试它并给我们反馈。这个版本中部分改进如下:

  • 支持 xdg-shell,比如现在支持 GTK+ 应用了
  • 对触屏支持做了很多改进
  • 支持触屏手势,虽然现在还没有任何手势
  • 现在支持滑动弹窗效果
  • 在 X11 和 Wayland 应用之间同步剪贴板内容

更多的详细变更内容请参见变更日志

支持期直到 2018 年 4 月

如上面所提到的,KDE Plasma 5.8 LTS 会支持到 2018 年,并将会发布至少 9 个维护版本。而第一个维护版本 KDE Plasma 5.8.1 在下周的 10 月 11 日就要发布了!按照开发计划,开始的维护版本发布会很频繁,简直让人目不暇接:之后再过一周会发布 5.8.2,11 月 1 日发布 5.8.3,11 月 22 日发布 5.8.4。

下载与使用

体验镜像

体验 KDE 5.8 最容易的方式是将体验镜像放到可启动的 USB 棒中,你可用在 KDE 社区维基中找到 Plasma 5 的体验镜像列表

下载软件包

软件包如下:

源代码

你也可以从源代码直接安装 Plasma 5。KDE 社区维基有如何编译的指导。注意,Plasma 5 不能与 Plasma 4 共存,你需要卸载旧版本或将其安装到不同的前缀目录下。

KDE 20 周年纪念北京庆祝沙龙

2016 年 10 月 15 日,由普华基础软件与“Linux 中国”开源社区共同联合主办的 KDE 20 周年庆祝沙龙在北京召开,欢迎各位 KDE 用户和开源爱好者们参加,沙龙不但由社区骨灰级爱好者进行讲演,而且还提供了琳琅满目的独有纪念品。报名人数名额限定,希望参加者需尽快报名

这是 KDE 在国内的第一次大型活动。该活动得到了 KDE 的官方认证,可以通过官方活动入口这里直接报名。

在此沙龙上,我们还会宣布成立 KDE 中国用户组 China KUG,您将成为 China KUG 的第一批成员。

KDE 20 周年纪念沙龙

来吧!和我们一起吃蛋糕、合影,分享 KDE 体会,还有机会获取 iSOFTLinux V4.0 U 盘、KDE 二十周年 T 恤等多种奖品。我们在这里真诚期待每一个 KDE 爱好者及开源软件爱好者的到来!

KDE 20 周年纪念专属定制限量 T 恤

沙龙日程

13:30–14:00签到
14:00-14:30KDE 20 年发展历史 (KDE 成员 Leslie Zhai 讲演)
14:30-14:50国际及国内 KDE KOL 对本次北京庆祝活动的祝贺视频
14:50–15:20KDE 组件打包
15:20-15:50KDE-China 翻译组介绍
15:50-16:1020 周年庆典(蛋糕)
16:20-16:40China KUG 成立仪式
16:40-17:00游戏及合影

沙龙地点

北京海淀区农大南路 1 号硅谷亮城 8 号楼 1 层布谷森林咖啡厅

请务必提前报名,好给您预留座位。

如果你正在运行 Swarm 模式的集群,或者只运行单台 Docker,你都会有下面的疑问:

我如何才能监控到它们都在干些什么?

这个问题的答案是“很不容易”。

你需要监控下面的参数:

  1. 容器的数量和状态。
  2. 一台容器是否已经移到另一个节点了,如果是,那是在什么时候,移动到哪个节点?
  3. 给定节点上运行着的容器数量。
  4. 一段时间内的通信峰值。
  5. 孤儿卷和网络(LCTT 译注:孤儿卷就是当你删除容器时忘记删除它的卷,这个卷就不会再被使用,但会一直占用资源)。
  6. 可用磁盘空间、可用 inode 数。
  7. 容器数量与连接在 docker0docker_gwbridge 上的虚拟网卡数量不一致(LCTT 译注:当 docker 启动时,它会在宿主机器上创建一个名为 docker0 的虚拟网络接口)。
  8. 开启和关闭 Swarm 节点。
  9. 收集并集中处理日志。

本文的目标是介绍 Elasticsearch + Kibana + cAdvisor 的用法,使用它们来收集 Docker 容器的参数,分析数据并产生可视化报表。

阅读本文后你可以发现有一个监控仪表盘能够部分解决上述列出的问题。但如果只是使用 cAdvisor,有些参数就无法显示出来,比如 Swarm 模式的节点。

如果你有一些 cAdvisor 或其他工具无法解决的特殊需求,我建议你开发自己的数据收集器和数据处理器(比如 Beats),请注意我不会演示如何使用 Elasticsearch 来集中收集 Docker 容器的日志。

“你要如何才能监控到 Swarm 模式集群里面发生了什么事情?要做到这点很不容易。” —— @fntlnz

我们为什么要监控容器?

想象一下这个经典场景:你在管理一台或多台虚拟机,你把 tmux 工具用得很溜,用各种 session 事先设定好了所有基础的东西,包括监控。然后生产环境出问题了,你使用 tophtopiotopjnettop 各种 top 来排查,然后你准备好修复故障。

现在重新想象一下你有 3 个节点,包含 50 台容器,你需要在一个地方查看整洁的历史数据,这样你知道问题出在哪个地方,而不是把你的生命浪费在那些字符界面来赌你可以找到问题点。

什么是 Elastic Stack ?

Elastic Stack 就一个工具集,包括以下工具:

  • Elasticsearch
  • Kibana
  • Logstash
  • Beats

我们会使用其中一部分工具,比如使用 Elasticsearch 来分析基于 JSON 格式的文本,以及使用 Kibana 来可视化数据并产生报表。

另一个重要的工具是 Beats,但在本文中我们还是把精力放在容器上,官方的 Beats 工具不支持 Docker,所以我们选择原生兼容 Elasticsearch 的 cAdvisor。

cAdvisor 工具负责收集、整合正在运行的容器数据,并导出报表。在本文中,这些报表被到入到 Elasticsearch 中。

cAdvisor 有两个比较酷的特性:

  • 它不只局限于 Docker 容器。
  • 它有自己的 Web 服务器,可以简单地显示当前节点的可视化报表。

设置测试集群,或搭建自己的基础架构

和我以前的文章一样,我习惯提供一个简单的脚本,让读者不用花很多时间就能部署好和我一样的测试环境。你可以使用以下(非生产环境使用的)脚本来搭建一个 Swarm 模式的集群,其中一个容器运行着 Elasticsearch。

如果你有充足的时间和经验,你可以 搭建自己的基础架构 Bring Your Own Infrastructure,BYOI

如果要继续阅读本文,你需要:

  • 运行 Docker 进程的一个或多个节点(docker 版本号大于等于 1.12)。
  • 至少有一个独立运行的 Elasticsearch 节点(版本号 2.4.X)。

重申一下,此 Elasticsearch 集群环境不能放在生产环境中使用。生产环境也不推荐使用单节点集群,所以如果你计划安装一个生产环境,请参考 Elastic 指南

对喜欢尝鲜的用户的友情提示

我就是一个喜欢尝鲜的人(当然我也已经在生产环境中使用了最新的 alpha 版本),但是在本文中,我不会使用最新的 Elasticsearch 5.0.0 alpha 版本,我还不是很清楚这个版本的功能,所以我不想成为那个引导你们出错的关键。

所以本文中涉及的 Elasticsearch 版本为最新稳定版 2.4.0。

测试集群部署脚本

前面已经说过,我提供这个脚本给你们,让你们不必费神去部署 Swarm 集群和 Elasticsearch,当然你也可以跳过这一步,用你自己的 Swarm 模式引擎和你自己的 Elasticserch 节点。

执行这段脚本之前,你需要:

创建集群的脚本

现在万事俱备,你可以把下面的代码拷到 create-cluster.sh 文件中:

#!/usr/bin/env bash
#
# Create a Swarm Mode cluster with a single master and a configurable number of workers

workers=${WORKERS:-"worker1 worker2"}

#######################################
# Creates a machine on Digital Ocean
# Globals:
#   DO_ACCESS_TOKEN The token needed to access DigitalOcean's API
# Arguments:
#   $1 the actual name to give to the machine
#######################################
create_machine() {
  docker-machine create \
    -d digitalocean \
    --digitalocean-access-token=$DO_ACCESS_TOKEN \
    --digitalocean-size 2gb \
    $1
}

#######################################
# Executes a command on the specified machine
# Arguments:
#   $1     The machine on which to run the command
#   $2..$n The command to execute on that machine
#######################################
machine_do() {
  docker-machine ssh $@
}

main() {

  if [ -z "$DO_ACCESS_TOKEN" ]; then
    echo "Please export a DigitalOcean Access token: https://cloud.digitalocean.com/settings/api/tokens/new"
    echo "export DO_ACCESS_TOKEN=<yourtokenhere>"
    exit 1
  fi

  if [ -z "$WORKERS" ]; then
    echo "You haven't provided your workers by setting the \$WORKERS environment variable, using the default ones: $workers"
  fi

  # Create the first and only master
  echo "Creating the master"

  create_machine master1

  master_ip=$(docker-machine ip master1)

  # Initialize the swarm mode on it
  echo "Initializing the swarm mode"
  machine_do master1 docker swarm init --advertise-addr $master_ip

  # Obtain the token to allow workers to join
  worker_tkn=$(machine_do master1 docker swarm join-token -q worker)
  echo "Worker token: ${worker_tkn}"

  # Create and join the workers
  for worker in $workers; do
    echo "Creating worker ${worker}"
    create_machine $worker
    machine_do $worker docker swarm join --token $worker_tkn $master_ip:2377
  done
}

main $@

赋予它可执行权限:

chmod +x create-cluster.sh

创建集群

如文件名所示,我们可以用它来创建集群。默认情况下这个脚本会创建一个 master 和两个 worker,如果你想修改 worker 个数,可以设置环境变量 WORKERS。

现在就来创建集群吧。

./create-cluster.sh

你可以出去喝杯咖啡,因为这需要花点时间。

最后集群部署好了。

现在为了验证 Swarm 模式集群已经正常运行,我们可以通过 ssh 登录进 master:

docker-machine ssh master1

然后列出集群的节点:

docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
26fi3wiqr8lsidkjy69k031w2 *  master1   Ready   Active        Leader
dyluxpq8sztj7kmwlzs51u4id    worker2   Ready   Active
epglndegvixag0jztarn2lte8    worker1   Ready   Active

安装 Elasticsearch 和 Kibana

注意,从现在开始所有的命令都运行在主节点 master1 上。

在生产环境中,你可能会把 Elasticsearch 和 Kibana 安装在一个单独的、大小合适的实例集合中。但是在我们的实验中,我们还是把它们和 Swarm 模式集群安装在一起。

为了将 Elasticsearch 和 cAdvisor 连通,我们需要创建一个自定义的网络,因为我们使用了集群,并且容器可能会分布在不同的节点上,我们需要使用 overlay 网络(LCTT 译注:overlay 网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在 IP 报文之上的新的数据格式,是目前最主流的容器跨节点数据传输和路由方案)。

也许你会问,“为什么还要网络?我们不是可以用 link 吗?” 请考虑一下,自从引入用户定义网络后,link 机制就已经过时了。

以下内容摘自 Docker 文档

在 Docker network 特性出来以前,你可以使用 Docker link 特性实现容器互相发现、安全通信。而在 network 特性出来以后,你还可以使用 link,但是当容器处于默认桥接网络或用户自定义网络时,它们的表现是不一样的。

现在创建 overlay 网络,名称为 monitoring:

docker network create monitoring -d overlay

Elasticsearch 容器

docker service create --network=monitoring \
  --mount type=volume,target=/usr/share/elasticsearch/data \
  --constraint node.hostname==worker1 \
  --name elasticsearch elasticsearch:2.4.0

注意 Elasticsearch 容器被限定在 worker1 节点,这是因为它运行时需要依赖 worker1 节点上挂载的卷。

Kibana 容器

docker service create --network=monitoring --name kibana -e ELASTICSEARCH_URL="http://elasticsearch:9200" -p 5601:5601 kibana:4.6.0

如你所见,我们启动这两个容器时,都让它们加入 monitoring 网络,这样一来它们可以通过名称(如 Kibana)被相同网络的其他服务访问。

现在,通过 routing mesh 机制,我们可以使用浏览器访问服务器的 IP 地址来查看 Kibana 报表界面。

获取 master1 实例的公共 IP 地址:

docker-machine ip master1

打开浏览器输入地址:http://[master1 的 ip 地址]:5601/status

所有项目都应该是绿色:

让我们接下来开始收集数据!

收集容器的运行数据

收集数据之前,我们需要创建一个服务,以全局模式运行 cAdvisor,为每个有效节点设置一个定时任务。

这个服务与 Elasticsearch 处于相同的网络,以便于 cAdvisor 可以推送数据给 Elasticsearch。

docker service create --network=monitoring --mode global --name cadvisor \
  --mount type=bind,source=/,target=/rootfs,readonly=true \
  --mount type=bind,source=/var/run,target=/var/run,readonly=false \
  --mount type=bind,source=/sys,target=/sys,readonly=true \
  --mount type=bind,source=/var/lib/docker/,target=/var/lib/docker,readonly=true \
  google/cadvisor:latest \
  -storage_driver=elasticsearch \
  -storage_driver_es_host="http://elasticsearch:9200"
注意:如果你想配置 cAdvisor 选项,参考这里

现在 cAdvisor 在发送数据给 Elasticsearch,我们通过定义一个索引模型来检索 Kibana 中的数据。有两种方式可以做到这一点:通过 Kibana 或者通过 API。在这里我们使用 API 方式实现。

我们需要在一个连接到 monitoring 网络的正在运行的容器中运行索引创建命令,你可以在 cAdvisor 容器中拿到 shell,不幸的是 Swarm 模式在开启服务时会在容器名称后面附加一个唯一的 ID 号,所以你需要手动指定 cAdvisor 容器的名称。

拿到 shell:

docker exec -ti <cadvisor-container-name> sh

创建索引:

curl -XPUT http://elasticsearch:9200/.kibana/index-pattern/cadvisor -d '{"title" : "cadvisor*",  "timeFieldName": "container_stats.timestamp"}'

如果你够懒,可以只执行下面这一句:

docker exec $(docker ps | grep cadvisor | awk '{print $1}' | head -1) curl -XPUT http://elasticsearch:9200/.kibana/index-pattern/cadvisor -d '{"title" : "cadvisor*",  "timeFieldName": "container_stats.timestamp"}'

把数据汇总成报表

你现在可以使用 Kibana 来创建一份美观的报表了。但是不要着急,我为你们建了一份报表和一些图形界面来方便你们入门。

访问 Kibana 界面 => Setting => Objects => Import,然后选择包含以下内容的 JSON 文件,就可以导入我的配置信息了:

[
  {
    "_id": "cAdvisor",
    "_type": "dashboard",
    "_source": {
      "title": "cAdvisor",
      "hits": 0,
      "description": "",
      "panelsJSON": "[{\"id\":\"Filesystem-usage\",\"type\":\"visualization\",\"panelIndex\":1,\"size_x\":6,\"size_y\":3,\"col\":1,\"row\":1},{\"id\":\"Memory-[Node-equal->Container]\",\"type\":\"visualization\",\"panelIndex\":2,\"size_x\":6,\"size_y\":4,\"col\":7,\"row\":4},{\"id\":\"memory-usage-by-machine\",\"type\":\"visualization\",\"panelIndex\":3,\"size_x\":6,\"size_y\":6,\"col\":1,\"row\":4},{\"id\":\"CPU-Total-Usage\",\"type\":\"visualization\",\"panelIndex\":4,\"size_x\":6,\"size_y\":5,\"col\":7,\"row\":8},{\"id\":\"Network-RX-TX\",\"type\":\"visualization\",\"panelIndex\":5,\"size_x\":6,\"size_y\":3,\"col\":7,\"row\":1}]",
      "optionsJSON": "{\"darkTheme\":false}",
      "uiStateJSON": "{}",
      "version": 1,
      "timeRestore": false,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}}}]}"
      }
    }
  },
  {
    "_id": "Network",
    "_type": "search",
    "_source": {
      "title": "Network",
      "description": "",
      "hits": 0,
      "columns": [
        "machine_name",
        "container_Name",
        "container_stats.network.name",
        "container_stats.network.interfaces",
        "container_stats.network.rx_bytes",
        "container_stats.network.rx_packets",
        "container_stats.network.rx_dropped",
        "container_stats.network.rx_errors",
        "container_stats.network.tx_packets",
        "container_stats.network.tx_bytes",
        "container_stats.network.tx_dropped",
        "container_stats.network.tx_errors"
      ],
      "sort": [
        "container_stats.timestamp",
        "desc"
      ],
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"cadvisor*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"highlight\":{\"pre_tags\":[\"@kibana-highlighted-field@\"],\"post_tags\":[\"@/kibana-highlighted-field@\"],\"fields\":{\"*\":{}},\"fragment_size\":2147483647},\"filter\":[]}"
      }
    }
  },
  {
    "_id": "Filesystem-usage",
    "_type": "visualization",
    "_source": {
      "title": "Filesystem usage",
      "visState": "{\"title\":\"Filesystem usage\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"defaultYExtents\":false,\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"container_stats.filesystem.usage\",\"customLabel\":\"USED\"}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"machine_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":false}},{\"id\":\"3\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"container_stats.filesystem.capacity\",\"customLabel\":\"AVAIL\"}},{\"id\":\"4\",\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"container_stats.filesystem.device\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}",
      "uiStateJSON": "{\"vis\":{\"colors\":{\"Average container_stats.filesystem.available\":\"#E24D42\",\"Average container_stats.filesystem.base_usage\":\"#890F02\",\"Average container_stats.filesystem.capacity\":\"#3F6833\",\"Average container_stats.filesystem.usage\":\"#E24D42\",\"USED\":\"#BF1B00\",\"AVAIL\":\"#508642\"}}}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"cadvisor*\",\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}},\"filter\":[]}"
      }
    }
  },
  {
    "_id": "CPU-Total-Usage",
    "_type": "visualization",
    "_source": {
      "title": "CPU Total Usage",
      "visState": "{\"title\":\"CPU Total Usage\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"container_stats.cpu.usage.total\"}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"container_stats.timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"container_Name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"4\",\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"machine_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":true}}],\"listeners\":{}}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"cadvisor*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
      }
    }
  },
  {
    "_id": "memory-usage-by-machine",
    "_type": "visualization",
    "_source": {
      "title": "Memory [Node]",
      "visState": "{\"title\":\"Memory [Node]\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"container_stats.memory.usage\"}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"container_stats.timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"cadvisor*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
      }
    }
  },
  {
    "_id": "Network-RX-TX",
    "_type": "visualization",
    "_source": {
      "title": "Network RX TX",
      "visState": "{\"title\":\"Network RX TX\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":true,\"addTooltip\":true,\"defaultYExtents\":false,\"mode\":\"stacked\",\"scale\":\"linear\",\"setYExtents\":false,\"shareYAxis\":true,\"times\":[],\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"container_stats.network.rx_bytes\",\"customLabel\":\"RX\"}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"container_stats.timestamp\",\"interval\":\"s\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"container_stats.network.tx_bytes\",\"customLabel\":\"TX\"}}],\"listeners\":{}}",
      "uiStateJSON": "{\"vis\":{\"colors\":{\"RX\":\"#EAB839\",\"TX\":\"#BF1B00\"}}}",
      "description": "",
      "savedSearchId": "Network",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"filter\":[]}"
      }
    }
  },
  {
    "_id": "Memory-[Node-equal->Container]",
    "_type": "visualization",
    "_source": {
      "title": "Memory [Node=>Container]",
      "visState": "{\"title\":\"Memory [Node=>Container]\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"container_stats.memory.usage\"}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"container_stats.timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"container_Name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"4\",\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"machine_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"row\":true}}],\"listeners\":{}}",
      "uiStateJSON": "{}",
      "description": "",
      "version": 1,
      "kibanaSavedObjectMeta": {
        "searchSourceJSON": "{\"index\":\"cadvisor*\",\"query\":{\"query_string\":{\"query\":\"* NOT container_Name.raw: \\\\\\\"/\\\\\\\" AND NOT container_Name.raw: \\\\\\\"/docker\\\\\\\"\",\"analyze_wildcard\":true}},\"filter\":[]}"
      }
    }
  }
]

这里还有很多东西可以玩,你也许想自定义报表界面,比如添加内存页错误状态,或者收发包的丢包数。如果你能实现开头列表处我没能实现的项目,那也是很好的。

总结

正确监控需要大量时间和精力,容器的 CPU、内存、IO、网络和磁盘,监控的这些参数还只是整个监控项目中的沧海一粟而已。

我不知道你做到了哪一阶段,但接下来的任务也许是:

  • 收集运行中的容器的日志
  • 收集应用的日志
  • 监控应用的性能
  • 报警
  • 监控健康状态

如果你有意见或建议,请留言。祝你玩得开心。

现在你可以关掉这些测试系统了:

docker-machine rm master1 worker{1,2}

via: https://blog.codeship.com/monitoring-docker-containers-with-elasticsearch-and-cadvisor/

作者:Lorenzo Fontana 译者:bazz2 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

聊天机器人(Bot) 是一种像 Slack 一样的实用的互动聊天服务方式。如果你之前从来没有建立过聊天机器人,那么这篇文章提供了一个简单的入门指南,告诉你如何用 Python 结合 Slack API 建立你第一个聊天机器人。

我们通过搭建你的开发环境, 获得一个 Slack API 的聊天机器人令牌,并用 Pyhon 开发一个简单聊天机器人。

我们所需的工具

我们的聊天机器人我们将它称作为“StarterBot”,它需要 Python 和 Slack API。要运行我们的 Python 代码,我们需要:

当你在本教程中进行构建时,Slack API 文档 是很有用的。

本教程中所有的代码都放在 slack-starterbot 公共库里,并以 MIT 许可证开源。

搭建我们的环境

我们现在已经知道我们的项目需要什么样的工具,因此让我们来搭建我们所的开发环境吧。首先到终端上(或者 Windows 上的命令提示符)并且切换到你想要存储这个项目的目录。在那个目录里,创建一个新的 virtualenv 以便和其他的 Python 项目相隔离我们的应用程序依赖关系。

virtualenv starterbot

激活 virtualenv:

source starterbot/bin/activate

你的提示符现在应该看起来如截图:

已经激活的 starterbot 的 virtualenv的命令提示符

这个官方的 slack 客户端 API 帮助库是由 Slack 建立的,它可以通过 Slack 通道发送和接收消息。通过这个 pip 命令安装 slackclient 库:

pip install slackclient

pip 命令完成时,你应该看到类似这样的输出,并返回提示符。

在已经激活的 virtualenv 用 pip 安装 slackclient 的输出

我们也需要为我们的 Slack 项目获得一个访问令牌,以便我们的聊天机器人可以用它来连接到 Slack API。

Slack 实时消息传递(RTM)API

Slack 允许程序通过一个 Web API 来访问他们的消息传递通道。去这个 Slack Web API 页面 注册建立你自己的 Slack 项目。你也可以登录一个你拥有管理权限的已有账号。

使用 Web API页面的右上角登录按钮

登录后你会到达 聊天机器人用户页面

定制聊天机器人用户页面

给你的聊天机器人起名为“starterbot”然后点击 “Add bot integration” 按钮。

添加一个bot integration 并起名为“starterbot”

这个页面将重新加载,你将看到一个新生成的访问令牌。你还可以将标志改成你自己设计的。例如我给的这个“Full Stack Python”标志。

为你的新 Slack 聊天机器人复制和粘贴访问令牌

在页面底部点击“Save Integration”按钮。你的聊天机器人现在已经准备好连接 Slack API。

Python 开发人员的一个常见的做法是以环境变量输出秘密令牌。输出的 Slack 令牌名字为SLACK_BOT_TOKEN

export SLACK_BOT_TOKEN='你的 slack 令牌粘帖在这里'

好了,我们现在得到了将这个 Slack API 用作聊天机器人的授权。

我们建立聊天机器人还需要更多信息:我们的聊天机器人的 ID。接下来我们将会写一个简短的脚本,从 Slack API 获得该 ID。

获得我们聊天机器人的 ID

这是最后写一些 Python 代码的时候了! 我们编写一个简短的 Python 脚本获得 StarterBot 的 ID 来热身一下。这个 ID 基于 Slack 项目而不同。

我们需要该 ID,当解析从 Slack RTM 上发给 StarterBot 的消息时,它用于对我们的应用验明正身。我们的脚本也会测试我们 SLACK_BOT_TOKEN 环境变量是否设置正确。

建立一个命名为 printbotid.py 的新文件,并且填入下面的代码:

import os
from slackclient import SlackClient

BOT_NAME = 'starterbot'

slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))

if __name__ == "__main__":
    api_call = slack_client.api_call("users.list")
    if api_call.get('ok'):
        # retrieve all users so we can find our bot
        users = api_call.get('members')
        for user in users:
            if 'name' in user and user.get('name') == BOT_NAME:
                print("Bot ID for '" + user['name'] + "' is " + user.get('id'))
    else:
        print("could not find bot user with the name " + BOT_NAME)

我们的代码导入 SlackClient,并用我们设置的环境变量 SLACK_BOT_TOKEN 实例化它。 当该脚本通过 python 命令执行时,我们通过会访问 Slack API 列出所有的 Slack 用户并且获得匹配一个名字为“satrterbot”的 ID。

这个获得聊天机器人的 ID 的脚本我们仅需要运行一次。

python print_bot_id.py

当它运行为我们提供了聊天机器人的 ID 时,脚本会打印出简单的一行输出。

在你的 Slack 项目中用 Python 脚本打印 Slack 聊天机器人的 ID

复制这个脚本打印出的唯一 ID。并将该 ID 作为一个环境变量 BOT_ID 输出。

(starterbot)$ export BOT_ID='bot id returned by script'

这个脚本仅仅需要运行一次来获得聊天机器人的 ID。 我们现在可以在我们的运行 StarterBot 的 Python应用程序中使用这个 ID 。

编码我们的 StarterBot

现在我们拥有了写我们的 StarterBot 代码所需的一切。 创建一个新文件命名为 starterbot.py ,它包括以下代码。

import os
import time
from slackclient import SlackClient

osSlackClient 的导入我们看起来很熟悉,因为我们已经在 theprintbotid.py 中用过它们了。

通过我们导入的依赖包,我们可以使用它们获得环境变量值,并实例化 Slack 客户端。

# starterbot 的 ID 作为一个环境变量
BOT_ID = os.environ.get("BOT_ID")

# 常量
AT_BOT = "<@" + BOT_ID + ">:"
EXAMPLE_COMMAND = "do"

# 实例化 Slack 和 Twilio 客户端
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))

该代码通过我们以输出的环境变量 SLACK_BOT_TOKEN 实例化SlackClient` 客户端。

if __name__ == "__main__":
    READ_WEBSOCKET_DELAY = 1 # 1 从 firehose 读取延迟 1 秒
    if slack_client.rtm_connect():
        print("StarterBot connected and running!")
        while True:
            command, channel = parse_slack_output(slack_client.rtm_read())
            if command and channel:
                handle_command(command, channel)
            time.sleep(READ_WEBSOCKET_DELAY)
    else:
        print("Connection failed. Invalid Slack token or bot ID?")

Slack 客户端会连接到 Slack RTM API WebSocket,然后当解析来自 firehose 的消息时会不断循环。如果有任何发给 StarterBot 的消息,那么一个被称作 handle_command 的函数会决定做什么。

接下来添加两个函数来解析 Slack 的输出并处理命令。

def handle_command(command, channel):
    """
        Receives commands directed at the bot and determines if they
        are valid commands. If so, then acts on the commands. If not,
        returns back what it needs for clarification.
    """
    response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \
               "* command with numbers, delimited by spaces."
    if command.startswith(EXAMPLE_COMMAND):
        response = "Sure...write some more code then I can do that!"
    slack_client.api_call("chat.postMessage", channel=channel,
                          text=response, as_user=True)

def parse_slack_output(slack_rtm_output):
    """
        The Slack Real Time Messaging API is an events firehose.
        this parsing function returns None unless a message is
        directed at the Bot, based on its ID.
    """
    output_list = slack_rtm_output
    if output_list and len(output_list) > 0:
        for output in output_list:
            if output and 'text' in output and AT_BOT in output['text']:
                # 返回 @ 之后的文本,删除空格
                return output['text'].split(AT_BOT)[1].strip().lower(), \
                       output['channel']
    return None, None

parse_slack_output 函数从 Slack 接受信息,并且如果它们是发给我们的 StarterBot 时会作出判断。消息以一个给我们的聊天机器人 ID 的直接命令开始,然后交由我们的代码处理。目前只是通过 Slack 管道发布一个消息回去告诉用户去多写一些 Python 代码!

这是整个程序组合在一起的样子 (你也可以 在 GitHub 中查看该文件):

import os
import time
from slackclient import SlackClient

# starterbot 的 ID 作为一个环境变量
BOT_ID = os.environ.get("BOT_ID")

# 常量
AT_BOT = "<@" + BOT_ID + ">:"
EXAMPLE_COMMAND = "do"

# 实例化 Slack 和 Twilio 客户端
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))

def handle_command(command, channel):
    """
        Receives commands directed at the bot and determines if they
        are valid commands. If so, then acts on the commands. If not,
        returns back what it needs for clarification.
    """
    response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \
               "* command with numbers, delimited by spaces."
    if command.startswith(EXAMPLE_COMMAND):
        response = "Sure...write some more code then I can do that!"
    slack_client.api_call("chat.postMessage", channel=channel,
                          text=response, as_user=True)

def parse_slack_output(slack_rtm_output):
    """
        The Slack Real Time Messaging API is an events firehose.
        this parsing function returns None unless a message is
        directed at the Bot, based on its ID.
    """
    output_list = slack_rtm_output
    if output_list and len(output_list) > 0:
        for output in output_list:
            if output and 'text' in output and AT_BOT in output['text']:
                # 返回 @ 之后的文本,删除空格
                return output['text'].split(AT_BOT)[1].strip().lower(), \
                       output['channel']
    return None, None

if __name__ == "__main__":
    READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
    if slack_client.rtm_connect():
        print("StarterBot connected and running!")
        while True:
            command, channel = parse_slack_output(slack_client.rtm_read())
            if command and channel:
                handle_command(command, channel)
            time.sleep(READ_WEBSOCKET_DELAY)
    else:
        print("Connection failed. Invalid Slack token or bot ID?")

现在我们的代码已经有了,我们可以通过 python starterbot.py 来运行我们 StarterBot 的代码了。

当 StarterBot 开始运行而且连接到 API 的输出通道

在 Slack 中创建新通道,并且把 StarterBot 邀请进来,或者把 StarterBot 邀请进一个已经存在的通道中。

在 Slack 界面创建一个新通道并且邀请 StarterBot

现在在你的通道中给 StarterBot 发命令。

在你的 Slack 通道里给你的 StarterBot 发命令

如果你从聊天机器人得到的响应中遇见问题,你可能需要做一个修改。正如上面所写的这个教程,其中一行 AT_BOT = "<@" + BOT_ID + ">:",在“@starter”(你给你自己的聊天机器人起的名字)后需要一个冒号。从 AT_BOT 字符串后面移除:。Slack 似乎需要在@ 一个人名后加一个冒号,但这好像是有些不协调的。

结束

好吧,你现在已经获得一个简易的聊天机器人,你可以在代码中很多地方加入你想要创建的任何特性。

我们能够使用 Slack RTM API 和 Python 完成很多功能。看看通过这些文章你还可以学习到什么:

有问题? 通过 Twitter 联系我 @fullstackpython@mattmakai。 我在 GitHub 上的用户名是 mattmakai

这篇文章感兴趣? Fork 这个 GitHub 上的页面吧。


via: https://www.fullstackpython.com/blog/build-first-slack-bot-python.html

作者:Matt Makai 译者:jiajia9llinuxer 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出aa

正在为 Linux 桌面端找一个免费的 REST 客户端? 别睡不着觉了!试试 Insomnia

这个应用是跨平台的,可以工作在 Linux、macOS、Windows。开发者 Gregory Schier 告诉我们他创造这个应用是为了“帮助开发者处理和 REST API 的通信”

他还说,Insomnia 已经有大约10000 个活跃用户,9% 使用着 Linux.

“目前来说,Linux用户的反馈是非常积极的,因为类似的应用(反正不怎么样)通常不支持 Linux。”

Insomnia 的目标是“加速你的 API 测试工作流”,通过一个简洁的接口让你组织、运行、调试 HTTP 请求。

这款应用还包含一些其他的高级功能比如 Cookie 管理、全局环境、SSL 验证和代码段生成。

由于我不是一个开发者,没有办法第一时间的评价这款应用,也没办法告诉你的它的特性或指出任何比较重大的不足之处。

但是,我将这款应用告诉你,让你自己决定它,如果你正在寻找一个有着顺滑的用户界面的替代命令行工具,比如HTTPie,它可能是值得一试的。

下载 Linux 版 Insomnia 3.0

Insomnia 3.0 现在可以用在 Windows、macOS、Linux 上(不要和只能在 Chrome 上使用的 Insomnia v2.0 混淆)。

对于 Ubuntu 14.04 LTS 或更高版本,有一个安装包,它是一个跨发行版的安装包:

如果你想跟进这个应用的步伐,你可以在 Twitter 上关注它。


via: http://www.omgubuntu.co.uk/2016/09/insomnia-3-is-free-rest-client-for-linux

作者:JOEY-ELIJAH SNEDDON 译者:Bestony 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

人工智能 artificial intelligence,AI 是科技研究中最热门的方向之一。像 IBM、谷歌、微软、Facebook 和亚马逊等公司都在研发上投入大量的资金、或者收购那些在机器学习、神经网络、自然语言和图像处理等领域取得了进展的初创公司。考虑到人们对此感兴趣的程度,我们将不会惊讶于斯坦福的专家在人工智能报告中得出的结论:“越来越强大的人工智能应用,可能会对我们的社会和经济产生深远的积极影响,这将出现在从现在到 2030 年的时间段里。”

在最近的一篇文章中,我们概述了 45 个十分有趣或有前途的人工智能项目。在本文中,我们将聚焦于开源的人工智能工具,详细的了解下最著名的 15 个开源人工智能项目。

开源人工智能

以下这些开源人工智能应用都处于人工智能研究的最前沿。

1. Caffe

它是由贾扬清在加州大学伯克利分校的读博时创造的,Caffe 是一个基于表达体系结构和可扩展代码的深度学习框架。使它声名鹊起的是它的速度,这让它受到研究人员和企业用户的欢迎。根据其网站所言,它可以在一天之内只用一个 NVIDIA K40 GPU 处理 6000 万多个图像。它是由伯克利视野和学习中心(BVLC)管理的,并且由 NVIDIA 和亚马逊等公司资助来支持它的发展。

2. CNTK

它是 计算网络工具包 Computational Network Toolkit 的缩写,CNTK 是一个微软的开源人工智能工具。不论是在单个 CPU、单个 GPU、多个 GPU 或是拥有多个 GPU 的多台机器上它都有优异的表现。微软主要用它做语音识别的研究,但是它在机器翻译、图像识别、图像字幕、文本处理、语言理解和语言建模方面都有着良好的应用。

3. Deeplearning4j

Deeplearning4j 是一个 java 虚拟机(JVM)的开源深度学习库。它运行在分布式环境并且集成在 Hadoop 和 Apache Spark 中。这使它可以配置深度神经网络,并且它与 Java、Scala 和 其他 JVM 语言兼容。

这个项目是由一个叫做 Skymind 的商业公司管理的,它为这个项目提供支持、培训和一个企业的发行版。

4. DMTK

DMTK 分布式机器学习工具 Distributed Machine Learning Toolkit 的缩写,和 CNTK 一样,是微软的开源人工智能工具。作为设计用于大数据的应用程序,它的目标是更快的训练人工智能系统。它包括三个主要组件:DMTK 框架、LightLDA 主题模型算法和分布式(多义)字嵌入算法。为了证明它的速度,微软声称在一个八集群的机器上,它能够“用 100 万个主题和 1000 万个单词的词汇表(总共 10 万亿参数)训练一个主题模型,在一个文档中收集 1000 亿个符号,”。这一成绩是别的工具无法比拟的。

5. H20

相比起科研,H2O 更注重将 AI 服务于企业用户,因此 H2O 有着大量的公司客户,比如第一资本金融公司、思科、Nielsen Catalina、PayPal 和泛美都是它的用户。它声称任何人都可以利用机器学习和预测分析的力量来解决业务难题。它可以用于预测建模、风险和欺诈分析、保险分析、广告技术、医疗保健和客户情报。

它有两种开源版本:标准版 H2O 和 Sparking Water 版,它被集成在 Apache Spark 中。也有付费的企业用户支持。

6. Mahout

它是 Apache 基金会项目,Mahout 是一个开源机器学习框架。根据它的网站所言,它有着三个主要的特性:一个构建可扩展算法的编程环境、像 Spark 和 H2O 一样的预制算法工具和一个叫 Samsara 的矢量数学实验环境。使用 Mahout 的公司有 Adobe、埃森哲咨询公司、Foursquare、英特尔、领英、Twitter、雅虎和其他许多公司。其网站列了出第三方的专业支持。

7. MLlib

由于其速度,Apache Spark 成为一个最流行的大数据处理工具。MLlib 是 Spark 的可扩展机器学习库。它集成了 Hadoop 并可以与 NumPy 和 R 进行交互操作。它包括了许多机器学习算法如分类、回归、决策树、推荐、集群、主题建模、功能转换、模型评价、ML 管道架构、ML 持久、生存分析、频繁项集和序列模式挖掘、分布式线性代数和统计。

8. NuPIC

Numenta 公司管理的 NuPIC 是一个基于 分层暂时记忆 Hierarchical Temporal Memory,HTM 理论的开源人工智能项目。从本质上讲,HTM 试图创建一个计算机系统来模仿人类大脑皮层。他们的目标是创造一个 “在许多认知任务上接近或者超越人类认知能力” 的机器。

除了开源许可,Numenta 还提供 NuPic 的商业许可协议,并且它还提供技术专利的许可证。

9. OpenNN

作为一个为开发者和科研人员设计的具有高级理解力的人工智能,OpenNN 是一个实现神经网络算法的 c++ 编程库。它的关键特性包括深度的架构和快速的性能。其网站上可以查到丰富的文档,包括一个解释了神经网络的基本知识的入门教程。OpenNN 的付费支持由一家从事预测分析的西班牙公司 Artelnics 提供。

10. OpenCyc

由 Cycorp 公司开发的 OpenCyc 提供了对 Cyc 知识库的访问和常识推理引擎。它拥有超过 239,000 个条目,大约 2,093,000 个三元组和大约 69,000 owl:这是一种类似于链接到外部语义库的命名空间。它在富领域模型、语义数据集成、文本理解、特殊领域的专家系统和游戏 AI 中有着良好的应用。该公司还提供另外两个版本的 Cyc:一个可免费的用于科研但是不开源,和一个提供给企业的但是需要付费。

11. Oryx 2

构建在 Apache Spark 和 Kafka 之上的 Oryx 2 是一个专门针对大规模机器学习的应用程序开发框架。它采用一个独特的三层 λ 架构。开发者可以使用 Orys 2 创建新的应用程序,另外它还拥有一些预先构建的应用程序可以用于常见的大数据任务比如协同过滤、分类、回归和聚类。大数据工具供应商 Cloudera 创造了最初的 Oryx 1 项目并且一直积极参与持续发展。

12. PredictionIO

今年的二月,Salesforce 收购了 PredictionIO,接着在七月,它将该平台和商标贡献给 Apache 基金会,Apache 基金会将其列为孵育计划。所以当 Salesforce 利用 PredictionIO 技术来提升它的机器学习能力时,成效将会同步出现在开源版本中。它可以帮助用户创建带有机器学习功能的预测引擎,这可用于部署能够实时动态查询的 Web 服务。

13. SystemML

最初由 IBM 开发, SystemML 现在是一个 Apache 大数据项目。它提供了一个高度可伸缩的平台,可以实现高等数学运算,并且它的算法用 R 或一种类似 python 的语法写成。企业已经在使用它来跟踪汽车维修客户服务、规划机场交通和连接社会媒体数据与银行客户。它可以在 Spark 或 Hadoop 上运行。

14. TensorFlow

TensorFlow 是一个谷歌的开源人工智能工具。它提供了一个使用数据流图进行数值计算的库。它可以运行在多种不同的有着单或多 CPU 和 GPU 的系统,甚至可以在移动设备上运行。它拥有深厚的灵活性、真正的可移植性、自动微分功能,并且支持 Python 和 c++。它的网站拥有十分详细的教程列表来帮助开发者和研究人员沉浸于使用或扩展他的功能。

15. Torch

Torch 将自己描述为:“一个优先使用 GPU 的拥有机器学习算法广泛支持的科学计算框架”,它的特点是灵活性和速度。此外,它可以很容易的通过软件包用于机器学习、计算机视觉、信号处理、并行处理、图像、视频、音频和网络等方面。它依赖一个叫做 LuaJIT 的脚本语言,而 LuaJIT 是基于 Lua 的。


via: http://www.datamation.com/open-source/slideshows/15-top-open-source-artificial-intelligence-tools.html

作者:Cynthia Harvey 译者:Chao-zhi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

从 awk 系列开始直到第 12 部分,我们都是在命令行或者脚本文件里写一些简短的 awk 命令和程序。

然而 awk 和 shell 一样也是一个解释型语言。通过从开始到现在的一系列的学习,你现在能写可以执行的 awk 脚本了。

和写 shell 脚本差不多,awk 脚本以下面这一行开头:

#! /path/to/awk/utility -f

例如在我的系统上,awk 工具安装在 /user/bin/awk 目录,所以我的 awk 脚本以如下内容作为开头:

#! /usr/bin/awk -f

上面一行的解释如下:

  • #! ,称为 释伴 Shebang ,指明使用那个解释器来执行脚本中的命令
  • /usr/bin/awk ,即解释器
  • -f ,解释器选项,用来指定读取的程序文件

说是这么说,现在从下面的简单例子开始,让我们深入研究一些可执行的 awk 脚本。使用你最喜欢的编辑器创建一个新文件,像下面这样:

$ vi script.awk

然后把下面代码粘贴到文件中:

#!/usr/bin/awk -f
BEGIN { printf "%s\n","Writing my first awk executable script!" }

保存文件后退出,然后执行下面命令,使得脚本可执行:

$ chmod +x script.awk

然后,执行它:

$ ./script.awk

输出样例:

Writing my first awk executable script!

一个严格的程序员一定会问:“注释呢?”。是的,你可以在 awk 脚本中包含注释。在代码中写注释是一种良好的编程习惯。

它有利于其它程序员阅读你的代码,理解程序文件或者脚本中每一部分的功能。

所以,你可以像下面这样在脚本中增加注释:

#!/usr/bin/awk -f
# 这是如何在 awk 中写注释的示例
# 使用特殊模式 BEGIN 来输出一句话
BEGIN { printf "%s\n","Writing my first awk executable script!" }

接下来我们看一个读文件的例子。我们想从帐号文件 /etc/passwd 中查找一个叫 aaronkilik 的用户,然后像下面这样打印用户名、用户的 ID、用户的 GID (LCTT译注:组 ID):

下面是我们脚本文件的内容,文件名为 second.awk。

#! /usr/bin/awk -f
# 使用 BEGIN 指定字符来设定 FS 内置变量
BEGIN { FS=":" }
# 搜索用户名 aaronkilik 并输出账号细节
/aaronkilik/ { print "Username :",$1,"User ID :",$3,"User GID :",$4 }

保存文件后退出,使得脚本可执行,然后像下面这样执行它:

$ chmod +x second.awk
$ ./second.awk /etc/passwd

输出样例:

Username : aaronkilik User ID : 1000 User GID : 1000

在下面最后一个例子中,我们将使用 do while 语句来打印数字 0-10:

下面是我们脚本文件的内容,文件名为 do.awk。

#! /usr/bin/awk -f
#printing from 0-10 using a do while statement
#do while statement
BEGIN {
#initialize a counter
x=0
do {
print x;
x+=1;
}
while(x<=10)
}

保存文件后,像之前操作一样使得脚本可执行。然后,运行它:

$ chmod +x do.awk
$ ./do.awk

输出样例

0
1
2
3
4
5
6
7
8
9
10

总结

我们已经到达这个精彩的 awk 系列的最后,我希望你从整个 13 个章节中学到了很多知识,把这些当作你 awk 编程语言的入门指导。

我一开始就提到过,awk 是一个完整的文本处理语言,所以你可以学习很多 awk 编程语言的其它方面,例如环境变量、数组、函数(内置的或者用户自定义的),等等。

awk 编程还有其它内容需要学习和掌握,所以在文末我提供了一些重要的在线资源的链接,你可以利用他们拓展你的 awk 编程技能。但这不是必须的,你也可以阅读一些关于 awk 的书籍。

如果你任何想要分享的想法或者问题,在下面留言。记得保持关注我们,会有更多的精彩内容。


via: http://www.tecmint.com/write-shell-scripts-in-awk-programming/

作者:Aaron Kili 译者:chunyang-wen 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出