2016年4月

我的上一篇文章里, 我介绍了 Linux 容器背后的技术的概念。我写了我知道的一切。容器对我来说也是比较新的概念。我写这篇文章的目的就是鼓励我真正的来学习这些东西。

我打算在使用中学习。首先实践,然后上手并记录下我是怎么走过来的。我假设这里肯定有很多像 "Hello World" 这种类型的知识帮助我快速的掌握基础。然后我能够更进一步,构建一个微服务容器或者其它东西。

我想,它应该不会有多难的。

但是我错了。

可能对某些人来说这很简单,因为他们在运维工作方面付出了大量的时间。但是对我来说实际上是很困难的,可以从我在Facebook 上的状态展示出来的挫折感就可以看出了。

但是还有一个好消息:我最终搞定了。而且它工作的还不错。所以我准备分享向你分享我如何制作我的第一个微服务容器。我的痛苦可能会节省你不少时间呢。

如果你曾经发现你也处于过这种境地,不要害怕:像我这样的人都能搞定,所以你也肯定行。

让我们开始吧。

一个缩略图微服务

我设计的微服务在理论上很简单。以 JPG 或者 PNG 格式在 HTTP 终端发布一张数字照片,然后获得一个100像素宽的缩略图。

下面是它的流程:

container-diagram-0

我决定使用 NodeJS 作为我的开发语言,使用 ImageMagick 来转换缩略图。

我的服务的第一版的逻辑如下所示:

container-diagram-1

我下载了 Docker Toolbox,用它安装了 Docker 的快速启动终端(Docker Quickstart Terminal)。Docker 快速启动终端使得创建容器更简单了。终端会启动一个装好了 Docker 的 Linux 虚拟机,它允许你在一个终端里运行 Docker 命令。

虽然在我的例子里,我的操作系统是 Mac OS X。但是 Windows 下也有相同的工具。

我准备使用 Docker 快速启动终端里为我的微服务创建一个容器镜像,然后从这个镜像运行容器。

Docker 快速启动终端就运行在你使用的普通终端里,就像这样:

container-diagram-2

第一个小问题和第一个大问题

我用 NodeJS 和 ImageMagick 瞎搞了一通,然后让我的服务在本地运行起来了。

然后我创建了 Dockerfile,这是 Docker 用来构建容器的配置脚本。(我会在后面深入介绍构建过程和 Dockerfile)

这是我运行 Docker 快速启动终端的命令:

$ docker build -t thumbnailer:0.1

获得如下回应:

docker: "build" requires 1 argument.

呃。

我估摸着过了15分钟我才反应过来:我忘记了在末尾参数输入一个点.

正确的指令应该是这样的:

$ docker build -t thumbnailer:0.1 .

但是这不是我遇到的最后一个问题。

我让这个镜像构建好了,然后我在 Docker 快速启动终端输入了 run 命令来启动容器,名字叫 thumbnailer:0.1:

$ docker run -d -p 3001:3000 thumbnailer:0.1

参数 -p 3001:3000 让 NodeJS 微服务在 Docker 内运行在端口3000,而绑定在宿主主机上的3001。

到目前看起来都很好,对吧?

错了。事情要马上变糟了。

我通过运行 docker-machine 命令为这个 Docker 快速启动终端里创建的虚拟机指定了 ip 地址:

$ docker-machine ip default

这句话返回了默认虚拟机的 IP 地址,它运行在 Docker 快速启动终端里。在我这里,这个 ip 地址是 192.168.99.100。

我浏览网页 http://192.168.99.100:3001/ ,然后找到了我创建的上传图片的网页:

container-diagram-3

我选择了一个文件,然后点击上传图片的按钮。

但是它并没有工作。

终端告诉我他无法找到我的微服务需要的 /upload 目录。

现在,你要知道,我已经在此耗费了将近一天的时间-从浪费时间到研究问题。我此时感到了一些挫折感。

然后灵光一闪。某人记起来微服务不应该自己做任何数据持久化的工作!保存数据应该是另一个服务的工作。

所以容器找不到目录 /upload 的原因到底是什么?这个问题的根本就是我的微服务在基础设计上就有问题。

让我们看看另一幅图:

container-diagram-4

