标签归档:linux

kvm、spice安装Windows 7备忘录

去年在一台备用服务器上装了个VirtualBox虚拟机,用headless模式跑Windows 7,当做我的日常用系统,无论在哪都用RDP(Windows的远程桌面协议)远程登上,彻底的大内存、多CPU、千兆接入云桌面,非常舒服。

VirtualBox是个很棒的虚拟机,无论图形界面还是命令行界面,都很好用。但间或死机(虚拟机停转,却把CPU占满),分越多的CPU速度越慢(可能是我后分的多CPU有关),以及虚拟磁盘配置不合理这三个原因,使我萌生了换虚拟机的念头。

这篇评测文章的结果是kvm的性能最好,此外听安天的王维工程师说只有kvm支持的spice协议是目前最快的远程桌面协议,有代码洁癖的我就当然选用它了。但这东西,比VirtualBox和VMWare都难配置太多了……必须得写下来备忘一些要点了。

kvm

kvm本身是个命令行程序,直接“kvm 参数”就能用。一开始就这么用,系统安装顺利,网络通畅。然后加bridged模式的网卡,结果一启动虚拟机就让主机网卡都断掉(甚至一度重启host系统都不能恢复,导致网络中心狠狠地重新收拾了一遍若干台交换机。对此麻烦,深表歉意)。查了无数资料,什么bridge、tun、tap的一通研究,各种脚本、手工试验,全无效。最后实在不想再跑机房了,就换用virt-manager建虚拟机。

virt-manager是libvirt的一个图形客户端,而libvirt是个通用的虚拟机管理库(支持kvm、xen、virtualbox、vmware等等)。virsh是libvirt的命令行客户端,用“virsh -c qemu:///system”可以在命令行管理virt-manager创建的虚拟机。

需要先在系统启动一个桥接网卡,才能在虚拟机里装bridged网卡。修改/etc/network/interfaces(debian)如下:

Windows 7最多只支持两个CPU socket,每个socket内可以有多个core。kvm缺省每个CPU模拟一个socket,必须修改虚拟机CPU的topology,才能使用超过一个CPU。

spice

virt-manager创建的虚拟机只要加了spice display,就可以用spice协议远程使用虚拟机的控制台。

Linux下的spice客户端叫spicec。

最重要的是Win7里必须安装spice的驱动和服务,才能让性能和功能达到最强。相关程序在这里下载:http://www.spice-space.org/download.html

qxl和virtio-serial驱动是必须安装的。如果安装时提示数字签名无效,驱动不生效,用管理员权限执行cmd.exe,运行下面两行命令并reboot(reboot后桌面会有“测试模式”字样,不影响使用):

Windows guest agent服务也必须安装,才能同步剪贴板、屏幕分辨率。解开那个vdagent-xxxxx.zip,在管理员权限命令行执行“vdservice install”,然后reboot。

客户端加上–full-screen=auto-conf参数,就能全屏且同步分辨率了。Shift-F11切换全屏状态

spice性能确实比rdp好太多,看flash、gif基本不卡,视频音画基本同步,鼠标、键盘无延迟。最爽的,可以用招商银行大众版了!

安全的spice

spice缺省使用不安全连接。

用下面脚本创建必须的key

根据提示记住–host-subject,拷贝ca-cert.pem到指定位置

关闭虚拟机,重新启动libvirtd(sudo /etc/init.d/libvirt-bin restart)

客户端用“spicec -h HOSTNAME -s TLS-PORT –host-subject HOST-SUBJECT -w PASSWORD”连接

其它

虚拟机硬件配置很容易调整,导致Windows激活经常失效。在线激活失败时,选电话激活,根据提示打电话,跟客服mm稍加解释,就能顺利激活了。(此条只对正版Windows有效)

主要参考

  1. SSLConnection – Spice
  2. QA:Testcase Virtualization Manually set spice listening port with TLS port set
  3. WinQXL – Spice
  4. Networking – KVM
  5. manpages

(待补充:port forward)

用rdesktop映射本地打印机到远程的要点

Linux端:

  1. rdesktop一定要用“-5”参数。只有RDP5才支持打印机映射
  2. rdesktop映射打印机的参数“-r printer:hp-LaserJet-1010=”HP 1010″”。其中hp-LaserJet-1010必须是Linux上安装的打印机的名字。”HP 1010″可随便起名,貌似是远程Windows看到的打印机名

Windows端:

  1. 貌似不会自动搜索到这个打印机,需要手工添加
  2. 添加打印机->添加本地打印机,在端口中找TS00x这样名的,后面括号里跟着你的Linux主机名和PRN1,然后下一步,选驱动就行了。

rdesktop的代码库最近很长时间一直在更新,但是始终没有发布新版本。可气的是作者把代码树里的Makefile删了,想自己编译一个尝鲜都不能。热烈盼望beta啊!

在Linux下用ffmpeg自拍课程录像

