I am LAZY bones? AN ancient AND boring SITE

linux下的“虚拟光驱”

每当有人问我“你的linux下有没有类似‘虚拟光驱’的软件呢?”的时候,我就会轻轻一笑,自豪地说“别把事情想得太复杂,linux下根本就不用什么另外的软件,就能虚拟光驱了。”,然后那人一般就会似懂非懂地说一句:“哦。。这样啊~”
下面,就来介绍几个虚拟光驱相关的命令:
把物理光盘做成iso镜像,下面几个命令几乎等效,假设设备是/dev/cdrom:

cp /dev/cdrom xxx.iso
dd if=/dev/cdrom of=xxx.iso
mkisofs -r -o xxx.iso /dev/cdrom
readcd -v dev=/dev/cdrom -f xxx.iso

其中,用mkisofs还可以把一个文件夹模拟成iso:

mkisofs -o xxx.iso /path/to/tree

如果要使用iso文件的话,就更简单了,可以mount到任意目录下:

mount -o loop xxx.iso /path

注意以上某些命令可能需要root权限。

不过,还有个终极问题没有解决,我手头有一张《浙江省汽车驾驶人理科考试智能》的光盘,估计是用了什么防拷贝技术,使用以上方法都无法正确生成ISO文件,也无法全部复制里面的内容,具体操作过程如下:

lily@LLY:~$ sudo mount -o ro,loop /dev/sr0 qc
lily@LLY:~$ ls qc
试题10.db  试题11.db  试题12.db  试题1.db  试题2.db  试题3.db  试题4.db  试题5.db  试题6.db  试题7.db  试题8.db  试题9.db
lily@LLY:~$ sudo umount qc
lily@LLY:~$ sudo mount -o ro /dev/sr0 qc
lily@LLY:~$ ls qc
2009理论模拟考试.exe  AutoRun.ico  AutoRun.rdt  system               试题10.db  试题1.db  试题4.db  试题7.db
AutoRun.ard           autorun.inf  htm          安装使用说明.html    试题11.db  试题2.db  试题5.db  试题8.db
AutoRun.exe           autorun.pro  image.jpg    读安装使用说明.html  试题12.db  试题3.db  试题6.db  试题9.db
lily@LLY:~$ cp -r qc qc1
cp: 正在读入"qc/试题3.db": 输入/输出错误
cp: 正在读入"qc/试题4.db": 输入/输出错误
{1}lily@LLY:~$ ls qc1
2009理论模拟考试.exe  AutoRun.ico  AutoRun.rdt  system               试题10.db  试题1.db  试题4.db  试题7.db
AutoRun.ard           autorun.inf  htm          安装使用说明.html    试题11.db  试题2.db  试题5.db  试题8.db
AutoRun.exe           autorun.pro  image.jpg    读安装使用说明.html  试题12.db  试题3.db  试题6.db  试题9.db
lily@LLY:~$ du -s qc qc1
398463	qc
349720	qc1

有谁知道这种变态的光盘怎么搞定吗?

点击触摸板模拟左键单击

这几天估计是比较背,刚说我的神舟本2年都没啥问题,结果,前几天发现光驱读盘能力不行了,最近又发现触摸板的左键也不灵了,要按得很重才能产生一次有效的单击事件,双击就更难了。这样下去,手指都要按残了,唉~
然后试了下,轻触触摸板模拟鼠标单击的功能在我的gentoo下默认是无效的,于是第一个想到的就是 xorg.conf 这个即将成为历史的东西。但是我已经不用这个配置文件很久了,现在为了触摸板,没办法,看来只能再请它出山了。于是翻出我的配置文件,在 Section “InputDevice” 一节里加上 Option “TapButton1” “1” 这行,一边心里在纳闷为什么X不默认启用这项呢?
加完重启了X以后,在登录界面试了一下,嘿嘿,果然可以了点击了,于是兴高采烈地登录我的gnome,结果再一看,怎么又不行了呢?明明刚才还可以的啊。难道是gnome的问题?上网一查,发现果然是,在gnome的“系统”->“首选项”->“鼠标”->“触摸板”里,有一项“Enable mouse clicks with touchpad”,勾上这个就好了。
然后再一转念,那在 xorg.conf 里的设置不是多此一举了吗?毕竟我不怎么关心登录界面能不能点击啊。
于是重新删除了 xorg.conf 重启X,登录gnome以后,果然也是可以的。
至此终于知道X为什么不默认启用触摸板点击了,哈哈,既然有DE做这个事情,自然就可以偷偷懒了,不过不知道用*box之类的WM的用户是怎么设置呢?