我为什么要把文件保存到磁盘?微服务按理来说是很快的。为什么不能让我的全部工作都在内存里完成?使用内存缓冲可以解决“找不到目录”这个问题,而且可以提高我的应用的性能。

这就是我现在所做的。下面是我的计划:

container-diagram-5

这是我用 NodeJS 写的在内存运行、生成缩略图的代码:

// Bind to the packages
var express = require('express');
var router = express.Router();
var path = require('path'); // used for file path
var im = require("imagemagick");

// Simple get that allows you test that you can access the thumbnail process
router.get('/', function (req, res, next) {
 res.status(200).send('Thumbnailer processor is up and running');
});

// This is the POST handler. It will take the uploaded file and make a thumbnail from the 
// submitted byte array. I know, it's not rocket science, but it serves a purpose
router.post('/', function (req, res, next) {
 req.pipe(req.busboy);
 req.busboy.on('file', function (fieldname, file, filename) {
   var ext = path.extname(filename)

   // Make sure that only png and jpg is allowed 
   if(ext.toLowerCase() != '.jpg' && ext.toLowerCase() != '.png'){
     res.status(406).send("Service accepts only jpg or png files");
   }

   var bytes = [];

   // put the bytes from the request into a byte array 
   file.on('data', function(data) {
     for (var i = 0; i < data.length; ++i) {
       bytes.push(data[i]);
     }
     console.log('File [' + fieldname + '] got bytes ' + bytes.length + ' bytes');
   });

   // Once the request is finished pushing the file bytes into the array, put the bytes in 
   // a buffer and process that buffer with the imagemagick resize function
   file.on('end', function() {
     var buffer = new Buffer(bytes,'binary');
     console.log('Bytes  got ' + bytes.length + ' bytes');

     //resize
     im.resize({
         srcData: buffer,
         height: 100
     }, function(err, stdout, stderr){
       if (err){
         throw err;
       }
       // get the extension without the period
       var typ = path.extname(filename).replace('.','');
       res.setHeader("content-type", "image/" + typ);
       res.status(200);
       // send the image back as a response
       res.send(new Buffer(stdout,'binary'));
     });
   });
 });
});

module.exports = router;

好了,一切回到了正轨,已经可以在我的本地机器正常工作了。我该去休息了。

但是,在我测试把这个微服务当作一个普通的 Node 应用运行在本地时...

Containers Hard

它工作的很好。现在我要做的就是让它在容器里面工作。

第二天我起床后喝点咖啡,然后创建一个镜像——这次没有忘记那个"."!

$ docker build -t thumbnailer:01 .

我从缩略图项目的根目录开始构建。构建命令使用了根目录下的 Dockerfile。它是这样工作的:把 Dockerfile 放到你想构建镜像的地方,然后系统就默认使用这个 Dockerfile。

下面是我使用的Dockerfile 的内容:

FROM ubuntu:latest
MAINTAINER [email protected]

RUN apt-get update
RUN apt-get install -y nodejs nodejs-legacy npm
RUN apt-get install imagemagick libmagickcore-dev libmagickwand-dev
RUN apt-get clean

COPY ./package.json src/

RUN cd src && npm install

COPY . /src

WORKDIR src/

CMD npm start

这怎么可能出错呢?

第二个大问题

我运行了 build 命令,然后出了这个错:

Do you want to continue? [Y/n] Abort.

The command '/bin/sh -c apt-get install imagemagick libmagickcore-dev libmagickwand-dev' returned a non-zero code: 1

我猜测微服务出错了。我回到本地机器,从本机启动微服务,然后试着上传文件。

然后我从 NodeJS 获得了这个错误:

Error: spawn convert ENOENT

怎么回事?之前还是好好的啊!

我搜索了我能想到的所有的错误原因。差不多4个小时后,我想:为什么不重启一下机器呢?

重启了,你猜猜结果?错误消失了!(LCTT 译注:万能的“重启试试”)

继续。

将精灵关进瓶子里

跳回正题:我需要完成构建工作。

我使用 rm 命令删除了虚拟机里所有的容器。

$ docker rm -f $(docker ps -a -q)

-f 在这里的用处是强制删除运行中的镜像。

然后删除了全部 Docker 镜像,用的是命令 rmi:

$ docker rmi if $(docker images | tail -n +2 | awk '{print $3}')

