Bowen's Blog

Respect My Authorita.

Learning Scala: Prepare Development Environment

| Comments

最近开始翻译Scala Cookbook, 希望能为Scala这门语言的推广做出些贡献。就我自己的学习语言和阅读教材经验来看,教材无法覆盖很多实际的使用过程中碰到的问题,比如环境问题等。于是想写一些列总结性blog,也算是自己的总结了。

Scala的安装:

安装前先确保机器上已经有java的环境,因为Scala同样需要JVM虚拟机。 Scala最新的版本是2.10.x, 安装的方法很简单,下载解压安装包,把scala/bin目录加入到PATH环境变量中即可,如下的脚本在OSX和*nux下适用。

1
2
link="http://www.scala-lang.org/files/archive/scala-2.10.3.tgz"
curl -O $link && tar xvzf scala-2.10.3.tgz ~/ && echo "export PATH=~/scala/bin/:$PATH"  >> ~/.bash_profile && source ~/.bash_profile

在命令行敲入scala就可以进入Scala的console(解释器)了。

1
2
3
4
5
 ~> scala
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
Type in expressions to have them evaluated.
Type :help for more information.
scala>

还有一种办法是安装SBT, Scala工程的构建工具,OSX下直接用Homebrew就可以安装. brew install sbt 可能需要修改java虚拟机的启动参数,否则可能出错:

1
echo "export JAVA_OPTS=\"-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M\"" >> ~/.bash_profile && source ~/.bash_profile

sbt console进入Scala的REPL console。

1
2
3
4
5
6
7
8
 ~> sbt console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
Type in expressions to have them evaluated.
Type :help for more information.

scala>

Scala REPL 的使用

:help可以告诉你想要的关于Scala REPL的一切信息,个人觉得几个比较有用的命令有:paste, :load, :sh, :history等。 :paste,直接在Scala console里面编辑代码相对来说不是很方便,你可以选择自己熟悉的编辑器,完成代码,使用:paste命令,Command + V将代码拷贝到Scala REPL中,之后按Ctrl + D退出,对应的代码就被load到当前的进程当中了。

1
2
3
4
5
6
7
8
9
10
11
scala> :paste
// Entering paste mode (ctrl-D to finish)

def hello() = println("hello, world")

// Exiting paste mode, now interpreting.

hello: ()Unit

scala> hello
hello, world

在Scala console中也可以执行shell的命令,结果会被保存到一个list中,如下

1
2
3
4
5
scala> :sh ls
res15: scala.tools.nsc.interpreter.ProcessResult = `ls` (6 lines, exit 0)

scala> res15.toArray
res16: Array[String] = Array(README.md, cn, code_examples, conventions.yml, en, target)

:load命令+文件路径,可以加载Scala文件,导入你自定义的类/代码。

1
2
3
4
5
scala> :load ./code_examples/chap1/hello.scala
Loading ./code_examples/chap1/hello.scala...
hello, world

scala>

Scala的console支持和shell类似的history功能,你可以用Ctrl + R去搜寻前面执行过的代码再来一次,用:history查看所有的曾经运行过的代码。比较尴尬的是,虽然SBT文档里面注明是可以用shebang的方式去执行历史代码,我在REPL中却没有试验成功。Anyway,这个不是特别重要了。 还有些命令诸如:implicits,显示当前scope中的隐式定义,:imports可以显示导入类库的记录。 我好像没有说明console的最重要的作用。。。,那就是解释scala代码并返回结果,这个时候的Scala代码就像脚本一样,支持自动补齐,不过功能不是很强大。

1
2
3
4
5
6
scala> val x = 1 + 2
x: Int = 3
scala> "hello " * 5   #如果没有显式的赋值,scala解释器会给把结果指定一个变量名
res1: String = "hello hello hello hello hello "
scala> println(res1)
hello hello hello hello hello

编译运行一个Scala文件

scalacscala命令,和使用javacjava命令很像,都会生成class文件。