清理ubuntu老内核的小脚本

ubuntu用久了,升级了几次内核以后,就免不了需要清理一下老的内核,毕竟一套内核就有170多M的空间呢。但是每次都打一堆字来清理也烦了。虽然Ubuntu 命令技巧(这里再罗嗦几句:如果还有ubuntuer没看过这个,强烈建议看一遍。)里有删除旧内核的命令,而且就一行:

sudo aptitude purge ~ilinux-image-.*\(\!`uname -r`\)

但是我却不是很喜欢,因为这这个没有把linux-headers-xxx删除掉。
于是自己写了个繁的,需要的可以自己保存,以便不时之需。

#!/bin/bash
# 清理ubuntu的老内核
# by bones7456
# http://li2z.cn
CURRENT="`uname -r | awk -F"-" '{print $1"-"$2}'`"
HEADERS=""
IMAGES=""
for HEADER in `dpkg --get-selections | grep ^linux-headers | \
grep -vE "(generic|386|virtual)" | awk '{gsub(/linux-headers-/,"",$1);print $1}'`
do
    if [[ "$CURRENT" < "$HEADER" ]]
    then
        echo "正在运行的内核不是最新的。 $CURRENT < $HEADER"
        echo "Running kernel is not the newest. $CURRENT < $HEADER"
        exit 1
    else
        [[ "$CURRENT" != "$HEADER" ]] && {
            HEADERS="${HEADERS} linux-headers-${HEADER}"
            IMAGE="`dpkg --get-selections | grep ^linux-image | \
                grep "${HEADER}" | awk '{print $1}'`"
            IMAGES="${IMAGES} $IMAGE"
        }
    fi
done
 
if [[ x"$HEADERS" == x"" ]]
then
    echo "没有要清理的老内核."
    echo "No old kernel need to clean."
    exit 0
fi
CMD="sudo apt-get purge $HEADERS $IMAGES"
echo "$CMD"
if [ "$1" == "-e" ]
then
    sh -c "$CMD"
else
    echo "请确定以上命令是否正确,然后输入 $0 -e 来执行以上命令。"
    echo "Be sure this command is right, then type $0 -e to execute."
fi

我也玩了下WIN7

曾经,我也有一个XP,虽然平时很少用到,但是在偶尔想玩玩游戏、或者要用到网银的时候,还是要发挥一下作用的,而且曾经的深度精简版也不是很占空间,于是,这个NTFS分区,就一直静静地留在了我的硬盘里了。
直到去年末,回老家办婚礼摆酒的时候,家里人来人往地比较多,有时候有的亲戚朋友要用下电脑,我不可能开个gentoo给人家啊,于是就打开这个XP,没过几天,再去看的时候,发现XP已经中毒很深了。。。要知道我这XP可是没有任何杀软的啊。唉,脆弱的win啊~
于是,这段时间也陆陆续续想了不少办法来拯救这个可恶的XP:曾经在linux下给它杀毒,杀出一堆来,能登录了却慢得出奇,常常还有不可预计的问题;曾经想用虚拟机里XP的文件来覆盖系统文件,要么不管用,要么启动的时候直接蓝屏,搞得我一点办法都没有;甚至也想过重装,但是发现我的光驱已经不能读盘了,无法从光盘引导;也试过硬盘安装,DOS也进去了,执行XP安装程序的时候,却总是说没有什么临时文件的空间。。。
搞得我只能把这个分区的所有文件都删了,后来,花花说硬盘安装WIN7比较方便,抱着试试看的心态,去下了个本以为永远不会去装的win7镜像,开始折腾。
下载到的文件名为 m2.wim ,要用一个叫 ImageX 的玩意打开或者挂载,于是在虚拟机里挂载以后,把文件都提取出来了,最终都放到原来那个NTFS分区的根目录里,一共只有5个目录和一个文件:Boot、Program Files、ProgramData、Users、Windows和bootmgr,很显然,bootmgr就是用于引导的文件,但是原来XP里的引导文件叫做NTLDR啊,grub也只会引导这个文件,所以把bootmgr又复制了一份叫NTLDR,然后直接重启,grub里选择原来XP的条目,一回车,还真进去了。。。
首次进入系统,会自动安装一堆驱动,我这个神舟本除了显卡驱动没认出来,分辨率只上到1440×1050外,其他硬件基本都能自己装好驱动,装好后重启一次,再下个显卡驱动,默认就是下面这个样子了,哈哈:

还蛮舒服的哈,大小也比较合理,wim文件是 350M ,解压后是800多M,装好以后包括一些软件在1.5G以内吧。
虽然偶尔也会有如图的“内存不能为read”的经典又深奥的错误,但是谁在乎呢?
看来,以后真要告别XP喽~

让ubuntu也来帮gentoo编译

最近,貌似关于gentoo的新闻越来越多了。刚又听说,chrome OS的宿主系统已经从ubuntu转向gentoo了,其实,我对这个倒是一点都不感到意外,gentoo对于这种特定的应用,可定制性显然比ubuntu强很多,让我来选的话也会选gentoo的。只是觉得一向低调的gentoo被google这么一搞,也许以后都没有办法再低调了,哈哈。
好像有点扯远了,说到gentoo,大家肯定会想到无休止的编译,也确实,gentoo的编译是比较费时间的,尤其是在性能不怎么强悍的机器上,比如跑着chrome的上网本里。如果你另外有几台强悍些的台式机或者服务器的话,其实可以把编译的工作分担一部分给强悍的机器。这时候就要用到distcc了。
distcc是一个通过网络进行分布式编译的工具,它包含两部分,一部分是服务端程序 distccd,一部分是客户端程序 distcc。大致的原理就是,distcc连接一个或多个distccd,有编译任务的时候,distcc依次并行地把C或C++文件分发给各distccd,distccd调用它们本地的编译器编译出 .o 文件以后,再发回给distcc,另外,configure和link等工作还是由客户端自己来完成。
这样一来,对各服务端的系统也就有了一个额外的要求:必须保证服务端和客户端的gcc版本是一致的,否则出来的.o肯定link不了啊,呵呵。
如果你的客户端和服务端都装的是gentoo,采用的一样的架构和keywords,那其实这个要求还是很好满足的:两边都升到最新即可,这样配置方法可以参考官方文档
但是如果你想用装着ubuntu、fedora、RHEL等发行版的服务端的话,就有点困难了,gentoo如果开了~x86的话,gcc的版本很容易就比这些发行版高出一大截了。
本文就是要解决这个问题的:

解决的思路,就是利用chroot,在各发行版里构建一套没有内核的gentoo系统(因为有kernel也用不着嘛),然后把里面的编译环境都升级到最新,再在里面安装运行distccd。
条件是你需要有server的root权限。
方法其实也不难,大致如下:

#建立gentoo的根目录,这里最好有>1.5G的硬盘空间,不然会不够用
mkdir gentoo
cd gentoo
#可以从 http://www.gentoo.org/main/en/mirrors.xml 这里选择速度快的mirror。
#下载你需要的架构的stage3
wget http://gentoo.cs.nctu.edu.tw/gentoo/releases/x86/current-stage3/stage3-i686-20100126.tar.bz2
#下载最新的portage树,其实不下也是可以的,不过后面emerge --sync的时候会慢些。
wget http://gentoo.cs.nctu.edu.tw/gentoo/snapshots/portage-latest.tar.bz2
#释放文件
tar xvf stage3-i686-20100126.tar.bz2 -C .
tar xvf portage-latest.tar.bz2 -C usr/
#清理现场
rm stage3-i686-20100126.tar.bz2 portage-latest.tar.bz2