我重新执行了重新构建镜像、安装容器、运行微服务的整个过程。然后过了一个充满自我怀疑和沮丧的一个小时,我告诉我自己:这个错误可能不是微服务的原因。

所以我重新看到了这个错误:

Do you want to continue? [Y/n] Abort.

The command '/bin/sh -c apt-get install imagemagick libmagickcore-dev libmagickwand-dev' returned a non-zero code: 1

这太打击我了:构建脚本好像需要有人从键盘输入 Y! 但是,这是一个非交互的 Dockerfile 脚本啊。这里并没有键盘。

回到 Dockerfile,脚本原来是这样的:

RUN apt-get update
RUN apt-get install -y nodejs nodejs-legacy npm
RUN apt-get install imagemagick libmagickcore-dev libmagickwand-dev
RUN apt-get clean

第二个apt-get 忘记了-y 标志,它用于自动应答提示所需要的“yes”。这才是错误的根本原因。

我在这条命令后面添加了-y

RUN apt-get update
RUN apt-get install -y nodejs nodejs-legacy npm
RUN apt-get install -y imagemagick libmagickcore-dev libmagickwand-dev
RUN apt-get clean

猜一猜结果:经过将近两天的尝试和痛苦,容器终于正常工作了!整整两天啊!

我完成了构建工作:

$ docker build -t thumbnailer:0.1 .

启动了容器:

$ docker run -d -p 3001:3000 thumbnailer:0.1

获取了虚拟机的IP 地址:

$ docker-machine ip default

在我的浏览器里面输入 http://192.168.99.100:3001/

上传页面打开了。

我选择了一个图片,然后得到了这个:

container-diagram-7

工作了!

在容器里面工作了,我的第一次啊!

这让我学到了什么?

很久以前,我接受了这样一个道理:当你刚开始尝试某项技术时,即使是最简单的事情也会变得很困难。因此,我不会把自己当成最聪明的那个人,然而最近几天尝试容器的过程就是一个充满自我怀疑的旅程。

但是你想知道一些其它的事情吗?这篇文章是我在凌晨2点完成的,而每一个受折磨的时刻都值得了。为什么?因为这段时间你将自己全身心投入了喜欢的工作里。这件事很难,对于所有人来说都不是很容易就获得结果的。但是不要忘记:你在学习技术,运行世界的技术。

P.S. 了解一下Hello World 容器的两段视频,这里会有 Raziel Tabib’s 的精彩工作内容。

千万被忘记第二部分...


via: https://deis.com/blog/2015/beyond-hello-world-containers-hard-stuff

作者:Bob Reselman 译者:Ezio 校对:wxy

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

Debian GNU/Linux 7 "Wheezy" 在昨天结束了版本周期,变成了所谓的 LTS 版本,接下来的两年,它将由 Debian LTS (Long Term Support) Team 团队进行支持,为其提供重要的安全补丁和软件更新。(我怎么就觉得 Debian 的这个 LTS 的说法和别家不同呢。)不过对于 Debian 7 的用户来说,并不需要为此做什么修改,LTS 的更新会继续通过原来的 sources.list 通道推送给你——只是推送的少了,不重要的不推罢了。另外,有个变化是,从6/26 开始,OpenJDK 7 会变成新的 Java JRE/JDK,并一直更新到两年后。

Fedora 项目组宣布了墙纸比赛的胜出者,共有 133 个投稿,最终选择了 16 张,它们将会出现在 6 月 7 日发布的 Fedora 24 中。

更多墙纸可以在此下载,或者等到 Fedora 24 发布。

著名的 Shotwell 开源图片查看器又继续开始维护了,最近发布了一年来第一个主要版本 0.23.0。现在支持更窄的迷你边栏、支持 WebKit2GTK+ 4.0 开源渲染引擎等。

基于 Ubuntu 16.04 和 Budgie 桌面开发的 Budgie-Remix 发布了 16.04 LTS,这个发行版即将会成为 Ubuntu 官方分支,到时候就会改名为 Ubuntu Budgie 了。

继 Lubuntu 16.04 LTS 发布了支持树莓派2的镜像之后, Ubuntu MATE 16.04 LTS 也发布了支持树莓派2和树莓派3的版本,完全支持板载的 Wi-Fi 和蓝牙。此外,Chromium OS 也发布了支持树莓派3的0.5版,但是目前还不能支持板载的 Wi-Fi。

