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
总结一句,解压的时候如果不知道哪个是你要的文件,找占用磁盘空间最大的那个,一定对!