解决 /dev/null is not a character device! 问题

昨天我们一个客户无法 ssh 到他的 VPS,但是可以 ping 通。从控制台上看没有异常,登陆进去后发现 ssh 服务没有启动,企图启动(重启)这个服务时报错 /dev/null is not a character device!:

# /etc/init.d/ssh restart
Restarting OpenBSD Secure Shell server: sshd failed!
/dev/null is not a character device!.

解决办法是,删除 /dev/null 后重建一个字符设备:

# rm -f /dev/null
# mknod /dev/null c 1 3

然后启动(重启)ssh 就可以了:

# /etc/init.d/ssh restart
Restarting OpenBSD Secure Shell server: sshd.

OneStack:分步部署 All-in-One 的 OneStack 实验环境

囧,上次 OneStack 项目作者 Kayven 发过来的 OneStack 介绍和配置的文章只发了一半就忘了(本来打算分两部分发的~),今天在草稿箱里把这部分整理出来了,希望文章内容还没有过时(OpenStack 和 Ubuntu 版本都有了很大变化 …)。

前部分介绍请看:OneStack:Ubuntu 12.04 上一键自动部署 OpenStack。下面介绍的是用 OneStack 分步部署 OpenStack 的方法:

1、切换 root,或者用 sudo 执行脚本:

$ sudo -i

2、(可选,如果不需要跳过本步骤):
系统语言设置,可以参考 oneStack.sh locale 部分,不在此介绍。比如设置 apt 源:

# vi /etc/apt/sources.list

3、设置网络(可以参考 oneStack.sh locale 部分):

# vi /etc/network/interfaces

4、配置参数,除了网络 ip,其它可以不变:

## 数据库
MYSQL_PASSWD=${MYSQL_PASSWD:-"cloud1234"}
## 自行检查下面network/interfaces的两个网卡设置与此处一致
OUT_IP="192.168.139.50"
## 选择虚拟技术,裸机使用kvm,虚拟机里面使用qemu
VIRT_TYPE="qemu"
## token, 登录dashboard密码
ADMIN_TOKEN="admin"

5、部署基本系统

./setup_base.sh

6、添加镜像(Ubuntu12.04),添加一个实例,注意:里面的 ip 需要自己配置,镜像地址可以自己改动:

./setup_test.sh

7、分别部署控制节点和计算节点:
控制节点同上,可以去掉 nova-compute;
计算节点,只需要配置网络、数据库、虚拟机技术即可。

配置参数,除了计算节点 ip,其余与控制节点相同(包括 nova.conf 里的 ip)自行检查下面 network/interfaces 的两个网卡设置:
ServerControlIP=”192.168.139.50″
computeControlIP=”192.168.139.150″ # 本计算节点的外网IP

## token, 登录 dashboard 密码
ADMIN_TOKEN="admin"

## 网络配置
NETWORK_CONF=${NETWORK_CONF:-"/etc/network/interfaces"}
cat <$NETWORK_CONF
# The primary network interface
auto eth0
iface eth0 inet static
pre-up ifconfig eth0 hw ether b8:ac:6f:9a:ee:e5 #不需要绑定网卡的不需要这一行
        address 192.168.139.51 #外网ip
auto eth1
iface eth1 inet static
pre-up ifconfig eth1 hw ether b8:ac:6f:9a:ee:e5
        address 10.0.0.2 #内网IP

INTERFACES
sed -i -e "s/192.168.139.51/$computeControlIP/g" $NETWORK_CONF
/etc/init.d/networking restart

注意:以下与控制节点相同

## 配置 /etc/nova/nova.conf,这里与控制节点的配置相同!比如ip是控制节点的ip
MYSQL_PASSWD=${MYSQL_PASSWD:-"cloud1234"}
NOVA_DB_USERNAME=${NOVA_DB_USERNAME:-"novadbadmin"}
NOVA_DB_PASSWD=${NOVA_DB_PASSWD:-"cloud1234"}
OUT_IP="192.168.139.50" 
……
## 选择虚拟技术,裸机使用 kvm,虚拟机里面使用 qemu
VIRT_TYPE="qemu"