Mozilla Firefox 46.0 发布了,虽然现在官方还没更新下载链接。这次终于在 Linux 平台上支持 GTK3 了,而放弃了老旧的 GTK2。具体可以阅读此文

还是 Mozilla 的事情,Thunderbird 是一个 Mozilla 开发的著名开源邮件客户端,它发布于 2004 年。它和 Firefox 共享了很多代码,因为它们都用了 Mozilla 的 Gecko 渲染引擎。但是自 2012 年起, Mozilla 就停止了它的开发,只保持一些安全性和稳定性的修复。而现在,有个好消息是,至少有两个开源基金会希望接手它的开发和维护。看起来 Thunderbird 会有一个更好的明天了。

Open365 是一个开源的 Office 365 替代品,可以让你在线创建和编辑文档,并将文件同步到云上。

目前该服务还处于 Beta 测试期间,不过已经可以在其官网注册使用了。你可以通过 Web 浏览器使用它,也可以下载 Windows、Mac 或 Linux 桌面的客户端,Android 客户端也已经有了,而 iOS 客户端将在不久后发布。

Open365 主要有两个用途,一个是它可以让你在你的设备和云服务之间同步;另外一个是可以让你通过开源的办公套件 LibreOffice Online 所提供的功能在云上查看、修改和创建文档。

Open365

open365

现在你就可以在其官网上注册使用,不过其开发者计划将它开源,到时候你就可以将它安装到你自己的服务器上了。

当你注册后,你会得到一个邮件地址,可以用它来登录网站服务及同步客户端,它同时也提供了邮件服务。

你会有 20G 的存储容量,这要远超现在的其它文件同步服务。不过并不清楚是不是这20G 容量仅可用于 Beta 测试期间。

登录该网站服务,会自动载入一个“Hub”视图,默认情况下,它会列出你自己所有的库和分享给你的库。

点击文件夹会在网站页面上打开该文件夹,而点击文件则视文件类型采取不同动作,如果是支持的格式会直接打开编辑器,否则会下载它。支持的格式包括典型的文档格式,如 docx、xls 或 pptx 等,也支持查看常见的图片格式,可以回放音频和视频。

库和文件可以在线分享或删除,你也可以通过网站页面直接上传新的文件。你可以在网站页面上直接创建新的库,并指定加密选项,只有输入正确的密码才能访问——这个密码不是账户密码。

库和文件可以分享给某个人和某个用户组,可以通过分享链接取得该文件的完全控制。

文档编辑与创建

open365 documents

该功能可以如预期的那样工作,你可以在网站页面中双击文档以载入,Open365 会以合适的编辑器打开它。然后你就可以浏览文档,或者打印和编辑它。如果你之前使用过 LibreOffice,无论是在线还是离线,你就会觉得非常熟悉,不过即使你没用过,也没有什么大的问题,你很快就会熟悉的。

Open365 会定期自动保存修改,不过你也可以手动保存。修改过的文档可以保存到线上,也可以保存到本地,也可以保存为原本的格式或者导出成其它兼容的格式。

载入文档的速度有点慢,在显示文档之前可能要等个几秒钟。

Open365 同步客户端

open365 sync

客户端能够如预期的工作起来。你可以拖放文件夹来增加你要同步到云上的文件夹,也可以使用客户端内建的文件夹浏览器来做这个。

当你将文件夹拖放到同步客户端时,它会自动转换成一个库。在你点击开始同步的按钮前,可以修改库的名字和启用加密。

open365 create

桌面客户端的选项提供了同步的配置,你随时可以在系统托盘区右键点击打开该菜单。在选项中你可以设置上传和下载的速度限制、禁用 http 同步,或者配置当你从本地删除一个库或在云上没有找到一个库时应该采取的操作。

结语

Open365 是一个 Office 365 和 Google Docs 的替代品,它是免费开源的,支持文件同步和在互联网上查看、编辑和创建文档。

将 Open365 安装到你自己的服务器可以让你完全控制你的文档,而 Office 365 和 Google Docs 则不能做到这一点。