某一天突然觉得,上课时直接用电脑自己把屏幕信息录下来,并同步录音,就能做出很不错的课程录像了,而且成本超级低。于是乎,折腾了一番。

因为我的操作系统课全程在Linux下放幻灯片、做演示,所以当然就寻找Linux下的解决方案。

首先试验了xvidcap,它支持命令行和图形界面两种方式,能同步录音和录像,支持多种编码,2006年开始停止更新。最先遇到的问题是不能录音,几经周折发现只有在音频编码设为pcm16的时候才能录音。然后遇到的问题是不稳定,连续工作一会儿就segment fault。于是放弃。

然后试验了recordmydesktop,它是命令行的,有图形前端,能同步录像和录音,只支持ogv编码和格式,2008年停止更新。它的问题是编码器的CPU消耗太高,我把帧率设成1,才能正常地实时编码。它支持先无损压缩捕获,然后再编码的方式,但因为下课就得走人,没那么多时间给它。从它的源码里发现一个未公开的参数–no-encode,捕获完毕直接退出,以后可以用–rescue参数慢慢编码。看上去很美,但–rescue的结果就是segment fault。调了调代码,没搞定,于是放弃。

开始慨叹咋就没一个像windows下Camtasia那样好用的呢?又几经周折,居然发现ffmpeg就能录!而且几乎100%满足我的需求!下面的脚本就是干这个的:

#!/bin/sh
 
wait_til()
{
    CURRENT=$(date +%s)
    TARGET=$(date -d "$1" +%s)
 
    SECONDS=$(($TARGET - $CURRENT))
 
    if [ $SECONDS -lt 0 ]; then
        SECONDS=0
    fi
 
    sleep "$SECONDS"
}
 
WORKDIR=~/podcast
FILENAME=lecture_`date +%Y%m%d_%H%M`.mkv
 
if [ "$1" != "" ]; then
    wait_til $1
fi
 
cd $WORKDIR
ffmpeg -f alsa -ac 1 -i pulse -f x11grab -r 10 -s 1024x768 -i :0.0 -acodec pcm_s16le -vcodec libx264 -vpre lossless_ultrafast -s 512x384 -threads 0 $FILENAME

将代码存为capscreen文件,赋予执行权限,然后在命令行输入capscreen命令就立刻开始录像了。录好的文件存放在~/podcast中,文件名是“class_日期_时间.mkv”。capscreen后如果加上一个时间参数,就是等到该时刻才开始录像。比如“capscreen 8:00”就是早8点整开始。

这个脚本为了节约CPU资源(我上课用的是上网本,atom cpu,实在能力不足),设定的是图像无损压缩,音频不压缩,帧率10,屏幕分辨率1024×768,视频文件分辨率512×384。过后,可以再用ffmpeg重新编码,制作出适合各种情况的视频,详情请参考这里。如果CPU够劲,可以忽略后期过程,直接输出最终格式,再配合上传脚本,或者nfs、smb一类的网络文件系统,以最快的速度发布。每个教室里的教师机都应该考虑搞个类似的东西。

缺点:

  1. 鼠标指针始终都是一个箭头,而且不能隐藏。这个据说新版ffmpeg已经能处理了。懒得自己编译了,等ubuntu 10.10吧
  2. 不能融合摄像头,做出camtasia那样的画中画功能

增加可被LKM调用的内核函数

LKM(Loadable Kernel Module)可以调用的内核函数及变量都列在/usr/src/linux-headers-xxxxxxxxx/Module.symvers里。有些资料说是在/proc/kallsyms里,这是不对的。kallsyms里列出的是内核中的各种符号,但并不是所有的符号都可以被LKM调用。如果使用了不可用的符号,insmod的时候会报错:Unknown symbol in module

如果想调用Module.symvers以外的内核函数,必须修改内核。找到该函数,在函数结束的“}”后加上一行:

EXPORT_SYMBOL(funcname);

在LKM的源文件中,用extern声明一下该函数。如果这个函数是系统调用,在extern后面还要加上asmlinkage,否则参数不会正确传递。

强制Makefile中的一条必须执行

一个工程有多个子目录。每个子目录下都有一个Makefile,将该子目录下的源代码编译为一个.o文件。根目录下的Makefile控制将这些.o链接到一起形成最终的执行文件。执行文件只依赖.o文件,对每个.o的处理规则都是进入其子目录然后make。这种布局会遇到一个问题,就是子目录里有源码的修改,根目录Makefile定义的依赖关系里检测不到,就不会重新编译。被这个问题困扰很久,今天看qt的Makefile,发现了一个很巧的解决方法。

subdir1/sub1.o: FORCE
    cd subdir1 && make
 
subdir2/sub2.o: FORCE
    cd subdir2 && make
 
FORCE:

给一台没有系统且不能从光驱、U盘、PXE等启动的电脑安装Linux

  1. 把硬盘拆下来,挂到别的机器上,并且拆下那台机器的硬盘;
  2. 在别的机器上安装Linux;
  3. 硬盘换回原先的机器;
  4. done

同样的方法用来安装Windows,硬件的相似度必备比较高才行。Linux貌似并不保存硬件信息,而是每次启动时重新检测。至少我这两台年龄相差6岁的机器没有半点儿相同的硬件。

一台机器同时接多个键盘的系统测试

给笔记本接上了两个usb键盘,做了个测试,觉得挺有意思的。

Windows XP下,用记事本:

  • 两个键盘同时按“a”,出现“aa”;
  • 三个键盘同时按“a”,出现“aaa”;
  • 三个键盘分别按“a”、“b”、“c”,得到abc的随机排列。

貌似没啥特别的。好玩的是在Linux上。

Ubuntu 9.10,Linux 2.6.31。在控制台,一切正常,和XP表现一样。在gnome里:

  • 两个键盘同时按“a”,出现“aaa”;
  • 三个键盘同时按“a”,出现“aaaaa”;
  • 三个键盘分别按“a”、“b”、“c”,得到abc的随机排列。
  • 两个键盘同时按“a”,另一个键盘按“b”,输出结果里必然有一个“b”和三个“a”。

总结一下gnome的规律。设同时按动按键X的键盘个数为k,那么向系统输入的字符X的数目为2*k-1。

不知道这是否该算作一个bug。没有装KDE、xfce等其它窗口管理器,不能推断这是gnome的问题还是X或其它组件的问题。

多IP(路由、接入)Linux系统的管理

曾管理一台同时有教育网、网通和电信三条接入线路的服务器多年,最近终于略有小成,领略了多线管理的要点。想到现在vpn因为某些伟大的原因变得盛行,这也是一种多线路接入,故撰写此文,同时做为自己的备忘。

为简化,下面仅描述双线的情况。假设两条线路的配置如下:

  1. eth0设备,IP:1.1.1.1,网关:1.1.1.9
  2. eth1设备,IP:2.2.2.2,网关:2.2.2.9

1. 配置基本路由

路由决定了从本地访问不同网站会自动从哪条线路走。比如运行命令:

route add -net 3.3.3.3 netmask 255.255.255.0 gw 1.1.1.9

此后所有对3.3.3.x的访问都会自动从线路一出去。线路一访问哪里快,就把到哪里的路由都配到线路一,然后把线路二配成缺省路由:

route add -net default gw 2.2.2.9

这样所有不从线路一走的访问就从线路二走了。当然,也可以让线路一做缺省,线路二逐条配,具体情况就看怎么方便了。

2.配置基于源地址的策略路由

对于一般用户而言,完成基本路由的配置就够了。但如果这台机器希望通过两条线路同时对外提供服务,或者想使用后面第4条介绍的东东,那么就必须配置源地址路由。为什么呢?原因并不难理解,但挺绕嘴,所以我就不说了。

首先修改/etc/iproute2/rt_tables,增加类似下面两行:

100 line1
101 line2

再用下面命令完成路由配置:

ip route add default via 1.1.1.9 table line1
ip rule add from 1.1.1.1 table line1
ip route add default via 2.2.2.9 table line2
ip rule add from 2.2.2.2 table line2

上面命令的意思是让所有从1.1.1.1发出的包都走1.1.1.9这个网关,所有从2.2.2.2发出的包都走2.2.2.9这个网关。

3. 测速

ping是最常用的测速命令。如果想测试到一个网站(比如:3.3.3.3)的速度,可以先把它路由到线路一,ping一次,再路由到线路二,再ping一次,比较ping的结果决定把它放入哪个路由。这样太麻烦了。无论当前路由是什么样,用下面命令

ping -I eth0 3.3.3.3

都是从线路一ping 3.3.3.3。同理:

ping -I eth1 3.3.3.3

都是从线路二ping 3.3.3.3。

我还拼凑出一个脚本,命名为mping,可以一行命令从多条线路ping一个网址,如下:

#!/bin/sh
 
ifconfig  | grep 'inet addr:'| grep -v '127.0.0.1' | 
cut -d: -f2 | awk '{ print $1}' |
xargs --verbose -I srcip fping $* -eS srcip 2>&1

使用它之前得先安装fping。

4. 若干命令忽视路由的参数

很多命令都能忽视路由配置,直接通过参数指定走哪条线路,列出我知道的几个:

wget --bind-address=x.x.x.x ......
ssh -b x.x.x.x
lftp中set net:socket-bind-ipv4 x.x.x.x

squid中可以这样配置:

acl bgfw dstdomain .google.com .wikipedia.org .............
tcp_outgoing_address x.x.x.x bgfw

我猜想,应该有某个命令可以以wrapper,通过它启动的进程发出网络连接时的来源地址永远是这个命令指定的地址。但我没搜到这样的东东。如果谁知道,赶快告诉我!