在 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

在 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

安装 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、框架之类的。我们喜欢简单、容易理解的工具。

升级 Red Hat Linux 7.3 到 CentOS 3.1

最近用 VMware vCenter Converter 工具企图虚拟化一台很古老的 Red Hat Linux 7.3 物理服务器失败,可能是因为 RedHat 7.3 版本太老 VMware Converter 支持不到位。虚拟化太老的系统如果使用一些自动迁移工具不成功的话可以自己动手迁移,虽然麻烦点,比如做个虚拟硬盘、加上分区表、把文件系统拷贝过去、重置 grub、最后修改几个关键文件等。现在这里的想法是把 RedHat 7.3 升级到 CentOS 3.1 再用 VMware Converter 试一下,如果这样还不成功就只能手动虚拟化物理机了。升级前先备份系统(可用光盘启动后 dd 硬盘到另一个硬盘),防止升级失败后系统启动不了或者升级后关键程序不能运行。升级前不确定 RedHat 7.3 到 CentOS 3.1 这种不同版本、不同版本号的大跨度升级能否成功,有必要纪录一下。

登陆 RedHat 7.3 后安装 yum:

# wget http://ftp.ie.freshrpms.net/pub/freshrpms/redhat/7.3/yum/yum-1.0.3-3.rh.fr.i386.rpm
# rpm -ivh yum-1.0.3-3.rh.fr.i386.rpm

编辑 yum.conf 加入 centos 3.1 的源:

# vi /etc/yum.conf
[main]
cachedir=/var/cache/yum
debuglevel=2
logfile=/var/log/yum.log
pkgpolicy=newest
distroverpkg=redhat-release
installonlypkgs=kernel kernel-smp kernel-hugemem kernel-enterprise kernel-debug kernel-uns
upported kernel-smp-unsupported kernel-hugemem-unsupported
tolerant=1
exactarch=1

[base]
name=CentOS-$releasever - Base
baseurl=http://centosa3.centos.org/centos-3/3.1/os/i386/
gpgcheck=1

#released updates
[update]
name=CentOS-$releasever - Updates
baseurl=http://centosa3.centos.org/centos-3/3.1//updates/i386/
gpgcheck=1

#packages used/produced in the build but not released
[addons]
name=CentOS-$releasever - Addons
baseurl=http://centosa3.centos.org/centos-3/3.1/addons/i386/
gpgcheck=1

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
baseurl=http://centosa3.centos.org/centos-3/3.1/extras/i386/
gpgcheck=1

升级系统,完成后重启:

# yum update
# yum upgrade

# shutdown -r now

FreeBSD 9.0 文件系统的默认 fragment size 是 4096

今天发现在一台小硬盘的 FreeBSD 9.0 虚拟机上启动 vi 时报错:

% vi

/: create/symlink failed, no inodes free
ex/vi: Error: Unable to create temporary file: No space left on device

检查了一下硬盘容量,貌似这个虚拟机只用了53%的硬盘,应该还有足够的空间啊:

% df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/ada0p3    5.7G    2.8G    2.4G    53%    /
devfs          1.0k    1.0k      0B   100%    /dev

仔细看错误信息发现是文件系统 no inodes free,应该是文件系统的 inode 不够了,df -i 查看 inode 用了100%,没了可用的 inode 也就不能创建文件了。

% df -i
Filesystem  1K-blocks    Used   Avail Capacity iused ifree %iused  Mounted on
/dev/ada0p3   5939036 2916144 2547772    53%  378873     5  100%   /
devfs               1       1       0   100%       0     0  100%   /dev

用 newfs 查看当前文件系统设置发现 fragment size 4096. 查看 newfs 命令的帮助文件得知 FreeBSD 9.0 下的 fragment size 和 block size 默认分别为32768和4096字节,是 FreeBSD 8.2(8192和1024字节)时的4倍(难怪以前在小硬盘上用 FreeBSD 8.2 的时候没遇到这个问题):

