把 Time Machine 备份到 FreeNAS 上

Mac 上的 Time Machine 很好用,不过每次备份都要用移动硬盘挺麻烦的。如果有多人使用多台 Mac 能不能把大家的 Time Machine 统一备份到云里或者局域网的某台服务器上呢?我们实验室大部分人都在用 Mac,现在正需要这么一个备份方案。谷歌了一下,发现这种使用 Time Machine 备份到远程电脑的方案是最方便、廉价的了,只需要一台普通 PC 就可以充当备份服务器。

Apple 使用自己的 Apple Filing Protocol (AFP) 协议提供文件共享服务,FreeNAS 刚好支持这一协议(貌似 Openfiler 目前还没有实现 AFP)。在一台服务器或虚拟机上安装 FreeNAS,安装过程很容易,这里省略。

配置 FreeNAS

安装好后进入 web 管理界面创建一个新用户,然后创建一个新 APF 共享, 在左边菜单里面选择 Sharing->Add Apple (AFP) Share,这里需要注意钩上 Disk Discovery 并选择 Disk discovery mode 为 Time Machine:

create a afp share

搞定~

配置 Mac

现在剩下的配置在 Mac 完成,让 Mac 连接刚创建的 AFP Share,点击 Mac 顶部菜单 Go->Connect to Server…,填入 freenas 服务器的 IP 地址 192.168.2.200 连接服务器:

time machine backup

成功连接后会挂载一个 AFP share 盘,然后配置 Time Machine 选择这个盘当作备份盘:

time machine backup

大功告成,等着自动备份吧:

time machine backup

把浏览器当作临时记事本