就在刚才,我们发现 Mozilla 将最终版本的 Firefox 46.0 上传到了他们的 FTP 服务器上,不过目前官方还没有正式更新下载链接。

被一直期待的 Firefox 46.0 定于今天发布,这次他们终于完成了承诺,在 GNU/Linux 平台上集成了 GTK3!集成 GTK3 这个事情可是从 Firefox 42.0 就开始给 Linux 用户们许诺了,而在 2015 年 11 月 42.0 发布时显然并没完成承诺,期间屡次许诺完成又屡次失信,直到现在才算真正实现。

除了 GTK3 之外,此次新版本还改进了 JavaScript JIT(Just In Time)编译器的安全,支持使用 内容解密模块 Content Decryption Module (CDN)作为解码未加密的 H.264 和 AAC 流的回退解码器。

Mozilla Firefox 46.0 看起来是一个小的发布版本,应该是我们所见过的最小的一个发布版本了,至少从之前的 Beta 版本的变更日志来看是这样的。从变更日志中可以看到,它改进了 WebRTC API 的稳定性和性能、支持 HTML5 的 document.elementsFromPoint 、增加了 Web Crypto API 的 HKDF 支持。

对于开发者来说,Mozilla Firefox 46.0 现在可以在内存工具中显示 dominator trees,在性能面板中增加了分配和垃圾回收的暂停分析,此外还支持在样式编辑器中直接启动响应模式。

Chromium OS for SBC 项目发布了 树莓派 Raspberry Pi 3 版本,已经可以下载安装了。

这是该项目第一次发布面向树莓派3的版本,其版本号 0.5 则是沿袭自面向树莓派2的0.5版本。

树莓派3B 发布于2016年2月的最后一天,具有内建的 Wi-Fi 和蓝牙支持,以及64位的 quad-core ARM Cortex-A53 处理器。而现在,Chromium OS for SBC 项目成功地将 Chromium OS 移植到了树莓派3上了。

面向树莓派3 的 Chrome OS 0.5 版亮点

不要被这个版本号所迷惑,面向树莓派3的 Chromium OS 其实并没有之前的版本,该团队只是将面向树莓派2的0.5版移植到了树莓派3罢了。

在这个版本中,我们注意到使用的是精简了大小的 Linux 4.2.8-ckt8 内核,它调整了 BFS 以减少延迟、更少的调试输出、以及非动态时钟、声卡驱动的多项改进、更好的存储性能,这些主要都是由于新的 BFQ 分层调度器和实时调度器的优化带来的。

用户体验也有了较大改善,为用户修复了 Kiosk 模式从而取得了更好的性能,也有一些小的视频方面的改进,特别是修复了 VC4 GPU 驱动和各种视频模式,比如让树莓派版的 Chromium OS 运行在非 1080p 显示下。

在这个首次移植版本中还有一些不足,比如现在还不支持树莓派 3B 板载的 Wi-Fi、不能播放 Netflix 视频、HTML 5 回放仅支持提供了 Flash 替代回放的网站。

你现在就可以从该项目的官网上下载 Chromium OS for Raspberry Pi 3 0.5 二进制镜像了。对了,最后补充一句,该项目团队正在将 Chromium OS 移植到 PINE64 单板计算机上,几周后就能发布了。

Eclipse 高级脚本环境(EASE)项目虽然还在开发中,但是必须要承认它非常强大,它让我们可以快速打造自己的Eclipse 开发环境。

依据 Eclipse 强大的框架,可以通过其内建的插件系统全方面的扩展 Eclipse。然而,编写和部署一个新的插件还是十分麻烦,即使你只是需要一个额外的小功能。不过,现在依托于 EASE,你可以不用写任何一行 Java 代码就可以方便的做到这点。EASE 是一种使用 Python 或者 Javascript 这样的脚本语言自动实现这些功能的平台。

本文中,根据我在今年北美的 EclipseCon 大会上的演讲,我将介绍如何用 Python 和 EASE 设置你的 Eclipse 环境,并告诉如何发挥 Python 的能量让你的 IDE 跑的飞起。

安装并运行 "Hello World"

本文中的例子使用 Python 的 Java 实现 Jython。你可以将 EASE 直接安装到你已有的 Eclipse IDE 中。本例中使用Eclipse Mars,并安装 EASE 环境本身以及它的模块和 Jython 引擎。

