2012年9月16日星期日

User Mode Linux 高效半虚拟化

今天看到一个软件 coLinux,可以在 Windows 上面半虚拟化跑 Linux,效率据说比真机 Linux 还快。
急忙寻求 Linux 下面的类似解决方案,找到了 User Mode Linux,简称 UML。
官方网站在此: http://uml.devloop.org.uk/
下载一个内核,然后解压,当作普通程序一样执行它:
wget -c http://uml.devloop.org.uk/kernels/kernel********.bz2
bunzip2 kernel********.bz2
chmod +x kernel********
./kernel******** ubda=root_fs
别急,先弄一个 root_fs 再说,可以在网站上面下载然后解压,也可以自己弄。既然没有 ArchLinux,我就决定自己弄。
touch arch.img
truncate -s 8G arch.img
mkfs -t ext4 -F arch.img
mkdir arch
sudo mount -o loop arch.img arch
sudo mkdir -p arch/var/lib/pacman
sudo pacman -Sy -r arch base net-tools # 其实 linuxmkinitcpio 之类的软件包可以不选。
sudo vim arch/etc/fstab # 编辑 fstab
sudo vim arch/etc/rc.conf # 编辑 rc.conf
rc.conf 的网络配置里面写:
interface=eth0
address=10.1.0.2
netmask=255.255.0.0
gateway=10.1.0.1
然后卸载卷。
sudo umount arch
rmdir arch
配置网络(这一节需要 root 权限,如果你没有办法获得 root 权限,可以考虑用 slirp 方式而不是现在的 tuntap 方式配置网络,前面的 rc.conf 也要配合修改,这里就不介绍了):
tunctl -u "$(id -un)" -g "$(id -gn)" -t tap1 # tunctluml_utilities 包里面。
ifconfig tap1 10.1.0.1
echo 1 >/proc/sys/net/ipv4/ip_forward # 1> 之间的空格不要忘记咯
iptables -t nat -A POSTROUTING -j MASQUERADE
最后,启动!秀一下我自己的配置:
./kernel64-3.5.4 ubda=arch.img mem=1G con=pty con1=fd:0,fd:1 root=/dev/ubda eth0=tuntap,tap0

P.S.: 貌似 UML 的 /dev/random 有点问题,读取的时候会卡住,导致 pacman-key 不能跑,临时用这个方法代替吧。
ls -l /dev/urandom 确认看到的是这样的:
crw-r--r-- 1 root root 1, 9 /dev/urandom
确认 root 右边那两个数字是 1, 9
然后用 /dev/urandom 来覆盖掉 /dev/random
mknod /dev/random c 1 9

最后我要说的事是:它的速度真的很快,我 2.4G 主频的 CPU,开机只需要 8 秒左右,确实比真机都快了。(但是据说有的 OpenVZ 能够 2 秒开机……)

2012年9月9日星期日

打印自身的 CGI 脚本

有的时候在网络上面分享一个文本,是 UTF-8 编码,可惜浏览器默认用 ISO-8859-1 或者 GBK 来解码,这个时候可以把以下两行放在文本最前面,赋予文本可执行权限,并允许服务器执行 CGI:
#!/bin/bash
if [ "$HTTP_IF_MODIFIED_SINCE" ];then if [ "$(date -u -d "$HTTP_IF_MODIFIED_SINCE" +%s)" -ge "$(stat -c %Y "$0")" ];then echo 'Status: 304 Not Modified';echo;exit 0;fi;fi;echo 'Status: 200 OK';echo 'Content-Type: text/plain; charset=utf-8';echo "Last-Modified: $(date -R -u -d @$(stat -c %Y "$0"))";echo "Content-Length: $(tail -n +3 "$0"|wc -c)";echo;exec tail -n +3 "$0"

2012年8月23日星期四

折腾 xmpptalk

Xmpptalk 是百合仙子的一个 XMPP(比如 GTalk)多人聊天机器人。只要加该机器人为好友,就可以和其他加该机器人为好友的人聊天。机器人负责转发消息。