7、执行 ./addComputeNode.sh

./addComputeNode.sh

如果对这篇有任何技术问题请直接咨询 OneStack 项目的原作者 Kayven (Hily.Hoo@gmail.com),git/github 粉也可以从这里获得源码: https://github.com/Kayven/OneStack

Bash 通过上下键更有效的查找历史命令

我们知道在 bash 里,可以通过 “上下” 键来浏览最近执行过的命令历史纪录(history),我们也知道如果历史纪录太多的话可以通过 ctrl+r 来查找命令或者通过 history 命令来浏览历史命令。我们不知道的是(也许只有本人不知道~),还有一种神奇的办法可以更准确、有效的在历史命令纪录中查找自己想要的命令。

在自己的用户主目录(home directory)新建一个 .inputrc 文件:

$ vi ~/.inputrc
"\e[A": history-search-backward
"\e[B": history-search-forward
set show-all-if-ambiguous on
set completion-ignore-case on

退出 bash 后重新登陆,敲打一个字母或者几个字母,然后 “上下” 键,就会看到以这个字母搜索到的完整命令行。如果搜索到几个类似命令,通过上下键来切换,有点像 ctrl+r,但是更好用。

DMTCP 分布式多线程检查点工具

高性能计算/分布式计算等大量计算需要程序运行几天、几周甚至几个月,如果期间因为电力或者不可避免的问题导致程序中断会浪费大量的时间和人力,还有超级计算机在这段时间里运行的电力成本。我们没有遇到过电力问题,不过我们最近遇到的场景是实验室需要做强制安全检查,要求关闭所有电脑,所以我们需要一种工具能设置断点暂停程序、把状态保存到硬盘、再按照要求恢复,就像程序员用 IDE 调试程序一样,设置断点、单步跟踪(或恢复运行)。

在多主机、多线程的复杂分布式计算环境,给程序设置断点不是一件容易的事情,因为程序的某部分可能在其他主机上运行。DMTCP: Distributed MultiThreaded CheckPointing 是我们目前正在考察的一个工具之一,我们喜欢它的一个原因是它不需要修改 Linux 内核,不依赖内核和内核模块。

安装

先安装一些编译 DMTCP 需要用到的软件包:

$ sudo apt-get install build-essential

下载 DMTCP 源代码后,解压、配置、编译、安装:

$ wget http://ufpr.dl.sourceforge.net/project/dmtcp/dmtcp/1.2.7/dmtcp-1.2.7.tar.gz
$ tar zxvf dmtcp-1.2.7.tar.gz
$ cd dmtcp-1.2.7
$ make
$ sudo make install

我们先来看一个例子程序,转到 dmtcp-1.2.7 里的 test 目录运行 dmtcp1,这个例子很简单,按照顺序输出 1 2 3 … 数字:

$ cd test
$ ./dmtcp1
  1   2   3   4   5   6 ^C

接下来我们要试验的是,中断这个例子程序,然后看看能不能恢复它。步骤是:

  1. 启动控制端 dmtcp_coordinator;
  2. 用 dmtcp_checkpoint 运行这个 dmtcp1 程序;
  3. 强制中断 dmtcp1;
  4. 恢复运行 dmtcp1.

使用

开另外一个窗口或者 screen 运行控制端 dmtcp_coordinator,用 l 查看当前节点状态:

$ dmtcp_coordinator
dmtcp_coordinator starting...
    Port: 7779
    Checkpoint Interval: disabled (checkpoint manually instead)
    Exit on last client: 0
Type '?' for help.

?
COMMANDS:
  l : List connected nodes
  s : Print status message
  c : Checkpoint all nodes
  i : Print current checkpoint interval
      (To change checkpoint interval, use dmtcp_command)
  f : Force a restart even if there are missing nodes (debugging only)
  k : Kill all nodes
  q : Kill all nodes and quit
  ? : Show this message