然后,为了方便起见,在当前目录写一个gogentoo的脚本,内容如下,加上可执行权限:

#!/bin/bash
 
[[ $UID == 0 ]] || { echo "Must be root to go gentoo."; exit 0; }
 
cp /etc/resolv.conf etc/
mount -t proc proc proc/
mount -o bind /dev dev/
chroot . /bin/bash

然后执行 sudo ./gogentoo 就进入gentoo环境了。进去以后执行:

env-update
source /etc/profile
 
#添加 ~x86 的keywords,请按需修改成你自己的。
nano /etc/make.conf
#更新系统
emerge --sync
emerge -avuDN world
#完成以后,一般还需要gcc-config到最新的gcc版本。然后清理系统
emerge --depclean -av
#最后安装distcc
emerge distcc

到了这里,服务端的软件环境就算准备完毕了,你可以对比下两边的

gcc --version

的输出,看看是否完全一致。
不过,如果你在chroot环境下,直接执行 /etc/init.d/distccd start 来启动服务的话,多半是会遇到错误的,会提示什么udev有问题,我也没深究。不过既然不让启动服务的话,我手工启动总好了吧,于是执行:

distccd --port 3632 --log-file /var/log/distccd --log-level critical --allow client的IP -N 15

这样启动的distccd也照样能工作,哈哈。
以上步骤在 i686-pc-linux-gnu 的gentoo client 和 ubuntu 9.10 的server上试验通过。理论上这样做好的gentoo,应该是可以从ubuntu打包出来,到其他发行版直接用的,这样就很方便做出一个灰常强大的编译集群了,哈哈,改天试试看。

接下来就是配置你的client来使用这个server了,这个就和普通的没区别了,这里也先不讨论了,如有必要,另外再写一篇就好,呵呵。

怀念一下

怀念一下这个我许久不用的系统——ubuntu 7.04
是这样的,现在我再用的是我之前的电脑,早在07年初就已经给我小妹使用了,当时只是空出一个分区,装上一个XP而已,ubuntu一直都没删掉,所以,这个ubuntu就一直这么静静地呆在这个硬盘里了,呵呵。
直到今天,回家过年的我才猛然想起它,打开一看,它还是这么健壮,虽然早已经过了支持期了,找不到源更新了,但是它还是能很好地工作。
firefox还是2.0.0.6,打开WP的后台都已经比较乱了,就像手机浏览器一样,呵呵。
virtualbox也还是1.3.8的,还属于InnoTek,不属于SUN或者Oracle。
一切的设置都还比较熟悉,不知道这个系统能坚持到什么时候~

perl升级引起的gentoo编译错误

最近,gentoo portage里的perl从 5.8.8 版本升到了 5.10.1 ,导致在编译一些其他包的时候,出现一些莫名的错误,而且这些错误都和perl有关。
例如,在 emerge gnome-extra/gnome-screensaver-2.28.3 的时候,就会出现:

checking for XML::Parser… configure: error: XML::Parser perl module is required for intltool

这样的错误。
解决办法是emerge一个 perl-cleaner,然后执行:

sudo perl-cleaner --all

把perl相关的模块和文件都检查并修正一遍,然后再编译其他包,就不会出错了。

a2p──将awk程序转成perl

呵呵,不管你觉得有没有必要,反正,就是有这样的工具了,而且还是perl包自带的哦(看来perl确实有点怪异,哈哈)。
别的不说了,拿个小程序演示下,下面的awk程序是用来统计当前登录系统的人数的,其实就是 who | wc -l

BEGIN { 
while ( "who" | getline ) n++ 
print n 
}

然后这样:

lily@LLY:~/test/awk$ awk -f count.awk
3
lily@LLY:~/test/awk$ a2p count.awk > count.pl 
lily@LLY:~/test/awk$ perl count.pl
3