首先,强调这篇文章发表是 2012 年 8 月。在此之后可能会更新,所以当你看到这文章的时候,原来的程序可能已经更新不再使用这种方法了,所以请自己考虑清楚每一步。
一个 VPS 是必不可少的,怎么购买 VPS 不是本文谈论的范畴。
  1. 下载 xmpptalk 的源代码。
    git clone https://github.com/lilydjwg/xmpptalk
  2. 不要先运行 scripts/quickinstall.sh!它会毁了你的系统的!
    使用发行版自带的软件包工具安装下列软件:
    • python3.2
    • python3.2-dev
    • python2.7
    • python2.7-dev
    • mongodb (安装之后请启动服务,ArchLinux 用户貌似要手动创建 /data/db 目录)
    • mercurial (有的发行版里面叫做 hg)
    • prosody (如果你不打算使用公共的 XMPP 服务,而自己开一个 XMPP 服务器)
    • mongokit (很多发行版里面是没有这个包的,而且由于没有更新,不支持 python3,所以需要用 2to3 转换,后面介绍这个包的详细安装)
  3. 安装 mongokit。这一段的版本号全部自己变通,因为你看到文章的时候原程序可能已经更新了。
    wget http://pypi.python.org/packages/source/m/mongokit/mongokit-0.8.tar.gz
    tar xvzf mongokit-0.8.tar.gz
    cd mongokit-0.8
    原程序在安装的时候会自动下载 setuptools,但由于需要的版本 0.6c7-py2.7 已经无法下载,目前的版本是 0.6c11-py2.7,所以我们需要手工下载目前版本,并且修改名字为需要的版本。
    wget -O setuptools-0.6c7-py2.7.egg http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg
    sudo python2 setup.py install
    下一步是把 python2 的模块转换为 python3。
    sudo cp -a /usr/local/lib/python2.7/dist-packages/mongokit-0.8-py2.7.egg/mongokit /usr/local/lib/python3.2/dist-packages/
    sudo 2to3 -w /usr/local/lib/python3.2/dist-packages/mongokit
    安装好了再去运行 scripts/quickinstall.sh,用 root 权限。
  4. 配置 config.py,此文件是 Python 语法,请按注释进行配置。
    一定要修改的地方有 jidrootsaltdatabase(数据库名字不要 . 等特殊符号)、settings.password
    如果要配置 Prosody,机器人的 XMPP 地址要写成自己的 VPS 的域名,等一会配置 Prosody 的时候创建你要的机器人账户。
  5. 配置 Prosody
    Prosody 的配置有一点烦人,你还需要在本地电脑上准备好 Pidgin 一类的 xmpp 聊天软件。
    Prosody 的全局配置文件在 /etc/prosody/prosody.cfg.lua
    打开后找到
    allow_registration = false;
    false 修改成 true,在完成新用户注册之后再修改回来。
    下面代码中斜体的 example.com 表示要修改成自己站点的名字。
    sudo cp /etc/prosody/conf.avail/example.com.cfg.lua /etc/prosody/conf.d/example.com.cfg.lua
    打开 /etc/prosody/conf.d/example.com.cfg.lua,删除下面这行:
    enabled = false -- Remove this line to enable this host
    然后修改所有的 example.com 为自己站点的名字。
    然后用 root 执行:
    cd /etc/prosody/certs
    openssl req -new -x509 -nodes -days 99999 -out "example.com.crt" -keyout "example.com.key"
    然后一路回车或者填写一些信息。
    最后重启 Prosody 服务,比较通用的命令是:
    sudo /etc/init.d/prosody restart
    当然如果你的发行版提供开关服务的命令,使用它,比如 ArchLinux(SysVInit)的命令是 sudo rc.d restart prosody
  6. 创建 XMPP 账户
    用你的 XMPP 客户端(比如 Pidgin)创建一个新账号,服务器填写你的 VPS 的地址,勾选“在服务器上创建此新账号”。
  7. 启动 xmpptalk
    在 xmpptalk 的目录里面,第一次需要初始化数据库,输入:
    python3 dbman.py
    然后启动机器人:
    python3 main.py
至此结束。你还可以配置机器人来达到更多的功能,另外建议开启 Prosody 的加密功能,具体配置可以在 /etc/prosody/prosody.cfg.lua 中找到。

Tips: 如果发现重新启动服务器之后 mongodb 迟迟不肯工作,试试看删除 /var/lib/mongodb/mongod.lock,然后重新启动 mongodb 服务即可。

Update 2012-08-31: 今天发布了我自己的 chatlist。依赖项只有一个 SleekXMPP
安装 SleekXMPP 的命令放在下面:

git clone https://github.com/fritzy/SleekXMPP.git
cd SleekXMPP
sudo python3 setup.py install
请记住全程用 Python 3(如果你机器默认的 Python 是 Python 2 的话)。

2012年8月16日星期四

Linuxer 的 Windows 入门指南

本文章的灵感来自 Linuxer 的 Windows 生存指南,旨在带领 Linux 用户通过本指南得到 Windows 的入门。

现在 Linux 世界正在发生一些动荡。你可能正打算避避风头,暂时迁移到 Windows。而由于你没有操作 Windows 的经验(或者忘记了),会遇到很多麻烦。本指南希望能够让你顺利迁移到 Windows。

磁盘

每一个磁盘卷在 Windows 中一般情况下有一个盘符,用一个字母表示,比如 /dev/sda1 在 Windows 中称作 C:C: 也是 Windows 的系统盘。
以后的分区一般安顺序分排为 D:E: 一直到 Z:。但是往往 Z:Y: 等是用来挂载网络驱动器的。
Windows 中的软驱,/dev/fd0 称为 A:/dev/fd1 称为 B:。光驱没有特殊的称呼,也只占用一个普通的盘符。