l
Client List:
#, PROG[PID]@HOST, DMTCP-UNIQUEPID, STATE
[7845] NOTE at dmtcp_coordinator.cpp:1039 in onConnect; REASON='worker connected'
     hello_remote.from = b51cf8-7846-516fbedc(-1)

然后重新用 dmtcp_checkpoint 运行 dmtcp1 这个例子程序:

$ dmtcp_checkpoint ./dmtcp1
dmtcp_checkpoint (DMTCP + MTCP) 1.2.7
Copyright (C) 2006-2011  Jason Ansel, Michael Rieker, Kapil Arya, and
                                                       Gene Cooperman
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see COPYING file for details.
(Use flag "-q" to hide this message.)

  1   2   3

回到控制端,l 一下就会看到多了条结点状态,dmtcp1 程序[进程号 7846]运行在主机名为 vpseedev 的主机上。

l
Client List:
#, PROG[PID]@HOST, DMTCP-UNIQUEPID, STATE
1, dmtcp1[7846]@vpseedev, b51cf8-7846-516fbedc, RUNNING

现在我们在控制端设置一个检查点(checkpoint),用 c 命令:

c
[7845] NOTE at dmtcp_coordinator.cpp:1315 in startCheckpoint; REASON='starting checkpoint, suspending all nodes'
     s.numPeers = 1
[7845] NOTE at dmtcp_coordinator.cpp:1317 in startCheckpoint; REASON='Incremented Generation'
     UniquePid::ComputationId().generation() = 1
[7845] NOTE at dmtcp_coordinator.cpp:643 in onData; REASON='locking all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:678 in onData; REASON='draining all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:684 in onData; REASON='checkpointing all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:694 in onData; REASON='building name service database'
[7845] NOTE at dmtcp_coordinator.cpp:713 in onData; REASON='entertaining queries now'
[7845] NOTE at dmtcp_coordinator.cpp:718 in onData; REASON='refilling all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:747 in onData; REASON='restarting all nodes'
[7845] NOTE at dmtcp_coordinator.cpp:919 in onDisconnect; REASON='client disconnected'
     client.identity() = b51cf8-7846-516fbedc

然后用 Ctrl + c 强制中断这个正在运行的 dmtcp1:

$ dmtcp_checkpoint ./dmtcp1
dmtcp_checkpoint (DMTCP + MTCP) 1.2.7
Copyright (C) 2006-2011  Jason Ansel, Michael Rieker, Kapil Arya, and
                                                       Gene Cooperman
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see COPYING file for details.
(Use flag "-q" to hide this message.)

  1   2   3   4   5   6   7   8 ^C

这样在当前目录 test 下会生成一个临时文件用来保存程序镜像(稍后会看到就是通过这个文件来恢复程序的):

$ ls -l ckpt_dmtcp1_b51cf8-7846-516fbedc.dmtcp
-rw------- 1 vpsee vpsee 2532431 Apr 18 09:37 ckpt_dmtcp1_b51cf8-7846-516fbedc.dmtcp

用 dmtcp_restart 恢复就会看到 dmtp1 这个例子程序(从它中断的地方)继续运行了:

$ dmtcp_restart ckpt_dmtcp1_b51cf8-7846-516fbedc.dmtcp
dmtcp_checkpoint (DMTCP + MTCP) 1.2.7
Copyright (C) 2006-2011  Jason Ansel, Michael Rieker, Kapil Arya, and
                                                       Gene Cooperman
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; see COPYING file for details.
(Use flag "-q" to hide this message.)

  9  10  11  12 ^C

DMTCP 甚至允许我们把运行了一半的程序暂停、保存到硬盘、拷贝到其他服务器上、继续运行,很酷吧~

Xen 半虚拟化安装 NetBSD 虚拟机(domU)