使用 Eclipse 安装对话框(Help>Install New Software...),安装 EASE:http://download.eclipse.org/ease/update/nightly

选择下列组件:

  • EASE Core feature
  • EASE core UI feature
  • EASE Python Developer Resources
  • EASE modules (Incubation)

这会安装 EASE 及其模块。这里我们要注意一下 Resource 模块,此模块可以访问 Eclipse 工作空间、项目和文件 API。

成功安装后,接下来安装 EASE Jython 引擎 https://dl.bintray.com/pontesegger/ease-jython/ 。完成后,测试下。新建一个项目并新建一个 hello.py 文件,输入:

print "hello world"

选中这个文件,右击并选择“Run as -> EASE script”。这样就可以在控制台看到“Hello world”的输出。

现在就可以编写 Python 脚本来访问工作空间和项目了。这种方法可以用于各种定制,下面只是一些思路。

提升你的代码质量

管理良好的代码质量本身是一件非常烦恼的事情,尤其是当需要处理一个大型代码库或者要许多工程师参与的时候。而这些痛苦可以通过脚本来减轻,比如批量格式化一些文件,或者去掉文件中的 unix 式的行结束符来使得在 git 之类的源代码控制系统中比较差异更加容易。另外一个更好的用途是使用脚本来生成 Eclipse markers 以高亮你可以改善的代码。这里有一些示例脚本,你可以用来在 java 文件中所有找到的“printStackTrace”方法中加入task markers 。请看源码

拷贝该文件到工作空间来运行,右击并选择“Run as -> EASE script”。

loadModule('/System/Resources')

from org.eclipse.core.resources import IMarker

for ifile in findFiles("*.java"):
    file_name = str(ifile.getLocation())
    print "Processing " + file_name
    with open(file_name) as f:
        for line_no, line in enumerate(f, start=1):
            if "printStackTrace" in line:
                marker = ifile.createMarker(IMarker.TASK)
                marker.setAttribute(IMarker.TRANSIENT, True)
                marker.setAttribute(IMarker.LINE_NUMBER, line_no)
                marker.setAttribute(IMarker.MESSAGE, "Fix in Sprint 2: " + line.strip())

如果你的 java 文件中包含了 printStackTraces,你就可以看见任务视图和编辑器侧边栏上自动新加的标记。

自动构建繁琐任务

当同时工作在多个项目的时候,肯定需要完成许多繁杂、重复的任务。可能你需要在所有源文件头上加入版权信息,或者采用新框架时候自动更新文件。例如,当首次切换到 Tycho 和 Maven 的时候,我们需要 giel每个项目添加 pom.xml 文件。使用几行 Python 代码可以很轻松的完成这个任务。然后当 Tycho 支持无 pom 构建后,我们需要移除不要的 pom 文件。同样,几行代码就可以搞定这个任务,例如,这里有个脚本可以在每一个打开的工作空间项目上加入 README.md。请看源代码 add\_readme.py

拷贝该文件到工作空间来运行,右击并选择“Run as -> EASE script”。

loadModule('/System/Resources')  
  
for iproject in getWorkspace().getProjects():
    if not iproject.isOpen():
        continue

    ifile = iproject.getFile("README.md")

    if not ifile.exists():
        contents = "# " + iproject.getName() + "\n\n" 
        if iproject.hasNature("org.eclipse.jdt.core.javanature"):
            contents += "A Java Project\n"
        elif iproject.hasNature("org.python.pydev.pythonNature"):
            contents += "A Python Project\n"
        writeFile(ifile, contents)

脚本运行的结果会在每个打开的项目中加入 README.md,java 和 Python 的项目还会自动加上一行描述。

构建新功能

你可以使用 Python 脚本来快速构建一些急需的功能,或者做个原型给团队和用户演示你想要的功能。例如,一个 Eclipse 目前不支持的功能是自动保存你正在工作的文件。即使这个功能将会很快提供,但是你现在就可以马上拥有一个能每隔 30 秒或处于后台时自动保存的编辑器。以下是主要方法的片段。请看下列代码:autosave.py

def save_dirty_editors():
    workbench = getService(org.eclipse.ui.IWorkbench)
    for window in workbench.getWorkbenchWindows():
        for page in window.getPages():
            for editor_ref in page.getEditorReferences():
                part = editor_ref.getPart(False)
                if part and part.isDirty():
                    print "Auto-Saving", part.getTitle()
                    part.doSave(None)