基本桌面操作

如果你曾经是 LXDE 用户,那么基本桌面操作部分可以跳过。如果你曾经是 KDE 用户,那么这部分可以大略阅读一下。
当你登录进入 Windows 时,你面对的应该是 Windows 桌面。如果你面对的是一个 Metro 风格的“开始”屏幕,你需要点击“桌面”磁贴来进入传统 Windows 桌面。
屏幕最左下角是“开始”按钮,你可能会看到一个 Windows 标志,点击它,你的 Windows 旅程将会从单击这里开始
点击“开始”按钮之后,将显示“开始”屏幕或者“开始”菜单。你可以在其中浏览你安装的应用程序。
紧临着“开始”按钮的一整个工具条,叫做任务栏。任务栏当中显示了你当前正在运行的应用程序。
任务栏的最右端叫做托盘区域。读取系统时间也是在那里。
桌面上默认有一个“回收站”图标。你可以定制桌面来符合自己的喜好,比如很多人喜欢把“计算机”、个人文档、浏览器图标放在桌面上。
打开这样一个图标使用双击,打开“计算机”将会带出来一个文件管理器,名字叫做“资源管理器”,他的功能相当于 Nautilus、Dolphin、Thunar、Pcmanfm。你可以看到电脑当中的所有盘符,并且打开它们浏览。

各种路径

下面列出 Windows 的各种常用路径和 Linux 中等效的路径。

Windows 路径Linux 等效注释
C:\/你的系统盘
C:\WINDOWS\system32/bin/lib各种命令和 DLL 的所在地
C:\Program Files/usr/lib/usr/share各种应用程序的安装地
C:\Users/home个人文档的存放地,但由于不能单独分区,一般都不把文档存在这里
C:\Users\用户名\Local Settings\Temp/tmp临时文件放在这里,但是不像 Linux 那样存在内存里,关机时也不会自动清理
看到这里,你应该发现了,Windows 的路径分割用的是 \ 而不是 /,而且文件名不区分大小写。

各种命令

你可能离不开各种命令,Windows 也有命令解释器,它的名字叫做“命令提示符”。
要打开“命令提示符”,请在“开始”菜单中打开“所有程序”,依次打开“附件”、“命令提示符”,你也可以用路径 C:\WINDOWS\system32\cmd.exe 来启动它。
接下来你能够看到一个 80x25 的黑色窗口,它的名字叫做控制台(console)。
现在在控制台里面试试看这些命令吧。
Windows 命令行Linux 等效命令注释
cdcd切换当前目录
cd(不带参数)pwd查看当前目录
D:切换当前盘符
copycp复制文件
movemv移动文件
ren重命名文件
delrm删除文件(可以使用通配符,但展开通配符的不是命令提示符,而是 del 程序自身)
mdmkdir创建目录
rdrmdir删除空目录
rd /s /qrm -Rf清空并删除目录
pingping测试网络连通
tracerttraceroute追踪路由
nslookupnslookupDNS 查询与诊断
shutdownshutdown关机、重启
你应该也看到了,命令行参数是用 / 开头的,而不是 -,短选项不可以合并,长选项也是简单的一个 / 开头。获取帮助可以用 /help 选项。(然而 pingtracertnslookupshutdown 等命令仍然是 Unix 风格,因为 Windows 的网络功能差不多就是从 BSD 抄过来的)

安装软件

Windows 不提供软件包管理,所以软件需要自己安装。
请到官方网站下在安装包或者到信任的软件下载站下载。
安装包可以是 .exe 格式的可执行文件,也可以是 .msi 格式文件。双击打开就可以安装。
安装过程当中需要确认很恶心的最终用户许可协议,还需要一直点击“下一步”。
安装的目的地建议设置到 D: 盘,这样可以避免把 C: 盘占满。

选择软件

选择软件建议(摘录自 Linuxer 的 Windows 生存指南):
  • 选择跨平台软件
    跨平台软件可以让你在 Linux 和 Windows 中找到熟悉的软件,很快适应全新的工作环境。
  • 选择自由软件
    在长期的 Linux 世界生活,继续使用自由软件来管理很多事务,能够让自己在 Windows 世界依然体会到自由软件的乐趣。你仍然可以向开发者提交 bug 报告,或者协助写补丁等等。
  • 不要惧怕商业软件
    使用 Windows 就不要惧怕商业软件,Donʼt panic。商业软件也有很多优秀的。
  • 慎用中国产软件
    理由不用我说了吧。除非你用沙盒来运行程序。

安全

在 Windows 世界,你需要一个安全软件,不能再像在 Linux 那边那样裸奔了。
安全软件比如杀毒软件、防火墙软件都是必须的。
不要使用号称免费的安全软件,天下没有免费的午餐。