很久以前我们开始提供 NetBSD 的 VPS,期间陆续有朋友写信询问怎么制作 NetBSD/FreeBSD 的半虚拟化(PV)Xen 镜像,今天以安装最新的 NetBSD 6.0.1 版本为例演示一下,随便说一下制作 FreeBSD PV 虚拟机方法是类似的。Xen 全虚拟化方式(HVM)安装 NetBSD 虚拟机就不说了,和安装其他操作系统 Linux, Windows 差不多,毕竟全虚拟化不用考虑内核,安装要简单得多。考虑到性能,半虚拟化依然是 Xen 的强项,所以我们的 VPS 都是采用半虚拟化的,不过随着硬件的发展和 CPU 厂商的大力支持,半虚拟化的优势正渐渐消失。

这里演示的是安装 NetBSD domU,如果想了解安装 NetBSD dom0 的话看这里:在 NetBSD 上安装和配置 Xen.

准备

新建一个目录,然后下载一些东西,netbsd-INSTALL_XEN3_DOMU.gz 是安装 NetBSD 时候用的内核,netbsd-XEN3_DOMU.gz 是运行 NetBSD 用的内核,不要弄混了;NetBSD-6.0.1-amd64.iso 是我们需要的安装光盘。

$ mkdir netbsd
$ cd netbsd

$ wget http://ftp.netbsd.org/pub/NetBSD/NetBSD-6.0.1/iso/NetBSD-6.0.1-amd64.iso

$ wget http://ftp.netbsd.org/pub/NetBSD/NetBSD-6.0.1/amd64/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz
$ wget http://ftp.netbsd.org/pub/NetBSD/NetBSD-6.0.1/amd64/binary/kernel/netbsd-XEN3_DOMU.gz

安装

首先制作一个大小为 5GB 的硬盘:

$ dd if=/dev/zero of=netbsd.disk bs=1024k count=1 seek=5000

然后新建一个 Xen domU 配置文件,并输入以下内容,:

$ vi netbsd
name = "netbsd"
memory = "256"
kernel = "/home/vpsee/netbsd/netbsd-INSTALL_XEN3_DOMU.gz"
disk = [ 'file:/home/vpsee/netbsd/netbsd.disk,xvda,w', 'file:/home/vpsee/netbsd/NetBSD-6.0.1-amd64.iso,ioemu:hdc:cdrom,r' ]
vif = [ 'bridge=xenbr0' ]
vcpus = "1"

使用 root 帐号启动这个名为 netbsd 的虚拟机开始 NetBSD 安装过程,这一步需要注意的是在选择安装介质的时候选择从 CD-ROM 安装并使用设备名 xbd0a (device [xbd1a]: xbd0a):

$ su

# xm create netbsd -c

NetBSD 安装界面如下,顺着屏幕提示安装即可,没有难度:

google apps directory sync

安装完毕后关闭这个虚拟机,修改 netbsd 的 Xen 配置文件,然后用新的配置文件启动虚拟机:

# xm destroy netbsd

# vi netbsd
name = "netbsd"
memory = "256"
kernel = "/home/vpsee/netbsd/netbsd-XEN3_DOMU.gz"
disk = [ 'file:/home/vpsee/netbsd/netbsd.disk,xvda,w' ]
vif = [ 'bridge=xenbr0' ]
vcpus = "1"

# xm create netbsd
Using config file "./netbsd".
Started domain netbsd

虚拟机启动后用 xm list 确认一下,然后就可以从控制台登陆 NetBSD 虚拟机了:

# xm list
Name                                      ID Mem(MiB) VCPUs State   Time(s)
Domain-0                                   0     1024     4 r----- 279689.0
netbsd                                   242      256     1 -b----      0.6

# xm console netbsd

剩下的配置 NetBSD 环境、IP 地址等这里就不用赘述了~

迁移 LDAP 用户到 Google Apps 平台