在运行脚本之前,你需要勾选 'Allow Scripts to run code in UI thread' 设定,这个设定在 Window > Preferences > Scripting 中。然后添加该脚本到工作空间,右击并选择“Run as > EASE Script”。每次编辑器自动保存时,控制台就会输出一个保存的信息。要关掉自动保存脚本,只需要点击控制台的红色方块的停止按钮即可。

快速扩展用户界面

EASE 最棒的事情是可以将你的脚本与 IDE 界面上元素(比如一个新的按钮或菜单)结合起来。不需要编写 java 代码或者安装新的插件,只需要在你的脚本前面增加几行代码。

下面是一个简单的脚本示例,用来创建三个新项目。

# name      : Create fruit projects
# toolbar   : Project Explorer
# description   : Create fruit projects

loadModule("/System/Resources")

for name in ["banana", "pineapple", "mango"]:
    createProject(name)

上述注释会专门告诉 EASE 增加了一个按钮到 Project Explorer 工具条。下面这个脚本是用来增加一个删除这三个项目的按钮的。请看源码 createProjects.pydeleteProjects.py

# name            :Delete fruit projects
# toolbar        : Project Explorer
# description    : Get rid of the fruit projects

loadModule("/System/Resources")

for name in ["banana", "pineapple", "mango"]:
    project = getProject(name)
    project.delete(0, None)

为了使按钮显示出来,增加这两个脚本到一个新的项目,假如叫做 'ScriptsProject'。然后到 Windows > Preference > Scripting > Script Location,点击 'Add Workspace' 按钮并选择 ScriptProject 项目。这个项目现在会成为放置脚本的默认位置。你可以发现 Project Explorer 上出现了这两个按钮,这样你就可以通过这两个新加的按钮快速增加和删除项目。

整合第三方工具

不管怎么说,你可能需要除了 Eclipse 生态系统以外的工具(这是真的,虽然 Eclipse 已经很丰富了,但是不是什么都有)。这些时候你会发现将他们包装在一个脚本来调用会非常方便。这里有一个简单的例子让你整合资源管理器,并将它加入到右键菜单栏,这样点击图标就可以打开资源管理器浏览当前文件。请看源码 explorer.py

# name      : Explore from here
# popup     : enableFor(org.eclipse.core.resources.IResource)
# description   : Start a file browser using current selection
loadModule("/System/Platform")
loadModule('/System/UI')

selection = getSelection()
if isinstance(selection, org.eclipse.jface.viewers.IStructuredSelection):
    selection = selection.getFirstElement()

if not isinstance(selection, org.eclipse.core.resources.IResource):
    selection = adapt(selection, org.eclipse.core.resources.IResource)

if isinstance(selection, org.eclipse.core.resources.IFile):
    selection = selection.getParent()

if isinstance(selection, org.eclipse.core.resources.IContainer):
    runProcess("explorer.exe", [selection.getLocation().toFile().toString()])

为了让这个菜单显示出来,像之前一样将该文件加入一个新项目,比如说 'ScriptProject'。然后到 Windows > Preference > Scripting > Script Locations,点击“Add Workspace”并选择 'ScriptProject' 项目。当你在文件上右击鼠标键,你会看到弹出菜单出现了新的菜单项。点击它就会出现资源管理器。(注意,这个功能已经出现在 Eclipse 中了,但是你可以在这个例子中换成其它第三方工具。)

Eclipse 高级基本环境 (EASE)提供一套很棒的扩展功能,使得 Eclipse IDE 能使用 Python 来轻松扩展。虽然这个项目还在早期,但是关于这个项目更多更棒的功能也正在加紧开发中,如果你想为它做出贡献,请到论坛讨论。

我会在 2016 年的 Eclipsecon North America 会议上发布更多 EASE 细节。我的演讲 Scripting Eclipse with Python 也会不单会介绍 Jython,也包括 C-Python 和这个功能在科学领域是如何扩展的。


via: https://opensource.com/life/16/2/how-use-python-hack-your-ide

作者:Tracy Miranda 译者:VicYu/Vic020 校对:wxy

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