我的软件选择

浏览器:Google Chrome
文书处理:LibreOffice / Microsoft Office
开发:gVim
及时通讯:Pidgin
SSH 连接:Putty / Bitvise Tunnelier
模拟 Unix 环境:Cygwin / MSYS
虚拟机:Oracle VirtualBox / vmware Workstation
网络隧道:OpenVPN / Putty / MyEnTunnel

Unix 环境

在 Windows 下模拟 Unix 环境并非难事。一个小小的 Cygwin 就能解决问题。但是由于 Windows 进程创建的开销极大,所以一个 ./configure 下来,电脑基本吃不消了。
替代的方案有,连接到远程 SSH,或者使用虚拟机。我个人偏向后者。

提示

不要以为 Windows 的自动保存功能能够帮助你!Windows 程序一般不会自动保存你的文档,即使自动保存了,那个功能也是废物!
养成手动 Ctrl-S 的习惯,不要等到找不到备份的时候再悲愤!

2012年7月9日星期一

豆瓣FM中的彩蛋

打开豆瓣电台,在最右下角能看到“豆瓣实验室
打开后你会在页面左侧看到这个水滴图片(点击查看大图):
熟悉Linux的人都知道这个是一段代码,我把这代码抄了下来(原图第6行中有一个“-c”是错的,应该是“-e”,可能是因为字体太小,不清楚的缘故)
while [ $? -eq 0 ]; do nc -vlp 8888 -e '(r=read; e=echo; $r a b c; z=$r; while [ ${#z} -gt 2 ]; do $r z; done; f=`$e $b|sed "s/[^a-z0-9_.-]//gi"`; h="HTTP/1.1"; o="$h 200 OK"; c="Content"; hd="$c-Type: text/html; charset=utf-8"; if [ -z $f ]; then ($e "$o"; $e $hd; $e; ls | (while $r n; do if [ -f "$n" ]; then $e "<a href=\"/$n\">`ls -gh $n`</a><br>"; fi; done);); elif [[ $f=~eggs ]]; then ($e "$o"; $e $hd; $e; curl http://labs.douban.com/doublo/eggs?k=`$e $f | sed "s/eggs//gi"` 2>/dev/null;); elif [ -f $f ]; then $e "$o"; $e "$c-Type: `file -ib $f`"; $e "$c-Length: `stat -c%s $f`"; $e; cat $f; else $e -e "$h 404 Not Found\n\n404\n"; fi)'; done

这很明显是一个Bash脚本,运行。
这时候用浏览器打开http://localhost:8888
你会看到当前目录的文件列表。
随便点开一个文件,结果是:We need a number after eggs!
那么我们试试看http://localhost:8888/1,返回结果:Next fibonacci!
那肯定下面就是http://localhost:8888/2了,返回还是:Next fibonacci!
按顺序尝试斐波那契数列:1 2 3 5 8 13 21

一直到21的时候,页面显示:
哦!恭喜你中蛋啦!

总结:现在的彩蛋已经不是那么傻瓜化了,已经很有技术含量了。

2012年6月28日星期四

在虚拟磁盘映像上安装 ArchLinux

如果你是一个疯狂的 OS 爱好者,你可能硬盘里面安装了十几个 Linux 发行版,一定要分十几个区么?下面介绍如何在虚拟磁盘镜像上安装 ArchLinux。
在开始之前,强烈建议先阅读官方的安装指南
首先,用 ArchLinux 的安装光盘开机(不管你是用光盘还是U盘,或者是 GRUB 链式引导,只要开了就行)。如果你用的是2012年6月4日以后的安装光盘,需要先初始化软件包验证密钥,执行下列命令即可:
pacman-key --init
pacman-key --populate archlinux #一路敲 y,如果卡住不动,你可以晃晃鼠标消磨时间(顺便给 gpg 提供随机种子)