人手和精力不足的情况下自己维护邮件服务器实在是件头疼的事情,我们打算把这件吃力不讨好的事交给 Google,有免费的 Google Apps for Education 为啥要自己弄呢?Gmail 要比自己搭建的 SquirrelMail 和 roundcube 界面好用多了,而且还有免费的 Google Docs, Google Drive, Google Chat 可用,非常适合我们现在的情况。

我们的用户信息都保存在一台 LDAP 服务器上,要把全部用户信息(用户名、密码、Email、电话等)迁移到 Google Apps 的话需要迁移工具(没人想手动输入500个用户和电话!)。自己用 Python-LDAP 和 Google Apps Administrative APIs 写个 LDAP 到 Google Apps 的转换工具应该不难,不过要更懒一点,找现成工具。。。

Google 为帮助我们这些懒人和企业用户把数据迁到云端开发了不少工具,Google Apps Directory Sync 正是我们要找到,一个用于同步 LDAP 活动目录到 Google Apps 的好工具。

步骤

1、首先登陆到 Google Apps 平台,在自己帐号里的 Domain settings 的 User settings 页面选择 “Enable provisioning API”;

google apps directory sync

2、下载 Windows 或 Linux 版本的 Google Apps Directory Sync 工具并安装;

3、打开 Google Apps Directory Sync 工具,在里面依次配置 General Settings, Google Apps Configuration, LDAP Configuration, User Accounts, Notifications 等,LDAP 配置支持 MS Active Directory, OpenLDAP, Lotus Domino,我们的 LDAP 服务器用的是 OpenLDAP;

4、如果一切正常,在 Sync 里的 Validation Results & Sync 会看到 “打勾” 状态;

5、在真正同步(Sync & apply changes)之前先模拟(Simulate sync)一遍,点击下面蓝色的 “Simulate sync” 会出来结果报告;

google apps directory sync

6、查看上面的模拟结果,如果符合自己的要求的话就可以点击红色的 “Sync & apply changes” 开始实际操作了。

几个常用 Linux 桌面/窗口管理器的内存占用对比

A Memory Comparison of Light Linux Desktops 这篇文章比较了几个常用 Linux 桌面/窗口管理器的内存占用情况,个人使用的比较多的超轻量级窗口管理器 dwm 只占用 1MB,Fluxbox 占用 16MB,XFCE 占用 70MB,平铺窗口管理器里面最受欢迎的 xmonad 没有被提及。

大家喜欢用什么桌面/窗口管理器呢?

桌面/窗口管理器 内存占用
wm2 0.7MB
dwm 1MB
Ratpoison 1MB
JWM 3MB
i3 3MB
Blackbox 3MB
IceWM 4.5MB
Openbox 7MB
Window Maker 7MB
awesome 9MB
FVWM 13MB
Fluxbox 16MB
E17 35MB
LXDE 36MB
XFCE 70MB
Gnome 3 155MB
Unity 192MB
KDE 201MB

如何在 Xen dom0 下判断 domU 的硬盘使用率?

在 Xen 环境下我们可以很容易在 dom0 上通过 xm top 命令得到 domU 的当前运行状态信息,比如 domU 的 CPU 使用率,占用内存,IO 读写,网络等,但是无法知晓 domU 硬盘的使用情况,用了多少 inode、多少空间,还剩多少,是否快爆满、是否应该通知客户升级 Xen 硬盘等。这时候需要一种办法能得到 domU 上的硬盘信息,不一定要特别准确,只要不太离谱就行。我们使用 dumpe2fs 这个工具来打印客户的硬盘使用率,需要注意的是这个工具只针对 ext2/ext3/ext4 文件系统格式有效,也就是说只能用在那些使用 ext2/3/4 文件系统的 domU 中。

如果 Xen domU 使用的是文件格式的镜像:

# dumpe2fs -h /var/vps/images/vpsee.img
dumpe2fs 1.39 (29-May-2006)
Filesystem volume name:   
Last mounted on:          
Filesystem UUID:          e1f1f647-2098-4cfa-a1a3-9a44d4f93348
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal resize_inode dir_index filetype needs_recovery sparse_super large_file
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              2567264
Block count:              5120256
Reserved block count:     256012
Free blocks:              2674639
Free inodes:              1018476
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      621
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         16352
Inode blocks per group:   511
Filesystem created:       Sat Nov  7 06:25:55 2009
Last mount time:          Sat Sep  8 13:37:54 2012
Last write time:          Sat Sep  8 13:37:54 2012
Mount count:              3
Maximum mount count:      21
Last checked:             Fri Mar 23 12:34:20 2012
Check interval:           15552000 (6 months)
Next check after:         Wed Sep 19 12:34:20 2012
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:		  128
Journal inode:            8
First orphan inode:       1242758
Default directory hash:   tea
Directory Hash Seed:      a62d3cd5-9789-49bf-86c7-efee3d0286d4
Journal backup:           inode blocks
Journal size:             128M

如果 Xen domU 使用的是 LVM 格式的镜像:

# dumpe2fs -h /dev/vol-vps/vpsee_img 

从上面的 Inode count, Block count, Free blocks, Free inodes, Block size 等就可以判断出硬盘的使用率情况。

用 NetHogs 监控 Linux 每个进程的网络使用情况

有时候我们客户会发现服务器或 VPS 网络慢,进一步发现大量带宽被占用,一些客户到这里为止就不知道怎么办了。有什么简单办法能找出哪个程序(或者进程)占用了带宽呢?Linux 监控流量的小工具不少,如 iftop, iptraf, ifstat, darkstat, bwm-ng, vnstat 等,大都是统计和监控网卡流量的。今天介绍的 NetHogs 有点特别,可以监控每个进程的网络带宽占用情况。

在 Ubuntu/Debian 上安装 nethogs:

$ sudo apt-get install nethogs

在 CentOS/RHEL 上安装 nethogs:

# yum install nethogs

运行 nethogs:

# nethogs

# nethogs eth0

nethogs

定制 Ubuntu 安装盘

最近在准备一个关于高性能计算方面的 workshop,需要50台笔记本,这样每个人在 workshop 上都可以自己动手实践和学习。给50台笔记本安装系统是个体力活,因为全部要 WiFi,无线网卡又无法做 PXE 开机启动(市面上支持无线网卡启动的好像很少),那种通过 PXE 启动的办法就行不通,所以我们的 Cobbler 服务器也派不上用场。现在考虑的办法是自制基本的 Ubuntu 系统、做10个 U 盘、修改 BIOS 后用 USB 启动安装,安装完毕后再通过 Puppet 统一管理50台笔记本,这样可以灵活应对 workshop 中间可能出现的变化,比如某时候需要安装 Java 环境、集体修改密码等。

自己定制 Ubuntu 安装盘有很多现成工具,Ubuntu Customization Kit 和 Ubuntu Builder 是用的较多的两个,我们这里选用 Ubuntu Builder. 使用这类工具之前我们都需要一个原版的 Ubuntu ISO(ubuntu-12.04.2-desktop-amd64.iso),这样才能在此基础上做定制。

安装和运行:

$ sudo add-apt-repository ppa:f-muriana/ubuntu-builder
$ sudo apt-get update
$ sudo apt-get install ubuntu-builder

$ ubuntu-builder

可以定制的选项不是很多,选择我们要定制的 ISO、选择要安装的桌面环境(窗口管理器)、编辑一下 sources.list 使用我们内部的源(这样50台笔记本同时升级和安装软件都快很多)、安装一些我们要的软件包(比如 openssh-server, puppet 在 Ubuntu 12.04 Desktop 版本中没有默认安装。)等等。

ubuntu builder

定制完成后点击 Build 就会开始创建新的 Ubuntu ISO,build 完成后会在 /home/ubuntu-builder 目录下出现一个新的 iso 文件,这个文件就是刚刚定制的 Ubuntu 安装 ISO 文件,可以用 VirtualBox 试一下是否可用,然后刻成 CD/DVD 或者 USB 盘就可以了。