哈哈,确实能执行哦,再让我们来看看转出来的perl程序,格式都还蛮工整的呢:

#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if $running_under_some_shell;
			# this emulates #! processing on NIH machines.
			# (remove #! line above if indigestible)
 
eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
			# process any FOO=bar switches
 
open(WHO_FH, 'who|') || die 'Cannot pipe from "who".';
 
$, = ' ';		# set output field separator
$\ = "\n";		# set output record separator
 
while (($_ = &Getline2('WHO_FH', '|'),$getline_ok)) {
    $n++;
}
print $n;
 
sub Getline2 {
    ($fh) = @_;
    if ($getline_ok = (($_ = <$fh>) ne '')) {
	;
    }
    $_;
}

想学perl的同学可以折腾折腾。

exif──查看JPEG文件里的附加信息

不知道什么是EXIF的可以看这里(中文)和这里(英文),简单一句话,EXIF就是存在JPG文件里的一些额外信息。
现在的数码相机拍出来的图片里,绝大多数都存有拍摄时间、快门、焦距、光圈等很多信息,稍微好点的还有GPS定位的拍摄地点呢。
在GUI下,eog等图片查看软件,都可以通过右键的“属性”菜单查看具体的EXIF信息。其实在CLI下,也是有办法提起这些信息的。这个程序的名字就叫 exif 。
安装基本靠源,就不介绍了,使用也是超简单:

$ exif S7302998.JPG
‘S7302998.JPG’中的EXIF 信息标识(‘英特尔’字节顺序):
--------------------+----------------------------------------------------------
信息标识                |值
--------------------+----------------------------------------------------------
Image Description   |<Samsung D70 / D75 / S730 / S750>
Manufacturer        |Samsung Techwin
Model               |<Samsung D70 / D75 / S730 / S750>
Orientation         |左上
x-Resolution        |96.00
y-Resolution        |96.00
Resolution Unit     |英寸
Software            |708101
Date and Time       |2009:02:08 14:16:22
###限于篇幅,省略点输出信息。。
对比度                 |普通
饱和度                 |普通
锐度                  |普通
Interoperability Ind|R98
Interoperability Ver|0100
--------------------+----------------------------------------------------------
EXIF 数据中含有缩略图(3915 个字节)。

下一步就是找个写EXIF信息功能强一点的CLI软件,exif虽然也能写,但是好像只能逐字段挨个写,这个就不太方便了。
最终我要实现的就是:压缩照片,但是保留EXIF信息,哈哈。

========20100211 19:30:00 update========
哈哈,是我把convert想得太简单了,其实convert本身就会保留EXIF的,根本无须我多操心~

去掉wget烦人的 “eta(英国中部时间)” 提示

gentoo 里的 wget ,从1.12版本开始,就一直有个不影响功能的小毛病:由于中文翻译的失误,进度提示的时候,会被拉成很多行。原因就是原来英文的ETA这3个字母,被翻译成了 “eta(英国中部时间)” 这么长,所以引起断行出错。
zh_CN.po 里,其实还是有说明的,只不过翻译人员疏忽了。如下:

#. TRANSLATORS: "ETA" is English-centric, but this must
#. be short, ideally 3 chars.  Abbreviate if necessary.
#: src/progress.c:805
#, c-format
msgid "  eta %s"
msgstr " eta(英国中部时间) %s"

既然这个小毛病不影响功能,之前也就没太在意,一直在等上游更新,不过到了 1.12-r1 版本,仍旧还有这个毛病,我也渐渐的看不下去了,就决定动手自己改掉它了。
方法也很简单,用之前我介绍过的命令就可以了,具体如下:

msgunfmt /usr/share/locale/zh_CN/LC_MESSAGES/wget.mo -o - | sed 's/eta(英国中部时间)/ETA/' | msgfmt - -o /tmp/zh_CN.mo
sudo cp /tmp/zh_CN.mo /usr/share/locale/zh_CN/LC_MESSAGES/wget.mo

搞定。