然后就可以开始了。
  1. 创建镜像
    先挂载上 host 镜像的盘(用 Windows 的估计都会选 NTFS 的),这里我们举例将第一磁盘第五分区作为 host 盘,采用 NTFS-3G 来负责挂载,其他格式的将 ntfs-3g 换成 mount 即可。
    mkdir /host
    ntfs-3g /dev/sda5 /host
    然后创建镜像,这里用 ext4 格式,大小为 8G,放在 diskimg 目录下,自己根据需要修改。
    truncate -s 8G /host/diskimg/archlinux.img
    mkfs -t ext4 -F /host/diskimg/archlinux.img
    modprobe loop #如果你没有用官方的安装盘,需要这行
    mount -o loop /host/diskimg/archlinux.img /mnt
  2. 准备 pacman
    mkdir -p /mnt/var/lib/pacman
    编辑 /etc/pacman.d/mirrorlist,选择自己喜欢的镜像,把它复制下来放在第一行。
    nano /etc/pacman.d/mirrorlist #当然如果你擅长 Vi,也可以用 vi
    然后同步数据库(别忘了配置网络)
    pacman -Sy
    pacman -Sy -r /mnt #顺便也把新系统的数据库同步了
  3. 安装基础系统
    pacman -Sr /mnt base ntfs-3g net-tools wireless_tools #你可能还想安装一下别的,比如说网络组件
    然后有一点耐心,一共80多兆,下载完后自动安装。其中安装 linux 包的时候会出现问题,等一会我们再弄。
  4. 配置系统
    nano /mnt/etc/rc.conf
    nano /mnt/etc/mkinitcpio.conf
    怎么配置不用我说了吧,指南上面有。
  5. 配置引导参数和引导钩子
    先将 /boot 拷出来
    mv /mnt/boot /host/diskimg/archboot
    ln -s /host/diskimg/archboot /mnt/boot
    然后是关键的一步
    依次创建这些文件(斜体字部分是根据自己的情况修改的):

    /mnt/usr/lib/initcpio/hooks/looproot
    # vim:set ft=sh:
    run_hook ()
    {
            # Now mount the host filesystem
            mkdir /host
            # mount -t ntfs /dev/sda5 /host
            ntfs-3g /dev/sda5 /host
    
            # And the loop filesystem
            losetup /dev/loop0 /host/diskimg/archlinux.img
            mount -t ext4 /host/diskimg/archlinux.img /new_root
            mount --bind /host /new_root/host
    }
    
    /mnt/usr/lib/initcpio/install/looproot
    #!/bin/bash
    
    build() {
        SCRIPT="looproot"
    }
    
    help() {
        cat <<HELPEOF
    HELPEOF
    }
    
    # vim: set ft=sh ts=4 sw=4 et:
    
    /mnt/etc/rc.d/functions.d/omitntfs
    #!/bin/sh
    
    omitntfs() {
        sync
        add_omit_pids $(fuser /dev/sda5 2>/dev/null | awk '-F ' '{ print $1 }')
    }
    
    # remove fuseblk from the original NETFS variable
    NETFS="nfs,nfs4,smbfs,cifs,codafs,ncpfs,shfs,fuse,glusterfs,davfs,fuse.glusterfs"
    
    add_hook shutdown_prekillall omitntfs
    add_hook single_prekillall omitntfs
    
    修改 /mnt/etc/mkinitcpio.conf
    MODULES 里面加上 loop fuse
    BINARIES 里面加上 /usr/bin/ntfs-3g(如果你不用 NTFS,并且挂载时需要辅助程序的,加进来)
    HOOKS 最后加上 looproot
    修改 /mnt/etc/fstab
    # 
    # /etc/fstab: static file system information
    #
    # <file system> <dir>   <type>  <options>       <dump>  <pass>
    /dev/loop0      /       ext4    loop            0       1
    /dev/sda5       /host   ntfs    defaults        0       0
    
    创建目录 /mnt/host
  6. Chroot 进新系统
    for i in dev proc sys host; do mount --bind /$i /mnt/$i; done
    modprobe dm-mod #如果你要安装 GRUB 的话需要这行
    chroot /mnt
    passwd #先给 root 设置个密码
  7. 创建启动内存盘
    mkinitcpio -p linux
  8. 安装引导器(谨慎!一定要按照自己的情况来更改参数以免发生意外!
    mkdir /host/boot
    grub-install --target i386-pc --boot-directory /host/boot /dev/sda
    ln -s /host/boot/grub /boot/grub
    grub-mkconfig -o /host/boot/grub/grub.cfg
    最后还有一点要声明的是,要在内核启动选项后面加上 root=/dev/loop0似乎不加也行,但我不敢保证,如果有人成功了就留言通知我一声。
  9. 重新启动
    exit
    umount /mnt/dev /mnt/proc /mnt/sys /mnt/host /mnt /host
    reboot
  10. 继续定制系统
    现在开机,启动过程中会提示错误,然后掉进紧急 shell 当中,不要慌,因为我们 hook 了开机流程,导致自带的脚本执行出错。直接敲 exit 或者按快捷键 ^D 就行了。以后每一次开机都会提示错误,网络上能找到避免的方法,但是我不建议,因为每一次 mkinitcpio 升级之后都会还原。
    这时候你已经登入了新的系统,用 root 登录,密码你前面已经设置过了。

    登录进去之后干什么?这你还用问?

2012年6月22日星期五

10 个痛恨 Linux 的理由

  1. 首当其冲的还是内核问题。
    还记得当年 Linus Torvalds 和 Minix 的作者的那次争论么?或许是为了图省事,Linux 被做成了宏内核。导致了内核过于臃肿。即使是性能提升了,也导致了很多问题。
    1. 内核模块是和内核绑定的。这导致了很恶心的现象,每一次发布内核都需要发布内核模块,而每一次编译内核都要花掉 2/3 的时间在上面。
      你会说,我用发行版提供的内核包,不用自己编译。那问题是,截止 3.4.3 版本,Linux 内核(包括内核模块的二进制包)的大小已经达到了 56.75MiB,至少给网速慢的用户带来了升级上的负担。
      如果,你另外安装了什么驱动(比如 Nvidia 的闭源驱动),每一次更新内核都需要重新编译。你会忘记吗?你应该有过这样的经历。
    2. 内核过于臃肿带来了第二个问题。如果一个驱动崩掉了,整个系统估计也就 Kernel Panic 了。幸好现在的 Linux 提供了一些保护机制,让你至少还可能接着用一段时间,保存手头的工作。
      而我遇到的问题更麻烦,那是在 BtrFS 不太稳定的一段时间里。每当 BtrFS 崩溃,系统就会自动跳回 console,然后提示 btrfs-**** 进程崩溃,给出 backtrace。这时候内核还是在运行的状态,用 Magic SysRq 还能完美重启。而有一次直接 Kernel Panic 了,在 Xorg 下连提示都没有给我,就直接死了,Magic SysRq 都不能用。
  2. 系统调用的命名问题,这是一个历史问题。
    你可以觉得当年 Unix 的 creat() 函数名字很恶心,因为Unix 的创始人认为当年用的电脑键盘使用起来非常费劲,所以宁可省去一个字母(天哪,省别的字母多好,省去这一个字母有什么用?)。但是 POSIX 为什么不说“creat() is deprecated, use create() instead”呢,至少这不会造成小学生的英语水平下降呀。
    如果这个你还能接受的话,那就见识一下 dup() dup2() dup3() 三兄弟吧。你知道它们是干什么的呢,参数怎么用呢?什么?你说还有 man 手册来查?我告诉你,Windows 里面的 MSDN 手册比 Linux 里面的 man 好用多了,而且支持现代化的超链接。
    以前看到一个 Windows 的批评者说 Windows 里面的 CreateWindowEx() 函数参数太多,难以记忆。那我只好用两个观点来反驳了——Linux 里面的 dup*() 家族就不麻烦了?并且哪个人在写 Windows 软件的时候不用 MSDN 做参考(或者参数补全功能)?
    因此,我还是偏好于 Windows 的 API 命名风格(Windows 值得欣赏的估计也只有 API 了),那么 creat() dup() dup2() dup3() 就会叫做 CreateFile() DuplicateHandle() DuplicateHandleTo() DuplicateHandleToEx() 了(而事实上 Windows 本身的 CreateFile() 和 DuplicateHandle() 都实现了 creat() dup3() 的功能,将一些参数填成零也就实现了 dup() 和 dup2() 的功能)
    (引用 @红繁君 的一句话:谁能记住 mktemp mkstemp mkstemps tmpnam tempnam tmpfile 的区别,请举手。)
  3. Linux 前端缺乏创新意识,这也是 Linux 始终无法打入桌面领域的原因。
    这些年 Linux 在桌面市场也在不断发展,但是永远无法撼动 Windows 霸主的地位。不是说 Windows 完美无暇,而是说 Linux 永远跟着别人的脚步在走。
    比如 Gnome 推出了 Gnome-shell,结果遭来了一大堆骂声。批评者说,“难道 Linux 的桌面版以后都要向手机界面迈进?”我只想反问,Linux 社区的激进的极客精神哪里去了?毕竟我也比较喜欢 Gnome-shell,除了一些很小的问题之外还是非常优秀的桌面环境(我也不否认 KDE 和 LXDE 等)。
  4. Linux 的 Kernel Panic 处理很恶心。
    如果你正在图形环境下工作,这是不幸地发生了 Kernel Panic,会有什么现象呢?
    根据内核版本和 X Server 版本的不同,可能你会被拖回 console,然后面对黑底白字和满眼的 backtrace,弄得你手足无措。而也有的就直接死掉了,连提示都没有!(除非你当时在 Virtual Terminal 下,还能看到 backtrace)
    如果是 OS X 或者是 Windows 发生了内核崩溃,不仅会提示你发生了错误,还会把 memory dump 存在硬盘里,这比简简单单地把 backtrace 打在屏幕上要好得多吧。况且如果 backtrace 超过了 24 行,那 backtrace 有什么用!
    据说 Windows 8 开始要改善系统蓝屏的用户体验,不仅是蓝屏的背景颜色有所改变,而且提示文字支持了中文。Linux 什么时候能做到呢?
  5. Linux 对用户不完全友好,对开发者友好。
    虽然人们曾经的“Linux 不用户友好”的概念已经被有些发行版推翻(比如大名鼎鼎的 Ubuntu),但是做的还不够。(不过也难说 Windows 能友好到什么程度,OS X 那才是真正地注重“用户体验”)
    用户体验不是华丽的特效,也不是提供厚厚的操作手册;而是用户永远能在他认为该出现的地方找到他要的功能
    Ubuntu 虽然提供了软件中心(就这还是照苹果抄来的),但是没有提供自动清理软件包缓存的功能,导致缓存吃硬盘空间。当然,Windows 也有不清理 Temp 文件夹的坏习惯,但这不是 Ubuntu 不清理缓存的借口。而相反,ArchLinux 不清理缓存则是注重用户体验。(如果你用过 ArchLinux,你就知道这话的道理了)
    而至于对开发者伪友好,举一个例子就可以说明了。Linux 虽然提供了大量的开发工具,但是从来没有一个得心应手的 IDE,如果说 Linux 的开发者不喜欢 IDE 的话,那么考虑对于一个新手来说 IDE 是不是很重要。一个刚刚从别的平台迁过来的开发者,如果没有 IDE,会很不适应,然后被轻易吓跑。
  6. 图形工具包的不统一。
    这可以追溯到当年 GTK+ 和 QT 闹对抗的时代。然而有的人却找借口说,X 当年的设计就是这样的,“提供机制,而不是策略”,所以让别人自己设计图形工具包。这个说法并没有错,但造成了很多不便。开发者纠结该用什么库,是 GTK+ 还是 QT,还是 TK、FLTK、wxWidget,还是干脆只用 X。而对于用户 ,不仅需要安装一大堆的库,而且要忍受不同库之间的界面样式、主题不同之苦。开发者如果想调用用户的文件浏览器来显示某个目录的内容,就要枚举 Nautilus、Dolphin、PCMan……虽然 freedesktop 缓解了一些问题,但是没有真正解决。
    同样的问题也发生在 ALSA 和 OSS 之间,但我认为这是好事,因为促成了竞争(前提是 ALSA-OSS 兼容包的存在)。
  7. 进程通信的支持问题。
    曾经有一个人说,Linux 里面有万能的管道,Linux 所有的进程通信只需要管道就够了。
    现在,dbus 的出现说明了这种论断是错误的。首先,管道只有单向性,只能去不能回。并且,管道只能传输文本流,对于别的类型,转换的时候既会丢失精度,也降低了效率。当然我不是完全否定管道的,因为即使管道的一端换成了同样功能的软件也能照样运行。(用 less 来替换 more 就是一个很好的例子)
  8. 人们明知道内核过于臃肿不是好事,却仍在变本加厉。
    KMS 是最好的例子。上次听说某显卡驱动为了增强性能以及与内核的集成性,由 UMS 改为了 KMS。与其将更多的东西往内核里塞,不如从内核里拿出东西出来。
    本身内核就应该提供一些对于用户态驱动的接口,让驱动除了使用 int $0x80 以及直接在编译时和内核连接之外有别的、更好的选择。
  9. 对未来的考虑欠缺
    你应该知道 /dev/?d* 表示硬盘,比如 /dev/sda1 表示第一块(SATA 接口)硬盘。那么问题是,如果你安装了 27 块硬盘,该怎么编号呢?Red Hat 的解决办法和 Microsoft Excel 对于第 26 列之后的编号一样:sda sdb sdc ... sdz sdaa sdab ... sdaz sdba ...
    那么带来的问题是,如果原来有一个 Bash 脚本,枚举每一个磁盘,可以用
    for i in /dev/sd? ,现在只可以用
    for i in $(ls -1 /dev/sd* | tr -d [:digit:] | sort -u)
    了(如果有人想到了更简洁的方法请告诉我)
    当年 /dev/pts1 改成 /dev/pts/1 就是因为考虑得不够长远(改过之后也带来了不同发行版和类 Unix 系统分支之间的不兼容性),Intel 也犯过这样的错误,MBR 的设计者也是,甚至 IPv4 的制定者,甚至是“千年虫”也是因为这个导致的。Linux 现在为什么不可以汲取这样的教训呢?比如 Hurd 使用 /dev/hd0s1 的表示,用数字,枚举起来很方便,特别是在 Bash 脚本中。
  10. Hurd 才是 GNU 的未来。
    GNU/Hurd 在 Linux 开始之前就已经动工了,现在 Linux 都更新到 3.x 版本了,Hurd 连一个正式版本都没有释出,这也难怪 Hurd 没有成为开源社区的主流。
    但是的确如此,Hurd 才是 GNU 的未来,Mach 微内核的优雅设计,GNU 自身的支持,更好的安全性能,等等……
    但是毕竟 Hurd 还没有正式做出来,所以这只是痛恨 Linux 的理由,而不是不用 Linux 的理由。
总结:无论如何痛恨 Linux 这个操作系统,都是希望让它做得更好。并且鉴于目前在开源社区里没有更好的替代品(难道有大多数人在家里用 BSD 或者是 Minix 作日常使用么),我们也只能继续使用 Linux,并且向开源社区提供力所能及的帮助。

2012年6月8日星期五

从苹果 OS X Lion 安装包中提取字体

你应该听说过 OS X 中的字体很漂亮(因为乔布斯当年就是学过书法的,后来发明了电脑字体),想弄到手,又不知道怎么办。下面这个教程教你如何提取安装包中的字体,包括大名鼎鼎的黑体-简和 Hiragino Sans GB(又叫冬青黑体简体中文)。

在失败了 n 次之后,我——一个 Linux 老手和 Mac 新手,终于成功提取了 OS X Lion 中的字体。

如果有运行的 OS X 系统,直接拷贝 /Library/Fonts/System/Library/Fonts 出来就行了。

下面我说的是你没有一个正常工作的 OS X 系统(你知道在非苹果机中装苹果系统的难度的)。

要求:够用的内存和至少 12G 空闲的硬盘(用来解压文件)、运行的类 Linux 系统(虽然 Windows 系统也可以做,但是会有三个困难,下面详说)、7-Zip 压缩软件、dmg2img 转换软件、足够的动手能力和耐心(因为有 14 层压缩包等着你解开呢)。

首先,你需要一枚 Install Mac OS X Lion.app 安装文件(夹),共 3.8G,可以花 $29.99 从 Mac App Store 下,也可以……此处省略……
打开 Install Mac OS X Lion.app,苹果系统要右键,选择“显示软件包内容”,Linux 和 Windows 直接打开。
找到 Contents/SharedSupport/InstallESD.dmg
是一个 Xar 压缩包,用 7-Zip 解开,里面有 InstallESD.pkg,是一个文件夹,打开,里面又有一个 InstallESD.dmg,这是一个 dmg 映像。
dmg2img 转换成 img 格式,用 7-Zip 提取第5分区,是 hfs+ 磁盘映像。
然后打开终端执行 mkdir /tmp/work; sudo mount -t hfsplus -o loop,ro /tmp/work 'disk image.hfs' (文件名根据自己解压选的文件名改);Windows 自己想办法打开 hfs+ 映像,好像有 HFSExplorer 软件,7-Zip 也可以直接解。
输入管理员密码,打开目录 /tmp/work/Packages
用 7-Zip 打开 Essential.pkg,是一个 Xar 压缩包,找到 Payload 文件,提取出来。
Payload 文件是一个 gzip 压缩文件,解开。
解开后是一个 cpio 打包文件,用 7-Zip 找到 ./Library/Fonts./System/Library/Fonts,提取出来!
字体中有一些中文、日文字体(ヒラギノ系列、华文系列、苹果俪黑、俪宋系列)文件名有乱码,自己纠正,因为这个可能在 Windows 下提取不成功,我提醒过你们了。

如果你用 Linux,提取出来的 TrueType 字体安装后就可以直接用了。(怎么安装?在 /usr/share/fonts 下面建一个文件夹,把字体全部拷贝进去,需要管理员权限;非管理员拷贝到 ~/.fonts)其实,还建议你安装 freetype-infinality 或者 fontconfig-ubuntu 补丁,完美模拟苹果字体渲染(前者需要大量配置,如果配置得当可以达到以假乱真的程度,否则根本无法阅读;而后者是傻瓜化零配置)。
但是如果你用 Windows,还需要用 fontforge 来转换一下,否则不识别。我就不讨论了,因为我不用 Windows。而且,介于 Windows 糟糕的字体渲染,再美的字体在 Windows 下也是很恶心的,建议你安装系统美化软件 MacType,改善 Windows 的字体显示。

总结一下目录结构,共 14 层,箭头表示解压或提取:
Install Mac OS X Lion.app/Contents/SharedSupport/InstallESD.dmg>InstallMacOSX.pkg/InstallESD.dmg>InstallESD.img>5.disk_image.hfs>Packages/Essential.pkg>Payload>Payload~>./Library/Fonts./System/Library/Fonts
总结一句,解压的时候如果不知道哪个是你要的文件,找占用磁盘空间最大的那个,一定对!

2012年2月2日星期四

开篇词

墙之内:

为狗进出的洞口紧闭着,

为人翻越的缺口敞开着。

一个声音高喊着:

“翻过来吧!

给你自 由!”


——开篇词 by @m13253


今天开始搬家到 Blogger。原有的尘封 1 年未动的百度空间继续更新,原因是为了方便国内恼残的,使用 IE6 翘着二郎腿的政府审查人员和花不起钱买 VPN 的可怜孩子们看的。

这里会开始记录一些技术和其他杂项类的东西。因为是在谷歌的服务上,相比百度就很自由了吗?

原有的文章会陆续转过来,但是格式之类的就不会再进行调整了,凑合着看吧。