# newfs -N /dev/ada0p3
/dev/ada0p3: 5892.9MB (12068736 sectors) block size 32768, fragment size 4096
	using 8 cylinder groups of 740.00MB, 23680 blks, 47360 inodes.
super-block backups (for fsck -b #) at:
 192, 1515712, 3031232, 4546752, 6062272, 7577792, 9093312, 10608832

% man newfs
...
EXAMPLES
           newfs /dev/ad3s1a

     Creates a new ufs file system on ad3s1a.  The newfs utility will use a
     block size of 32768 bytes, a fragment size of 4096 bytes and the largest
     possible number of blocks per cylinders group.  These values tend to pro‐
     duce better performance for most applications than the historical
     defaults (8192 byte block size and 1024 byte fragment size).  This large
     fragment size may lead to much wasted space on file systems that contain
     many small files.
...

查看源码 freebsd/sbin/newfs/newfs.h 再次确认了 FreeBSD 9.0 下文件系统的 fragment size 和 block size 默认大小:

/*
 * The following two constants set the default block and fragment sizes.
 * Both constants must be a power of 2 and meet the following constraints:
 *      MINBSIZE <= DESBLKSIZE <= MAXBSIZE
 *      sectorsize <= DESFRAGSIZE <= DESBLKSIZE
 *      DESBLKSIZE / DESFRAGSIZE <= 8
 */
#define DFL_FRAGSIZE    4096
#define DFL_BLKSIZE     32768

现在要想办法改变 block size, fragment size,增加 inode 数目,/dev/ada0p3 分区刚好是 root 分区,只能重装了,分区的时候记得在分区格式化步骤的时候带上初始化参数,在动手之前 man newfs 仔细看看帮助文件里对 -b -f -i 等参数的说明:

# man newfs

# newfs -U -b 4096 -f 512 -i 2048 /dev/ada0p3

释放 Linux 系统预留的硬盘空间

大多数文件系统都会保留一部分空间留作紧急情况时用(比如硬盘空间满了),这样能保证有些关键应用(比如数据库)在硬盘满的时候有点余地,不致于马上就 crash,给监控系统和管理员一点时间去察觉。不过有时候这部分预留的硬盘空间不用的话有点浪费。如何释放这部分系统预留的空间呢?

在 Linux ext2/ext3/ext4 文件系统上通常默认预留5%的硬盘空间,如果硬盘是 4TB 的话就意味着有 200GB 的空间就这样浪费了,我们可以通过 tune2fs 来改变5%的默认设置,比如只预留1%的空间。可不可以设成0%呢?当然可以,但是不推荐。

查看当前硬盘空间情况:

# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vg_cloud22-lv_root
                       32G  1.1G   30G   4% /
tmpfs                  24G     0   24G   0% /dev/shm
/dev/sda1             485M   68M  392M  15% /boot
/dev/mapper/vg_cloud22-lv_home
                      3.2G   70M  2.9G   3% /home
/dev/sdd1            1008G  161G  797G  17% /var/cloud

调整 /dev/sdd1,只预留1%的空间:

# tune2fs -m 1 /dev/sdd1
tune2fs 1.41.12 (17-May-2010)
Setting reserved blocks percentage to 1% (2684381 blocks)

调整后查看释放后的硬盘空间,发现多出了 838-797=41GB 的空间:

# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vg_cloud22-lv_root
                       32G  1.1G   30G   4% /
tmpfs                  24G     0   24G   0% /dev/shm
/dev/sda1             485M   68M  392M  15% /boot
/dev/mapper/vg_cloud22-lv_home
                      3.2G   70M  2.9G   3% /home
/dev/sdd1            1008G  161G  838G  17% /var/cloud

如果硬盘被塞满了,想清理硬盘那是另外一回事,可以参考:什么吃掉了我的硬盘?

/dev/null 的另类用法

/dev/null 是个黑洞,进去的东西永远出不来,在脚本编程的时候经常会用它(空设备文件)来屏蔽标准或错误输出(stdout 或 stderr),比如 command > /dev/null 2>&1 把 command 执行的结果(标准输出和错误输出)全部重定向到 /dev/null,也就是在控制台上不回显任何输出。

今天发现我们的 Graphite 监控服务器硬盘空间不够了(因为监控日志体积日益增加),一些不必要的日志占据了不少硬盘,比如 graphite 里面的 console.log,一般来说日志配置都在相关的配置文件里,在 graphite 的配置文件里找了一圈居然没找到如何关闭 console.log 日志配置(有其他日志的配置选项,但是没有 console.log 这个日志的关闭选项),难道要写个 cron 定期清理 console.log?一个更好的办法是把 console.log 这个连接到 /dev/null(如果确定以后不需要查看 console.log 的话),这样 graphite 写到 console.log 就永远的消失了,对现在的系统和配置不会有任何影响,甚至连 graphite 服务都不用重启,下面的脆香米兄的评论是对的,graphite 正在操作 console.log,简单改变文件名称并没有更改已打开的文件句柄,所以需要重启 carbon-cache.py.

# cd /opt/graphite/storage/log/carbon-cache/carbon-cache-a/

# ls -l
total 1811016
-rw-r--r-- 1 root     root     1360161601 Aug  6 15:18 console.log

# /opt/graphite/bin/carbon-cache.py stop

# mv console.log console.log.bak
# ln -s /dev/null console.log

# /opt/graphite/bin/carbon-cache.py start

# ls -l
total 1811032
lrwxrwxrwx 1 root     root              9 Aug  6 15:18 console.log -> /dev/null
-rw-r--r-- 1 root     root     1360178736 Aug  6 15:18 console.log.bak

在 Ubuntu 12.04 上配置 Radius 和 LDAP 服务

上次提到了我们实验室的 Wi-Fi 更改了认证方式,不再使用 WPA2/PSK 通用密码,而是通过 LDAP 把 Wi-Fi 上网密码和个人帐号联系起来,大家只需要用自己平时的 Unix/Linux/Mail/GroupWise 帐号就可以登陆 Wi-Fi,那么如何配置这样一个系统呢?涉及到的东西有点多,首先需要一个支持 Radius 的无线路由器,然后需要一台装有 Radius 的服务器,这台服务器还需要作为 LDAP 客户端和 LDAP 服务器连起来。

准备工作

  • Linksys WRT 54GS 无线路由器,可以替换开源固件的 hacker-friendly 路由器;
  • DD-WRT 固件,刷固件的过程可以参考:把 Linksys WRT54GL 路由器当作交换机用
  • FreeRadius 服务,安装在一台 Ubuntu 服务器上;
  • LDAP 客户端,安装在同一台 Ubuntu 服务器上;
  • LDAP 服务器,一般安装在另一台服务器上,也可以和上面的 FreeRadius/LDAP client 装在一起,LDAP 服务器的配置和安装过程超出本文范围,这里不介绍。

配置 Wi-Fi

刷固件以后按照下图配置 Linksys WRT 54GS,指定 Radius 服务器的 IP 和端口、安全模式、WPA 算法、WPA Shared Key 等,这个 WPA Shared Key 由下面的 FreeRadius 配置指定:

dd-wrt and radius

安装和配置 LDAP

这里只是安装 LDAP 客户端,不包括 LDAP 服务器的安装,所以需要事先知道 LDAP 服务器的 IP 或域名等相关信息。

$ sudo apt-get install ldap-auth-client ldap-auth-config libpam-ldap

填入 LDAP 服务器地址 host, base 等:

$ sudo vi /etc/ldap.conf
host ldap.vpsee.com
base dc=vpsee,dc=com
pam_password exop
pam_lookup_policy yes

nss_initgroups_ignoreusers Debian-exim,backup,bin,daemon,dhcp,games,gnats,irc,klog,libuuid
,list,lp,mail,man,news,ntpd,proxy,root,snmp,sshd,statd,sync,sys,syslog,uucp,www-data

确认 nsswitch.conf 先搜索本地文件,用户登陆的时候先检索本地 /etc/passwd 找不到相关用户名再检索 ldap 服务器上的用户数据库:

$ sudo vi /etc/nsswitch.conf
passwd:         files ldap
group:          files ldap
shadow:         files ldap
automount:      files

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

安装和配置 FreeRadius

安装 FreeRadius:

$ sudo apt-get install freeradius freeradius-utils freeradius-ldap openssl 

编辑 clients.conf,确定哪个 IP 范围可以访问 Radius 服务,这里 secret 一行的 testing123 就是上面 DD-WRT 要用到的 WPA Shared Key:

$ sudo vi /etc/freeradius/clients.conf
...
client 192.168.2.0/24 {
        require_message_authenticator = no
        secret          = testing123
        shortname       = vpsee-network
}
...

配置 default,确定 pam 一行没有被注释掉:

$ sudo vi /etc/freeradius/sites-available/default
...
authorize {
        preprocess
        chap
        mschap
        suffix
        eap {
                ok = return
        }
        unix
        files
        expiration
        logintime
        pap
}
...
authenticate {
        Auth-Type PAP {
                pap
        }
        Auth-Type CHAP {
                chap
        }
        Auth-Type MS-CHAP {
                mschap
        }
        pam
        unix
        eap
}
...

同样的确定 inner-tunnel 配置文件里面的 pam 一行没有被注释掉:

$ sudo vi /etc/freeradius/sites-available/inner-tunnel
...
authenticate {
        Auth-Type PAP {
                pap
        }
        Auth-Type CHAP {
                chap
        }
        Auth-Type MS-CHAP {
                mschap
        }
        pam
        unix
        eap
}
...

在 users 加入下面认证类型:

$ sudo vi /etc/freeradius/users
...
DEFAULT Auth-Type = PAM
      Fall-Through = 1
...

测试

配置完毕后重启 freeradius:

$ sudo /etc/init.d/freeradius restart

如果要 debug 的话这样启动 freeradius:

$ sudo /etc/init.d/freeradius stop
$ sudo freeradius -X

先测试使用 LDAP 方式登陆系统是否正确,使用 LDAP 用户名和密码从另一台电脑 ssh 登陆到这台 Radius 服务器,如果不用本地帐号而用 LDAP 帐号顺利登陆的话就说明这台服务器已经能顺利使用 LDAP 登陆了:

$ ssh [email protected]

测试 Radius 服务是否能正确从 LDAP 那里得到验证信息,使用 ldap 用户名和密码测试 Radius 服务是否反馈正确消息 Access-Accept:

$ radtest vpsee "password" 192.168.2.65 1 testing123
Sending Access-Request of id 233 to 192.168.2.65 port 1812
	User-Name = "vpsee"
	User-Password = "password"
	NAS-IP-Address = 192.168.2.65
	NAS-Port = 1
rad_recv: Access-Accept packet from host 192.168.2.65 port 1812, id=233, length=20

另一种办法

另外有个办法是不用 pam 的方式,直接用 freeradius-ldap 模块和 LDAP 服务器连接,这种办法不适合我们实验室的应用场景,不过配置要简单一些。简单说一下就是利用 freeadius 的 ldap 模块直接连接 LDAP 服务器验证用户。先安装 freeradius-ldap 模块:

$ sudo apt-get install freeradius-ldap

然后配置 clients.conf

$ sudo vi /etc/freeradius/module/ldap
...
ldap {
        server = "ldap.vpsee.com"
        identity = "cn=admin,o=My Org,c=UA"
        password = mypass
        basedn = "o=My Org,c=UA"
        filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
...

然后取消下面2个文件里面关于 ldap 的相关注释:

$ sudo vi /etc/freeradius/sites-available/default
$ sudo vi /etc/freeradius/sites-available/inner-tunnel

重启 freeradius 让配置生效:

$ sudo /etc/init.d/freeradius restart