今天发现一个比较实用的小技巧,新建一个浏览器窗口在里面打字,可以当作简单的 notepad 用,比如临时记点东西什么的,这样不必每次开 Notes/TextEdit/Vi/Evernote 之类的工具了。(小技巧来自:One line browser notepad

打开浏览器,在地址栏里敲入下面这行:

data:text/html, <html contenteditable>

如果稍微美化调整一下并修改浏览器标题栏的话:

data:text/html, <title>Notepad</title>
<body contenteditable style="font-size:2rem;line-height:1.4;max-width:60rem;
margin:0 auto;padding:4rem;">

可以把上面代码保存到书签,这样就不必每次复制粘贴上面的代码了:

use browser as notepad

在 Ubuntu 上安装 NX 服务器

远程登陆 Linux 图形桌面有很多方式,比如使用 RFB (Remote Frame Buffer) 协议的各种 VNC 工具,TightVNC, UltraVNC, Xvnc 等,使用 NX 的 NoMachine, freenx, neatx 等。NX 通过 X11 调用来通信,比 VNC 这种通过截图似的通信要快的多,而且安全(通过 ssh),更适合在网速不高(相比局域网来说)的 Internet 上应用。如果你想在 VPS 上使用 Linux 图形界面的话,使用 NX 是一个比 VNC 好得多的方案。

安装 NX 服务器

到 NoMachine 官网下载 nxserver 4.0 到 Ubuntu 后直接安装就可以了,不需要其他的依赖包,这个比以前的 3.5 版本清晰多了,3.5 版本的 NX 服务器要装 nxnode, nxserver, nxclient,这三个名字很混淆人:

$ wget http://64.34.173.142/download/4.0/Linux/S/nxserver_4.0.181-7_i386.deb
$ sudo dpkg -i nxserver_4.0.181-7_i386.deb

安装 NX 客户端

在 Mac 上下载 nx 客户端 nxplayer 4.0 后安装,需要注意的是,nxplayer 是 nxclient 的下一代版本,目前还是预览版,因为 Mac OS X 10.8 上不能使用旧版本的 nx 客户端(nxclient-3.5.0-7.pkg),安装后不能启动,所以这里只能用 nxplayer 预览版。

$ wget http://64.34.173.142/download/4.0/MacOSX/nxplayer-4.0.181-7.dmg

测试

安装完毕后,在 Mac 上启动一个 nxplayer 连接 Linux 上的 nxserver:

nxplayer session

成功连接后输入用户名和密码就能进入 Ubuntu 桌面了:

nxplayer session

在 Ubuntu 12.04 上安装 CUDA 5 开发环境

休假时间太长,回来发现敲命令居然有点手生,一些命令都不能一次敲对。上个月去南非德班参加了一个高性能计算会议,会议的多数话题是关于 SKA 的,Square Kilometre Array(SKA)是迄今为止全球最大最灵敏的射电望远镜,将在南非和澳大利亚建造,所以这次德班会议的多个 talk 都和 SKA 项目有关。会议有很多提到 GPU 的地方,比如模拟太阳内部黑子爆发,后面用到了大量计算,普通 PC 要计算1600年的数据在现代集群 GPU 上只要几天就可以完成。我们今年新增了的几台做 GPU 高性能计算的 PowerEdge M610x 刀片服务器,上个月就到货了没来得及装配就放假了,昨天 Dell 的人过来装了一下,自己也顺便了解了一下 GPU,玩了一下 CUDA 这个开发环境。

安装必要软件包

sudo 成 root 用户后安装一些必要软件包:

$ sudo -i
# apt-get install build-essential libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev freeglut3-dev

需要在 blacklist.conf 末尾增加下面几行屏蔽几个模块,以便顺利安装驱动:

# vi /etc/modprobe.d/blacklist.conf
...
blacklist vga16fb
blacklist nouveau
blacklist rivafb
blacklist nvidiafb
blacklist rivatv

安装 NVIDIA 图形卡驱动

从 NVIDIA 官网找到对应的图形卡型号,下载和安装 NVIDIA 图形卡驱动:

# wget http://us.download.nvidia.com/XFree86/Linux-x86_64/310.19/NVIDIA-Linux-x86_64-310.19.run
# chmod +x NVIDIA-Linux-x86_64-310.19.run
# ./NVIDIA-Linux-x86_64-310.19.run
# reboot

nvidia driver install for cuda

安装 CUDA 5.0 开发工具包

从 NVIDIA 官网下载和安装最新的 CUDA 5.0 开发工具包,没有 for ubuntu 12.04 的不要紧,下载 for ubuntu 11.10 的一样可以用在 ubuntu 12.04 上:

# wget http://developer.download.nvidia.com/compute/cuda/5_0/rel-update-1/installers/cuda_5.0.35_linux_64_ubuntu11.10-1.run
# chmod +x cuda_5.0.35_linux_64_ubuntu11.10-1.run
# ./cuda_5.0.35_linux_64_ubuntu11.10-1.run

检查一下日志,看看安装过程中是否有错:

# tail /var/log/nvidia-installer.log 
-> done.
-> Driver file installation is complete.
-> Running post-install sanity check:
-> done.
-> Post-install sanity check passed.
-> Shared memory test passed.
-> Running runtime sanity check:
-> done.
-> Runtime sanity check passed.
-> Installation of the kernel module for the NVIDIA Accelerated Graphics Driver for Linux-x86_64 (version 304.54) is now complete.

最后简单验证一下 cuda 是否安装成功:

# cd /usr/local/cuda/bin
# ./nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2012 NVIDIA Corporation
Built on Fri_Sep_21_17:28:58_PDT_2012
Cuda compilation tools, release 5.0, V0.2.1221

Merry Christmas & a prosperous 2013

一年又过去了,三年多的坚持让我们惊讶我们竟然走了这么远,vpsee.com 的存在离不开你的持续关注、评论建议、信任理解和给力支持,所以,谢谢你!

祝广大客户、合作伙伴、读者和此时此刻还奋斗在键盘一线的码农们,圣诞快乐、新年 happy!

Merry Christmas and a prosperous 2013

使用 Python-LDAP 操作 LDAP

周末看到那些排队血拼的人们,不用走进 shopping mall、不用看到那些五颜六色的打折和视觉冲击就能感受到 “节日要到了!”。一年又快结束了,这周完成备份、升级之类的收尾工作,接下来就是6周的假期,没啥大安排,假期第1周去南非德班参加高性能计算会议,回来后和家人短途旅行,然后圣诞节在家休息学点新东西,比如修车什么的,几次痛苦经历告诉我出来玩迟早是要坏的,对于 hiking/camping/road trip/4×4 这几个关键字的爱好者来说懂点维修常识是必须的。废话留到假期再说吧,接下来六周可能没有技术方面的博客更新~

最近对 LDAP 服务器上面的数据做处理,有机会接触了一下 Python-LDAP 这个库和 LDAP/Kerberos. 去除所有打印和错误处理的代码后,用 Python-LDAP 操作 LDAP 的骨干代码其实很简单,就这么几行,唯一遇到的一个小麻烦就是折腾了一个多小时才知道 ‘TRUE’ 要大写(后面有说到)。

安装 Python-LDAP

在 Ubuntu/Debian 下安装 python-ldap 模块:

$ sudo apt-get install python-ldap

在 CentOS/RHEL 下安装 python-ldap 模块:

# yum install python-ldap

创建

创建一条 LDAP 新纪录。有个要注意的地方,我们的 LDAP 有个属性 active,用来判断用户帐号是否是激活的 attrs[‘active’] = ‘TRUE’,这里的 ‘TRUE’ 不能用小写的 ‘true’,刚开始被 LDAP 管理工具上的小写 ‘true’ 误导,老以为 Python 程序里也应该用小写,结果总报错。

phpLDAPadmin

def ldap_add(firstname, lastname, username):
    l = ldap.open(LDAP_HOST)
    l.protocol_version = ldap.VERSION3
    l.simple_bind(LDAP_BIND, LDAP_PASS)

    cn = firstname + ' ' + lastname
    addDN = "cn=%s,ou=People,dc=vpsee,dc=com" % cn
    attrs = {}
    attrs['objectclass'] = ['top','person','inetOrgPerson','posixAccount','vpseeAccount']
    attrs['cn'] = cn
    attrs['givenName'] = firstname
    attrs['homeDirectory'] = '/home/people/%s' % username
    attrs['loginShell'] = '/bin/bash'
    attrs['sn'] = lastname
    attrs['uid'] = username
    attrs['uidNumber'] = ldap_newuid()
    attrs['gidNumber'] = ldap_getgid()
    attrs['active'] = 'TRUE'
    ldif = modlist.addModlist(attrs)
    l.add_s(addDN, ldif)
    l.unbind_s()

查找和读取

查找和读取一条 LDAP 纪录,比如根据 username 查找出 cn:

def ldap_getcn(username):
    try:
        l = ldap.open(LDAP_HOST)
        l.protocol_version = ldap.VERSION3
        l.simple_bind(LDAP_BIND, LDAP_PASS)

        searchScope = ldap.SCOPE_SUBTREE
        searchFilter = "uid=*" + username + "*"
        resultID = l.search(LDAP_BASE, searchScope, searchFilter, None)
        result_set = []
        while 1:
            result_type, result_data = l.result(resultID, 0)
            if (result_data == []):
                break
            else:
                if result_type == ldap.RES_SEARCH_ENTRY:
                    result_set.append(result_data)
        return result_set[0][0][1]['cn'][0]
    except ldap.LDAPError, e:
        print e

更新

更新一条 LDAP 纪录,比如更新用户状态 active 为 false:

def ldap_deactive(username):
    try:
        l = ldap.open(LDAP_HOST)
        l.protocol_version = ldap.VERSION3
        l.simple_bind(LDAP_BIND, LDAP_PASS)

        deactiveDN = ("cn=%s," + LDAP_BASE) % ldap_getcn(username)
        old = {'active':'TRUE'}
        new = {'active':'FALSE'}
        ldif = modlist.modifyModlist(old, new)
        l.modify_s(deactiveDN, ldif)
        l.unbind_s()
    except ldap.LDAPError, e:
        print e

删除

删除一条 LDAP 纪录:

def ldap_delete(username):
    try:
        l = ldap.open(LDAP_HOST)
        l.protocol_version = ldap.VERSION3
        l.simple_bind(LDAP_BIND, LDAP_PASS)

        deleteDN = ("cn=%s," + LDAP_BASE) % ldap_getcn(username)
        l.delete_s(deleteDN)
    except ldap.LDAPError, e:
        print e

在 Ubuntu 12.04 上安装 GitLab

gitlab

我们需要一套能自己托管 git 的工具,类似 GitHub,但是要求能 host 在自己的服务器上,看了一下 Git Enterprise 版本,20人每年授权费用是5000美金,太贵,只能找找类似的开源工具,以前用的是 Redmine + GitTrac + Git/Subversion 来管理实验室的项目,有点腻了,听一个朋友说 GitLab 挺好用、基于 Rails & Gitolite、社区活跃每月都有 release、安装起来比 Gitorious 要简单。下午没事装了一个试了一下,感觉还不错,有个重要功能是支持 LDAP 认证,可以很容易和我们的 LDAP 服务器连起来,这样我们不需要在 GitLab 里另外创建用户就可以使用 GitLab 了。GitLab 的官方安装文档非常详细,按照步骤就可以完成安装。

安装 GitLab

安装 curl 后下载 GitLab 的自动安装脚本 debian_ubuntu.sh 并安装:

$ sudo apt-get install curl
$ sudo curl https://raw.github.com/gitlabhq/gitlab-recipes/master/install/debian_ubuntu.sh | sh

上面的安装脚本只进行了完成了部分工作,接下来安装一些库和包、下载 gitlab 源代码、拷贝配置文件:

$ sudo gem install charlock_holmes --version '0.6.8'
$ sudo pip install pygments
$ sudo gem install bundler
$ cd /home/gitlab

# 下载 gitlab 源代码
$ sudo -H -u gitlab git clone -b stable https://github.com/gitlabhq/gitlabhq.git gitlab

$ cd gitlab

# 拷贝配置文件
$ sudo -u gitlab cp config/gitlab.yml.example config/gitlab.yml

安装数据库引擎(可选 SQLite, MySQL, Postgres)、根据对应的数据库引擎(这里选择 SQLite)选择拷贝相应的配置文件并按照对应的 gem,最后安装数据库表:

$ sudo apt-get install -y sqlite3 libsqlite3-dev

$ sudo -u gitlab cp config/database.yml.sqlite config/database.yml

$ sudo -u gitlab -H bundle install --without development test mysql postgres  --deployment

$ sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production

配置 gitlab hooks:

$ sudo cp ./lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
$ sudo chown git:git /home/git/.gitolite/hooks/common/post-receive

测试一下程序状态,是否该有的配置文件都有了:

$ sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production

运行 gitlab 和 resque:

$ sudo -u gitlab bundle exec rails s -e production
$ sudo -u gitlab bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes

下载 gitlab 启动脚本并设为系统自动启动:

$ sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab -P /etc/init.d/
$ sudo chmod +x /etc/init.d/gitlab

$ sudo update-rc.d gitlab defaults 21

现在可以通过 /etc/init.d/gitlab 来启动、关闭和重启 gitlab 服务了:

$ sudo /etc/init.d/gitlab restart

配置 LDAP 支持(可选)

如果需要配置 LDAP 认证登陆,修改 gitlab.yml 文件的 2. Auth settings 部分:

$ sudo vi config/gitlab.yml
#
# 2. Auth settings
# ==========================
ldap:
  enabled: true
  host: 'ldap.vpsee.com'
  base: 'dc=vpsee,dc=com'
  port: 636
  uid: 'uid'
  method: 'ssl' # plain
  bind_dn: 'cn=admin,dc=vpsee,dc=com'
  password: 'password'

安装和配置 Nginx + Unicorn

GitLab 可以用 Rails 自带的服务器独立运行,但是在生产环境我们选择用 Nginx + Unicorn:

# 配置 Unicorn
$ cd /home/gitlab/gitlab
$ sudo -u gitlab cp config/unicorn.rb.example config/unicorn.rb
$ sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D

# 安装 nginx
$ sudo apt-get install nginx

# 增加 gitlab 的 nginx 配置文件
$ sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/nginx/gitlab -P /etc/nginx/sites-available/
$ sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab

# 修改 **YOUR_SERVER_IP** 和 **YOUR_SERVER_FQDN**
$ sudo vi /etc/nginx/sites-enabled/gitlab

# 重启 nginx
$ sudo /etc/init.d/nginx restart

测试

打开浏览器访问这台机器域名或 IP 地址,默认用户名是 [email protected] 密码是 5iveL!fe,登陆后可见如下界面:

gitlab

在 Ubuntu 12.04 上安装 Open vSwitch

云计算时代人类已经成功虚拟化了服务器硬件,现在大大小小的数据中心有无数的虚拟机跑在服务器硬件上,看上去很美好,但是任务还没有完成,这么多的虚拟机都依赖物理服务器(所在)的网络端口、网络和交换机(除了物理依赖还依赖这些硬件上的软件配置),这让底层变动成为一个大问题,比如我们想改变服务器 A 上的网络设置(192.168.2.0 改成 172.16.2.0)或者物理移动服务器 A 到另一数据中心,那么服务器 A 上运行的虚拟机怎么办呢?逐个改动配置是很麻烦的。有没有一种办法能把虚拟机所在的网络和物理服务器的网络隔开呢(虽然可以用 VLAN,但是还是不够)?这正是网络虚拟化正在做的,通过软件的方式形成交换机部件(vSwitch),让各个虚拟机和虚拟交换机连接起来而不用去理会真实物理机和物理交换机。比如,让 Host A 上的 VM02 和 Host B 上的虚拟机 VM10 连成一个网络而不用理会虚拟机(VM)所在服务器(Host)的网络设置。

网络虚拟化或者软件定义网络(Software Defined Network, SDN)的应用远不止这些,任何了解 SDN 的人都不会怀疑 SDN 的未来,这也是为啥 VMware 愿意花12亿美金买 Nicira(软件定义网络的先驱)。

要使用 SDN/OpenFlow 就必须有支持 OpenFlow 协议的物理(或软件)交换机,OpenvSwitch 就是这么一个支持 OpenFlow 协议的开源虚拟交换机。我们从安装虚拟交换机 Open vSwitch 开始来慢慢了解网络虚拟化吧。

安装必要软件包:

$ sudo -i
# apt-get install kvm libvirt-bin openvswitch-controller openvswitch-brcompat openvswitch-switch openvswitch-datapath-source

启动 Open vSwitch 服务,如果报错 FATAL: Error inserting brcompat_mod 模块错误则需要编译和加载 brcompat_mod 这个模块,这个模块是 openvswitch 为了兼容 linux bridge 而来的,有些程序使用 Linux bridge(比如 brctl),这些程序为了能在 openvswitch 下继续使用将需要这个 brcompat_mod 兼容模块,这个模块为那些慢慢迁移到 openvswitch 的程序提供了方便:

# service openvswitch-switch start
FATAL: Error inserting brcompat_mod (/lib/modules/3.2.0-30-generic/updates/dkms/brcompat_mod.ko): Invalid module format
 * Inserting brcompat module
Module has probably not been built for this kernel.
For instructions, read
/usr/share/doc/openvswitch-datapath-source/README.Debian
FATAL: Error inserting brcompat_mod (/lib/modules/3.2.0-30-generic/updates/dkms/brcompat_mod.ko): Invalid module format
 * Inserting brcompat module

# module-assistant auto-install openvswitch-datapath

编译模块后再次尝试启动服务:

# service openvswitch-switch restart
 * Killing ovs-brcompatd (1606)
 * Killing ovs-vswitchd (1603)
 * Killing ovsdb-server (1594)
 * Starting ovsdb-server
 * Configuring Open vSwitch system IDs
 * Starting ovs-vswitchd
 * Starting ovs-brcompatd
 * iptables already has a rule for gre, not explicitly enabling

 # service openvswitch-controller restart
 * Restarting ovs-controller ovs-controller                                              Sep 12 13:46:46|00001|stream_ssl|INFO|Trusting CA cert from /etc/openvswitch-controller/cacert.pem (/C=US/ST=CA/O=Open vSwitch/OU=switchca/CN=OVS switchca CA Certificate (2012 Sep 12 13:42:19)) (fingerprint 46:5b:14:1f:13:56:b0:b0:a7:4d:10:39:ee:68:18:d4:39:3c:4b:d0)
                                                                                  [ OK ]

编辑配置文件,取消注释并设置 BRCOMPAT 为 yes 以便启动后能使用 brcompat_mod 模块:

# vi /etc/default/openvswitch-switch
# This is a POSIX shell fragment                -*- sh -*-

# FORCE_COREFILES: If 'yes' then core files will be enabled.
# FORCE_COREFILES=yes

# BRCOMPAT: If 'yes' and the openvswitch-brcompat package is installed, then
# Linux bridge compatibility will be enabled.
BRCOMPAT=yes

重启一下系统,验证一下是否模块被自动加载:

# reboot

# lsmod | grep brcom
brcompat_mod           13512  0 
openvswitch_mod        83993  1 brcompat_mod

使用 openvswitch 增加网桥 br0 并把网络接口 eth0 加入 br0:

# ovs-vsctl add-br br0
# ovs-vsctl add-port br0 eth0

# ovs-vsctl show          
a23c503b-bfbe-4646-8738-a7f69e5d69a0
    Bridge "br0"
        Port "eth0"
            Interface "eth0"
        Port "br0"
            Interface "br0"
                type: internal
    ovs_version: "1.4.0+build0"

配置网桥 br0 和网络接口 eth0(和用 bridge-utils 工具配置的时候一样,不同的是这里用更先进的 openvswitch/brcompat_mod 替换了 bridge-utils):

# ifconfig eth0 0
# ifconfig br0 192.168.2.45 netmask 255.255.255.0
# route add default gw 192.168.1.1 br0

为了保存网络设置,最好把上面的配置写到 /etc/network/interfaces 里:

# vi /etc/network/interfaces
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
address 192.168.2.45
netmask 255.255.255.0
gateway 192.168.2.1

auto eth0
iface eth0 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down

安装 log.io 实时日志监控工具

日志是个好东西,对技术人员来说写日志能纪录成长,分享经验;对机器来说纪录日志能及时发现错误,为日后的排错提供信息。如果还在一台机器上用 tail -f 监听单个日志或者用 multitail 监听多个日志也太 out 了,我们需要一种工具能纪录上百台机器、不同类型的日志,并最好能汇集到一个界面里方便查看,最好还是实时的。log.io 就是这样一个实时日志监控工具,采用 node.js + socket.io 开发,使用浏览器访问,每秒可以处理超过5000条日志变动消息。有一点要指出来的是 log.io 只监视日志变动并不存储日志,不过这个没关系,我们知道日志存储在哪个机器上。

和其他的监控工具一样,log.io 也采用服务器-客户端的模式。log.io 由两部分组成:server 和 harvester, server 运行在机器 A(服务器)上监视和纪录其他机器发来的日志消息;log harvester 运行在机器 B(客户端)上用来监听和收集机器 B 上的日志改动,并将改动发送给机器 A,每个需要纪录日志的机器都需要一个 harvester.

在机器 A 和 B 上

因为 log.io 基于 node.js,所以在服务器和客户端都要安装 node.js,这里采用编译安装的办法,首先安装需要的依赖包:

$ sudo apt-get install g++ make git libssl-dev pkg-config

下载 node.js 源代码,编译并安装:

$ wget http://nodejs.org/dist/v0.8.14/node-v0.8.14.tar.gz
$ tar zxvf node-v0.8.14.tar.gz
$ cd node-v0.8.14/ 
$ ./configure
$ make
$ sudo make install

安装 NPM:

$ curl https://npmjs.org/install.sh | sudo sh 

安装 log.io(包含了 log server 和 log harvester)

$ sudo npm config set unsafe-perm true 
$ sudo npm install -g --prefix=/usr/local log.io

在机器 A 上启动 server

$ sudo log.io server start

在机器 B 上配置和启动 harvester

server 用来监听各个机器发来的日志消息,harvester 用来把本机的日志发给 server,所以 harvester 配置的时候需要指定 server 的主机地址(或域名)。如何告诉 harvester 哪些日志需要监控呢?log_file_paths 就是指定日志路径的地方。下面的配置是 harvester 把 auth.log 和 harvester.log 这两个日志的改动发送给 server:

$ sudo vi /etc/log.io/harvester.conf
exports.config = {
  // Log server host & port
  server: {
    host: 'log.vpsee.com', // 也可以用 IP 地址
    port: 8998,
  },

  // Watch the following log files, defined by label:path mappings
  log_file_paths: {
    logio_auth: '/var/log/auth.log',
    logio_harvester: '/var/log/log.io/harvester.log',
  },

  instance_name : 'log_node_1'
}

启动 harvester:

$ sudo log.io harvester start

测试

打开浏览器访问 log server 所在的机器 A,域名是 log.vpsee.com(也可以用 IP 地址),端口是 8998(注:为了隐私和保护内部信息,文章里面出现的 IP、域名、密码以及任何敏感信息都是处理过的,所以这里的 log.vpsee.com 是参考用的、是打不开的,囧,下面还有人留言问为啥打不开~):

log.io

使用 Fabric 批量执行服务器任务

我们的服务器和虚拟机的环境配置都由 puppet 管理,但有时候需要临时执行某些任务和操作,比如同时更换500台服务器的密码、同时更新或者重启500台虚拟机、在特定几台服务器上添加或者一个用户、上传一个特定文件/脚本到1000台服务器等等。这些任务用 Puppet 可以做,但是不是最简洁的办法。我们需要一种工具能完成大量服务器上的批量操作,并且要简单可编程,Fabric 就是这样一个基于 Python 的服务器批量管理库/工具,Fabric 使用 ssh(通过 paramiko 库)在多个服务器上批量执行任务,我们只需要用 Python 编写这些任务脚本并指定要执行这些任务的服务器就可以了。

Fabric 依赖 paramiko,所以需要安装这两个:

$ sudo pip install fabric
$ sudo pip install paramiko

编写一个简单的 Fabric 例子,在1台服务器上打印系统信息(uname -s):

$ vi fabfile.py
#!/usr/bin/python

from fabric.api import run

def host_os():
    run('uname -s')

在 vpsee.com 这台主机(host)上使用 root 帐户执行上面的任务 host_os:

$ fab -H [email protected] host_os
[[email protected]] Executing task 'host_os'
[[email protected]] run: uname -s
[[email protected]] Login password for 'root': 
[[email protected]] out: Linux

Done.
Disconnecting from [email protected]... done.

来看一个更复杂点的例子,在多个服务器(grid00, grid02, …, grid05)上更换 root 密码(假设原密码是 root),注意加上 @parallel,这样任务是并行执行的,在大量服务器上会快很多:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from fabric.api import *
import string
from random import choice
import socket
import paramiko

env.user = 'root'
env.password = 'root'
env.hosts = [ 'grid00', 'grid01', 'grid02', 'grid03', 'grid04', 'grid05']

@task
@parallel
def passwd(user, passwd=False):
    with settings(hide('running', 'stdout', 'stderr'), warn_only=True):
        if isup(env.host):
            if not passwd:
                passwd = genpass()
            sudo("echo -e '%s\n%s' | passwd %s" % (passwd, passwd, user))

def genpass(length=10):
    return ''.join(choice(string.ascii_letters + string.digits) for _ in range(length))

def isup(host):
    print 'connecting host: %s' % host
    timeout = socket.getdefaulttimeout()
    socket.setdefaulttimeout(1)
    up = True
    try:
        paramiko.Transport((host, 22))
    except Exception, e:
        up = False
        print '%s down, %s' % (host, e)
    finally:
        socket.setdefaulttimeout(timeout)
        return up

使用 fab -l 查看我们刚编写的 fabfile.py 里面的可用命令,这个命令就是那个函数名 def passwd(user, passwd=False):

$ fab -l
Available commands:

    passwd

使用这个命令批量更换 grid00-grid05 的 root 密码为 test,passwd 传递参数的时候接冒号,并且用户名和密码参数用逗号隔开:

$ fab passwd:root,test
[grid00] Executing task 'passwd'
[grid01] Executing task 'passwd'
[grid02] Executing task 'passwd'
[grid03] Executing task 'passwd'
[grid04] Executing task 'passwd'
[grid05] Executing task 'passwd'
connecting host: grid05
connecting host: grid04
connecting host: grid02
connecting host: grid03
connecting host: grid01
connecting host: grid00

Done.

Fabric 的强大之处在于可以用 Python 编写各种任务(函数),这些任务可以指定到任何服务器上(通过 ssh),非常适合管理大量服务器、批量处理任务。另外 Fabric 工作方式非常简单容易理解,就是简单的 ssh 而已,没有内幕没有架构,不像其他工具什么客户端服务器端、什么中间代码、什么 DSL 领域专属语言(嗯,说的就是 puppet, chef)。Fabric 使用起来只需要懂点 Python 就可以了,不需要学命令、api、框架之类的。我们喜欢简单、容易理解的工具。