1
2
3
4
/*helloworld, example, helloworld.scala*/
object HelloWorld extends App {
   println("Hello, World");
}

scalac命令编译

1
 ~> scalac helloworld.scala

scala命令运行

1
2
~> scala HelloWorld
Hello, World

Scala IDE

Intelij, NetBeads和Eclipse都提供了Scala支持,看个人喜欢,可以随意选择。Netbeans的Scala插件是由国内的一个程序员邓草原开发的。当然,你也可以考虑其他的工具比如Emacs,Vim,Sublime或者Atom。

关于开发环境,基本就是这些了。

Introduction to Docker

| Comments

周末在西安Rubyist线下聚会活动中给大家分享了下关于Docker的简单介绍,轻量级虚拟化确实来势凶猛,未来在集成测试、PaaS平台搭建,部署方面应该都会大有作为。我在实际的Spike中使用Docker在虚拟机中运行了大约4个服务,非常稳定,占用资源很少。

Install Python 2.7 Under Centos 6.4

| Comments

在Skype中使用Hubot

| Comments

Hubot 是一个github开源的机器人项目,可以集成到众多的聊天工具中,如IRC, Hipchat, Skype,QQ等。你可以用它来搞笑,也可以用它来进行自动化的管理,比如自动化部署等。这几天花了点时间,在OSX和Centos上分别尝试搭了下Hubot,详细过程如下:

安装Hubot, 有两种方式,懒人的方式就用现成的Vagarant Script, 有几点要注意的是:

  1. OSX必须得安装X11支持
  2. Oracle OCI 不是必须的

在Centos 6.4 上安装Hubot。

环境准备, 包括桌面支持,开发工具, skype等等.

1
2
3
4
5
6
7
8
9
10
11
yum install http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
yum groupinstall -y "Desktop"
yum groupinstall -y "Development Tools”
yum install qtwebkit.i686 webkitgtk.i686 —y
yum install tigervnc-server -y   #for vnc connect
yum install wget telnet -y
yum install sqlite-devel -y
yum install nodejs npm -y
yum install redis -y
yum install python-setuptools python-setuptools-devel -y
yum update

安装Skype:

1
2
3
4
wget http://download.skype.com/linux/skype-4.2.0.13.tar.bz2
tar skype-4.2.0.13.tar.bz2 -C /opt/
ln -s skype-4.2.0.13 skype
ln -s /opt/skype/skype /usr/bin/skype

安装Skype4py: Skype api 的python wrapper

1
2
easy_install pip
pip install Skype4Py

安装coffee-script hubot:

1
npm install -g coffee-script hubot

配置服务:

1
2
3
4
5
6
7
8
9
10
11
echo -e "VNCSERVERS="1:vnc"\n VNCSERVERARGS[1]="-geometry 1024x768" >> /etc/sysconfig/vncservers
useradd vnc
su - vnc
passwd

service iptables stop
service vncserver start

chkconfig redis on    # auto start
chkconfig vncserver on   #auto start
service redis start

centos默认iptables的服务是打开的,邪恶一点的方法是直接关掉iptables服务,上进的方法就是在iptables里面添加新的规则,还是邪恶吧……,因为hubot-skype也可能存在被iptables block的情况。 VNC到虚拟机上,启动Skype并登陆。

1
skype &

安装配置hubot-skype:

1
2
mkdir hubot && cd hubot
hubot -c .

自动生成如下目录结构:

1
2
3
4
5
6
7
8
9
10
[root@localhost hubot]# tree -L 1
.
|-- bin
|-- external-scripts.json
|-- hubot-scripts.json
|-- node_modules
|-- package.json
|-- Procfile
|-- README.md
`-- scripts

package.json 里面放的hubot运行依赖的插件,hubot-scripts.json 里面写的是hubot的脚本。修改 package.json:

1
2
3
4
5
6
  "dependencies": {
    "hubot":         ">= 2.6.0 < 3.0.0",
    "hubot-scripts": ">= 2.5.0 < 3.0.0",
    "hubot-skype": "0.0.2"
  }
npm install

修改hubot-scripts.json, 添加karma.coffee:

["redis-brain.coffee", "shipit.coffee", "karma.coffee”]

运行:

1
./bin/hubot  -a skype &

Skype会弹出是否允许第三方的应用控制,勾选就可以了。

把hubot添加到Skype对话中,就可以用命令来调戏hubot了, 下面是一些例子:

1
2
3
4
hubot image me keyword  #google 搜索keyword相关的图片,随机挑选一张返回图片链接
hubot animate me keyword  #google 搜索keyword相关的gif图片,随机挑选一张返回图片链接
hubot youtube me keyword  #youtube 搜索keyword相关的视频,随机挑选一个返回视频链接
rebot mustache me keyword #给google搜索返回的图片上加个胡子。。。。

添加了karma.coffee脚本-人品计算器的话,可以用user++/user— 来增加和减少讨论组内成员的人品值。 鉴于youtube国内无法访问,所以正准备扩展下脚本,提供 hubot youku me的命令。另外,如果把这个做成微信服务号部署到heroku上拿来玩应该也很有趣。

最后,写了一个脚本,配置过程中绝大多数操作都放到里面了, 不能保证100%自动化。

Note:

  1. 有个rails的工程hubot-control可以更加方便的进行hubot的管理, 我做了些许修改;
  2. 一定要VNC到虚拟机上去启动hubot-skype,不然会报这个错误:
1
2
3
4
  ......
  File "/usr/lib/python2.6/site-packages/Skype4Py/api/posix_x11.py", line 254, in __init__
    raise SkypeAPIError('Could not open XDisplay')
Skype4Py.errors.SkypeAPIError: Could not open XDisplay

原因是X11的环境变量 DISPLAY没有设置成0,非常之烦人,下次会考虑使用dbus去运行,虽然不知道怎么弄……

使用KeePassX管理你的密码

| Comments

SaaS化的趋势已经不可阻挡,传统软件的功能逐渐web化。网上服务越来越多,对应的账号也越来越多,所有账号一个密码显然不现实,至少支付宝的登陆密码和支付密码就是不一样的。再加上密码要求越来越严格,大小写字母,数字,特殊字符组合……,尼玛刚设置10分钟后就忘记了。这个时候,就得靠软件了……,比如KeePassX。 KeePassX是一款跨平台的免费开源的密码管理软件,安装和使用都比较简单。

下载地址

界面如下: 设置:

  1. 创建密码数据库. 点击 File -> New Database, 新建一个密码的数据库。创建的时候需要你设置文件保护密码,保存后会生成一个.kdb文件,

  2. 密码管理. KeePassX管理密码的方式有两种,组(Group) 和入口(Entry)。比如设置邮件组,里面放置所有的邮件账号。新建一个入口(Entry),输入标题,账号已经密码,确定即可。

  3. 也可以用KeePassX帮你生成随机密码,设置密码过期时间等等,不过我没有用。 使用: 异常简单,假设你现在要登录163的邮箱,选中标题,Command+B 拷贝用户名,Command+C拷贝密码,输入登录即可。

设置一个强度较高的文件保护密码,只要不是电脑丢了,应该是比较安全的。除此之外,还有类似1Password之类的软件,只不过需要收费,上次公司给报销,但是当时没有意识到,错过了。。。

Sublime Open Gems Source Code in Repo

| Comments

Jetbrains的产品很赞,不过就是太耗资源了,比如Rubymine。有时候会用轻量点的编辑器Sublime去打开/编辑ruby工程代码,一个麻烦就产生了,sublime无法关联到工程内所用到的rubygems的源码。

google搜索了下,有两种解决的办法,一种是通过修改EDITOR环境变量.

1
2
3
export EDITOR='subl' >> ~/.bash_profile && source ~/.bash_profile

bundle open rubygem_name

相信和很多人一样,我们都已经把 EDITOR 设置为 vim 或者 emacs。那么可以采用第二种方案.

1
2
3
 ~> bundle show rake # 返回rubygem的完整路径
 /Users/iambowen/.rvm/gems/ree-1.8.7-2012.02/gems/rake-0.9.6
 ~> bundle show rake | xargs subl   # xargs do the trick

这次应该解决了问题,不过每次输入这么多命令不是很方便,可以写一个函数的函数来解决这个问题:

1
2
3
4
function sublg ()
{
  bundle show $1 | xargs subl
}

把这个函数加入~/.bash_profile后,就可以直接使用sublg gem_name来打开gem的源码了。

Export/Import Database/procedures in Mysql

| Comments

最近在做一个关于Docker的spike的时候,遇到了这样的一个需求。我需要在Docker build Mysql服务的image的时候完成两个数据库的schema migration,不包含数据的migration. 其中一个数据库只有表,另外一个数据库还包括了store procedures和函数. 假设只有表的数据库叫做table_only, 有函数和store procedure的数据库叫做table_with_sp,数据在的主机名/地址为 host1,目标mysql服务器为host2。

Step 1: 导出schema/store procedures/functions
1
2
mysqldump -h host1 -u root -p --no-data table_only > table_only.sql
mysqldump -h host1 -u root -p --no-data --routines table_with_sp > table_with_sp.sql
Step 2: Migration
1
2
3
mysql -h host2 -u root -p -e "create database table_only; create database table_with_sp"
mysql -h host2 -u root -p table_only < table_only.sql
mysql -h host2 -u root -p table_with_sp < table_with_sp.sql

Notes

  • 不想用任何命令的,可以用可视化的数据库工具进行导出,Mac下可以使用SequelPro,非常方便,是免费的工具。
  • 如果想自动化整个过程,可以考虑对host2的mysql 配置做如下的修改,让mysqldump的时候自动使用如下的authentication.
1
2
3
[mysqldump]
user=root
password=password

Deploy Rails 4 App to Heroku

| Comments

今天参加Railsgirls的活动,被抓壮丁去做了Rails应用在Heroku部署的演示,本来以为很简单,照着教程 走一遍就好了,但是没想到其中还是有些坑的,做了个简单的ppt,解释下里面的坑。

为什么要安装rails_12factor

By default Rails 4 will return a 404 if an asset is not handled via an external proxy such as Nginx. While this default behavior may help you debug your Nginx configuration, it makes a default Rails app with assets unusable on a twelve-factor platform. …. The rails_serve_static_assets gem enables your Rails server to deliver your assets directly, instead of returning a 404.

产品环境里面,rails应用可能是在类似Nginx的服务器后面,静态的assets,比如对/public/assets/application.css 的请求是由Nginx直接处理的,但是Heroku并没有使用类似Nginx这样的proxy,而是在routing layer 做的loadbalancing。所以当你请求静态的assets的时候,会得到404的错误。rails_12factor包含了rails_serve_static_assets这个gem, 可以把对assets的控制权交给Rails应用本身。这样就不会出现拿不到更新的css的情况了。

Openwrt+迅雷离线实现离线下载以及家庭存储解决方案

| Comments

前一段时间考虑如果实现一个家庭存储的解决方案,NAS是一个解决思路,不过价格略贵,即便是双11活动的时候,最便宜的也得接近1000块,这还不算硬盘的价格。后来参考了一篇用路由器(OpenWrt系统)和移动硬盘来实现家庭存储的文章,决定试下用路由器+移动硬盘的方案。 OpenWrt是一个基于linux的嵌入式操作系统,你可以通过opkg来定制安装软件包,来获取你所需要的服务, 如aria2下载服务,DDNS服务,SMB共享文件服务等。它对路由器的硬件有一定的要求,所以首先得选择下合适的路由器。最后的软硬件选择为:

  1. 水星mw4530r 320
  2. 希捷1T移动硬盘 440
  3. 迅雷白金会员 90

路由是直接从taobao上买了刷好的系统,主要是为了超频和升级16M内存,后来才意识到软件其实可以安装在移动硬盘上,多花了70比较失败。水星的这款是支持2.4G和5.G双频的,实际使用没觉得有什么太大的区别。大概配置了如下的这些服务:

  1. ftp 服务, 用来从路由器外接的移动硬盘下载电影
  2. samba 文件共享服务, 用来在不用的电脑/系统间进行文件共享,直接选择共享文件去播放电影,偶尔有卡顿,还是下载到本机比较好
  3. aria2 下载服务,用来在路由器上下载文件,同时可以用迅雷离线进行远程下载
  4. ddns服务,动态路由,可以把路由绑定到域名上,这样就能在任何地方访问到我的路由器

大部分的服务比较容易配置,直接在Luci的web界面就可以配置了,还可以配置mDLNA的服务,这个只能等到去新房的电视机上测试了。这里只说几个稍微tricky点的设置。 动态路由:

  1. 申请花生壳动态域名, 如 myname.oicp.net
  2. 在DDNS配置页面中绑定你申请的动态域名
  3. ssh root@192.168.1.1, 修改/etc/config/uhttpdoption rfc1918_filter 1 修改为 option rfc1918_filter 0,允许openwrt 接受external的请求.
  4. 重启DDNS服务,/etc/init.d/ddns restart

离线下载:

  1. 申请离线下载,双十一的时候有活动,迅雷白金会员半价, 90块。还是比较超值的,离线空间大概有300多T,支持多种协议,如BT、磁力链接、ed2k等,基本上高清电影随便往进去扔。
  2. 在chrome下安装 迅雷离线助手 这个插件,可以帮助你直接导出aria2/aria2-rpc/wget/IDM/Orbit/YAAW下载。
  3. 安装完成后,登陆迅雷离线, 打开右上角设置,修改Aria2 json path 为 http://myname.oicp.net:6800/jsonrpc
  4. 点击任意一个资源下拉框,选择 yyaw导出,之后访问 http://myname.oicp.net/aria2,就可以看到正在下载的任务了。

国内云存储的选择很多,微云,115,百度云,华为网盘,迅雷离线空间等,存储空间都是以T为单位,大部分是不用付费的,每个云存储都有相应的客户端做同步。迅雷的价格最贵,但是它有几点好处:

  1. 离线空间更大,300T+,按照单部高清电影50G来计算,可以放6000部电影了,这辈子估计也看不完
  2. 资源丰富,很多时候,你可以发现,下载任务刚添加,就完成了,可以推测服务器上早就有这个资源了,凭借md5校验码来验证资源是否,存在的话,直接做个链接就可以了
  3. 迅雷做了很好的CDN,所以不管你的网络运营商是什么,电信、联通还是铁通,都可以做到峰值下载
  4. 迅雷云播,可以直接在电脑或者手机客户端上播放离线空间资源,还能自动匹配字幕

国家的版权控制越来越严格,可以想见的将来,资源的获取会更加困难,首先是音乐,因为目前音乐作品在网络上缺乏一个很好的渠道和商业模式去盈利,因此发行商或者利益相关者会盯的更紧些。电影则不然,清晰版的影片一般会在下映后或者更长时间才会出现,盈利不会受到很大影响。后来思考一番,多下载点影片和无损音乐在云端,路由接的移动硬盘除了放部分电影之类的话,也可以作为文档或者家里的视频照片等的存储空间。你可以使用samba或者ftp去上传文件,就是每次人工干预会略不爽,可以使用rsync做文件的同步,然后用crontab建个定时自动运行的任务就可以了。 大概的步骤是如下这样:

  1. 把你的public key 扔到openwrt系统上,openwrt使用的是一个比较轻量的ssl服务,叫做dropbear,所以ssh key放置的目录也不太一样。你可以直接run这条命令: cat ~/.ssh/id_rsa.pub | ssh root@192.168.1.1 "cat >> /etc/dropbear/authorized_keys”. 这样你ssh到openwrt的时候就不需要再输入密码.
  2. 安装rsync, opkg install rsync.
  3. 在pc端新建cron job,假设我希望每天晚上11点半同步所有dropbox里面的文件, 运行crontab -e,添加”30 23 * * * rsync -r ~/Dropbox/ root@192.168.1.1:/mnt/sda1/Dropbox/“, 保存即可

自己去搭建这么一套简单的家庭存储的解决方案的好处很多:

  1. 省钱,一场电影要30块,两个人一年看10次电影就差不多了。路由器的功耗很低,每小时只有几瓦,如果你开着一台PC去下载,一小时至少400w左右的功耗,从这个角度也节省了钱。
  2. 最大化利用带宽,压榨宽带资源。一个月的宽带费用要一两百,所以一定要做到物尽其用,在家人都上班的时候添加好任务,回家之后就可以观看电影,不会影响到家人去使用网络。
  3. 私人服务器。由于电信运营商对上行带宽的限制,从外部访问路由上的ftp下载服务比较慢,但是下载一些文档照片是足够了,上传的速度很快,所以如果你在旅游的时候拍的照片啊什么的,可以上传到服务器上,家人就可以在电视上看了。
  4. 可玩性高。可以在openwrt上安装使用的服务远不止此,比如使用摄像头进行监控服务,只要有无线摄像头连接上,可以随时监控家里的情况。13号baidu就要退出一款无线摄像头,价格只有99,非常之便宜。还有类似流媒体服务,在家庭多个位置放置无线音箱,在手机或者电视,pc上控制播放,很有趣。

当然,相比NAS,还是有些不足,比如:

  1. 单个USB移动硬盘无法做数据的备份,比如raid,如果硬盘出问题,数据可能丢失。
  2. 意外断电可能导致的设备损坏。

几年前我在TCL教育做实习的时候,他们已经开始做基于android的智能电视了,在互联网企业杀入这个市场后,家庭智能化趋势已经不可阻挡了,物联网真正的实现也近在眼前。其中智能电视,路由器和游戏机是几个比较关键的要素,国内的几家公司,比如小米,马上要推出的小米路由或者果壳等,比较值得关注。随着宽带计划提升到国家战略层面,访问敏感网站逐渐松绑,互联网带来的自由革命也即将到来。

Restarting Virtualbox Under Osx

| Comments

使用vagrant启动虚拟机的时候遇到了如下的错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 ~> vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Clearing any previously set forwarded ports...
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Available bridged network interfaces:
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for machine to boot. This may take a few minutes...
The guest machine entered an invalid state while waiting for it
to boot. Valid states are 'starting, running'. The machine is in the
'poweroff' state. Please verify everything is configured
properly and try again.

If the provider you're using has a GUI that comes with it,
it is often helpful to open that and watch the machine, since the
GUI often has more helpful error messages than Vagrant can retrieve.
For example, if you're using VirtualBox, run `vagrant up` while the
VirtualBox GUI is open.

错误信息提示我虚拟机所处状态(poweroff),不能启动。原因未知,不过除了信息中给出的解决办法,还可以通过重启VirtualBox来解决。办法如下:

1
2
3
4
5
6
7
8
9
10
 ~> sudo /Library/StartupItems/VirtualBox/VirtualBox restart
Password:
Unloading VBoxUSB.kext
Unloading VBoxDrv.kext
/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostart => /Applications/VirtualBox.app/Contents/MacOS/VBoxAutostart-amd64
………..
Loading VBoxDrv.kext
Loading VBoxUSB.kext
Loading VBoxNetFlt.kext
Loading VBoxNetAdp.kext

然后就可以顺利的通过Vagrant启动虚拟机了。