从磁盘映像中挂载或提取指定分区

2009/10/11 | 22:48 | 分类:Linux与开源 | 标签: | 375次阅读

  最近在做虚拟机相关的事,需要处理一些磁盘和分区的映像文件。如何从一个磁盘映像中挂载指定的分区到本地 Linux 文件系统呢?理论上说,可以用 dd 把该分区从磁盘映像中提取出来再挂载,不过 mount 提供了针对 loop 设备的偏移量参数,方便直接从磁盘映像中挂载指定分区。笔记如下:
  演示用的磁盘映像使用 qemu-img 制作。我们使用原生的 raw 格式,等价于磁盘上的原始数据流,保证它在任何 Linux 系统上都可以直接挂载。使用 Windows PE 工具盘启动该 qemu 虚拟机,创建一系列不同格式的分区并在其中建立几个文件。

  1. root@lj-laptop:/opt/vm# qemu-img create -f raw vmtest.img 5G
  2. root@lj-laptop:/opt/vm# qemu -hda ./vmtest.img -cdrom /dev/cdrom -boot d -m 256M -localtime

  磁盘分区结构如截图:
从磁盘映像中挂载或提取指定分区
  回到宿主系统,使用 fdisk 的 -l、-u 参数查看磁盘映像。其中 -u 表示以扇区为单位显示分区起止位置,方便后续计算。

  1. root@lj-laptop:/opt/vm# fdisk -l -u vmtest.img
  2. You must set cylinders.
  3. You can do this from the extra functions menu.
  4.  
  5. Disk vmtest.img: 0 MB, 0 bytes
  6. 255 heads, 63 sectors/track, 0 cylinders, total 0 sectors
  7. Units = sectors of 1 * 512 = 512 bytes
  8. Disk identifier: 0xbd86bd86
  9.  
  10.      Device Boot      Start         End      Blocks   Id  System
  11. vmtest.img1              63     8193149     4096543+  83  Linux
  12. vmtest.img2         8193150    10249469     1028160    5  Extended
  13. vmtest.img3        10249470    10474379      112455    6  FAT16
  14. vmtest.img5         8193213     8610839      208813+  83  Linux
  15. vmtest.img6         8610903     9028529      208813+  82  Linux swap / Solaris
  16. vmtest.img7         9028593    10249469      610438+   b  W95 FAT32

  这时我们只需要为 mount 添加 offset 参数,指定分区在磁盘映像中的逻辑地址,即可挂载这一分区。注意 offset 的单位是字节,通常一个扇区是 512 字节,因此需要用 fdisk 输出的 Start 乘以 512。以 vmtest.img3 分区为例。

  1. root@lj-laptop:/opt/vm# mount -o loop,offset=$((10249470*512)) vmtest.img ./part/
  2. root@lj-laptop:/opt/vm# ls ./part/
  3. InFAT16.txt
  4. root@lj-laptop:/opt/vm# umount ./part/

  如果有必要,我们可以将特定的分区从硬盘映像中提取出来,方便单独使用。通过 dd 可以完成提取,简便起见使用扇区大小 512 字节作为 bs 参数,这样 skip、count 参数很容易从 fdisk 的输出中计算出来。下面提取 vmtest.img5。

  1. root@lj-laptop:/opt/vm# dd if=vmtest.img of=linux2.img bs=512 skip=8193213 count=$((8610839-8193213+1))
  2. 417627+0 records in
  3. 417627+0 records out
  4. 213825024 bytes (214 MB) copied, 4.67434 s, 45.7 MB/s
  5. root@lj-laptop:/opt/vm# mount -o loop linux2.img ./part/
  6. root@lj-laptop:/opt/vm# ls ./part/
  7. InLinux2.txt  lost+found
  8. root@lj-laptop:/opt/vm# umount ./part/

  到这一步,我们已经实现了从磁盘映像中挂载或提取指定分区。其中 fdisk 帮我们完成了磁盘映像的分析,直接将分区的逻辑地址显示给了我们。现在我们再借机复习一下磁盘分区表的格式,试试手工计算相关地址。这里推荐大家阅读网上这篇《解读 Windows 操作系统分区表的秘密》,其中详解过的概念这里不再赘述,下面的内容权当对这篇文章在 Linux 平台下的补充。
  首先查看磁盘映像的主引导扇区,其中分区表位于 0x1be 开始的 64 字节。

  1. root@lj-laptop:/opt/vm# cat vmtest.img | xxd | head -32
  2. ...
  3. 00001b0: 0000 0000 0000 0000 86bd 86bd 0000 0001  ................
  4. 00001c0: 0100 83fe 7ffd 3f00 0000 3f04 7d00 0000  ......?...?.}...
  5. 00001d0: 41fe 05fe bf7d 7e04 7d00 8060 1f00 0000  A....}~.}..`....
  6. 00001e0: 817e 06fe bf8b fe64 9c00 8e6e 0300 0000  .~.....d...n....
  7. 00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

  对于 vmtest.img1 和 vmtest.img3 这两个主分区,我们读出它们的起始逻辑地址分别为 0x3f 和 0x9c64fe(注意在分区表中以 Little-endian 存储),换算成十进制与 fdisk 输出的一致。bash 的算术表达式支持十六进制字面值,挂载方式同上。

  1. root@lj-laptop:/opt/vm# mount -o loop,offset=$((0x3f*512)) vmtest.img ./part/
  2. root@lj-laptop:/opt/vm# ls ./part/
  3. InLinux.txt  lost+found
  4. root@lj-laptop:/opt/vm# umount ./part/
  5. root@lj-laptop:/opt/vm# mount -o loop,offset=$((0x9c64fe*512)) vmtest.img ./part/
  6. root@lj-laptop:/opt/vm# ls ./part/
  7. InFAT16.txt
  8. root@lj-laptop:/opt/vm# umount ./part/

  对于扩展分区 vmtest.img2,我们通过 dd 定位到它所指向的第一个逻辑分区 vmtest.img5 前面的卷引导记录,查看逻辑分区的链式分区表。

  1. root@lj-laptop:/opt/vm# dd if=vmtest.img bs=512 skip=$((0x7d047e)) | xxd | head -32
  2. ...
  3. 00001b0: 0000 0000 0000 0000 0000 0000 0000 0001  ................
  4. 00001c0: 41fe 83fe bf17 3f00 0000 5b5f 0600 0000  A.....?...[_....
  5. 00001d0: 8118 05fe bf31 9a5f 0600 9a5f 0600 0000  .....1._..._....
  6. 00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  7. 00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

  vmtest.img5 相对于 vmtest.img2 的偏移量为 0x3f,按此地址挂载。

  1. root@lj-laptop:/opt/vm# mount -o loop,offset=$(((0x7d047e+0x3f)*512)) vmtest.img ./part/
  2. root@lj-laptop:/opt/vm# ls ./part/
  3. InLinux2.txt  lost+found
  4. root@lj-laptop:/opt/vm# umount ./part/

  沿着链式分区表的第二条记录(即链表指针)指示的偏移量,我们可以找到第二、第三个逻辑分区(vmtest.img6、vmtest.img7)前面的卷引导记录以及这两个分区的逻辑地址。

  1. root@lj-laptop:/opt/vm# dd if=vmtest.img bs=512 skip=$((0x7d047e+0x65f9a)) | xxd | head -32
  2. ...
  3. 00001b0: 0000 0000 0000 0000 0000 0000 0000 0001  ................
  4. 00001c0: 8118 82fe bf31 3f00 0000 5b5f 0600 0000  .....1?...[_....
  5. 00001d0: 8132 05fe bf7d 34bf 0c00 4ca1 1200 0000  .2...}4...L.....
  6. 00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  7. 00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.
  8. root@lj-laptop:/opt/vm# dd if=vmtest.img bs=512 skip=$((0x7d047e+0xcbf34)) | xxd | head -32
  9. ...
  10. 00001b0: 0000 0000 0000 0000 0000 0000 0000 0001  ................
  11. 00001c0: 8132 0bfe bf7d 3f00 0000 0da1 1200 0000  .2...}?.........
  12. 00001d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  13. 00001e0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  14. 00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa  ..............U.

  取得了相应的地址,挂载或提取分区当然是轻而易举的。下面挂载了 vmtest.img7、提取了 vmtest.img5。

  1. root@lj-laptop:/opt/vm# mount -o loop,offset=$(((0x7d047e+0xcbf34+0x3f)*512)) vmtest.img ./part/
  2. root@lj-laptop:/opt/vm# ls ./part/
  3. InFAT32.txt
  4. root@lj-laptop:/opt/vm# umount ./part/
  5. root@lj-laptop:/opt/vm# dd if=vmtest.img of=linux2.img bs=512 skip=$((0x7d047e+0x3f)) count=$((0x65f5b))
  6. 417627+0 records in
  7. 417627+0 records out
  8. 213825024 bytes (214 MB) copied, 4.65149 s, 46.0 MB/s
  9. root@lj-laptop:/opt/vm# mount -o loop ./linux2.img ./part/
  10. root@lj-laptop:/opt/vm# ls ./part/
  11. InLinux2.txt  lost+found
  12. root@lj-laptop:/opt/vm# umount ./part/

解决 Ubuntu 登录时用户名中不能含有“@”的问题

2009/10/06 | 13:19 | 分类:Linux与开源 | 标签: | 394次阅读

  最近的项目需要在 Linux 中配置自定义的 PAM 做用户认证。在这个 PAM 中,用户名是 Email 的形式。该 PAM 在 CentOS 5.3 下工作正常,但在 Ubuntu 9.04 下,登录过程输入用户名时一旦按下 Email 中的“@”,之前输入的字符就会被清空(相当于 Ctrl-U,kill character 的效果),导致无法登录。我开始认为这是键盘映射的问题,但用 loadkeys 恢复标准键盘映射之后问题依旧。这也不像 stty 的错误,因为在同一个终端上登录到 shell 之后再输入“@”是正常的。于是 google 之,在相关的 HOWTO 页面找到了以下信息:

Under xdm, the default erase and kill characters are # and @, as in good old Unix Version 6.
At the first attempt, you are talking to getty. At the second attempt, you are talking to login, a different program.

  看来“@”变成 kill character 不是无中生有,而是有历史依据的;同时输入不了“@”的关键在 getty,而不在 login(实验发现如果第一遍用户名、密码输入错误,第二遍输入用户名时是可以输入“@”的,这印证了问题确实在 getty 而不在 login)。于是我 man getty,发现了问题所在:Ubuntu 上的采用的 getty 是 agetty,而 CentOS 上采用的是 mingetty。agetty 的 Manual 指出,“@”、“#”分别被用作 kill character 和 erase character,而 mingetty 并没有这一非标准的定义。agetty 的 Manual 没有说明如何取消“@”、“#”的特殊功能,我查看了它的源代码(位于 util-linux-ng 包)才发现这个特性是写死在代码中的。看来要在用户名中输入“@”,只能设法绕开 agetty。我的方法是在 Ubuntu 中安装 mingetty,然后设置系统启动时用 mingetty 代替 agetty 开启终端(/etc/event.d/tty*):

  1. $ sudo apt-get install mingetty
  2. $ tail -1 /etc/event.d/tty1
  3. exec /sbin/mingetty tty1

  重启之后,就可以用 Email 形式的用户名登录了。

互联网需要 Kaopulity 精神

2009/10/03 | 01:15 | 分类:IT杂谈 | 标签: | 396次阅读

  晚上整理旧文件时,我偶然发现了 2001 年申请的一个网络服务:来自 Everyone.net 的免费邮局(起初没有自己的顶级域名,我注册的邮局名为“8.mail.everyone.net”,邮箱后缀是“@8.every1.net”)。那时只是出于好奇,申请之后在同学间做过宣传,只有两三个人上去注册了自己的邮箱。最后连我自己也没怎么使用就慢慢淡忘了。八年过后,Everyone.net 竟然还保留着我的账户,登录、收发邮件一切正常。这种感觉可以用一个新学到的词汇来形容——Kaopulity
  这让我联想到了更早申请的另一项免费服务:来自 Webalias.com 的二级域名。这个网站真可谓是十年如一日,1998 年建立,1999 年小幅改版之后到现在界面和功能一直没有变化(Internet Archive 为证)。我在 1999 年申请的几个二级域名(to.up.toto.stop.toto.sail.to)至今还可以访问。试问国内有哪个类似的网络服务做到了这一点?
  上了十年网,又有几个网站能给我留下 Kaopulity 的印象呢?数数看,自己手头有近十年历史的老账号—— Hotmail、Yahoo!、ICQ、搜狐、网易、新浪,还有已经弃用的 QQ(OICQ),其中 Hotmail 和 Yahoo! 没有出过什么大问题,始终是我较为信任的服务。2000 年前后的互联网泡沫时期,我并没有使用太多的国外服务,因此并不了解当时外国的互联网界被折腾到了什么地步。体会较深的便是 163.net、263.net 等邮箱以及网易、3322.net 等个人主页纷纷倒向收费阵营,QQ 以注册号码、申请会员为切入点发明出各种敛财花样,新浪邮箱缩水、大量个人主页服务商停止申请新账号这类事件。其后几年倒下的网站和服务我还能列举出不少——fm365.com、chinese.com、PCICQ、TomQ……免费服务如此,收费服务同样遭殃,我的第一个顶级域名“ljnu.com”(Lin Jian Networt Union)便是随着注册商“中文热站”(hothost.com)的倒台而消失的(据说这家公司是新网的前身?)
  大学之初,我也是 Gmail 的早期测试用户,然而 2006 年遇到了一波严重的垃圾邮件攻击让我对这个号称能最有效地拦截垃圾邮件的邮箱产生了严重的怀疑。直到后来发现 Google 的服务不断改进和完善,我才在同学的劝说下第二次注册了 Gmail 账号,稳定使用至今。Google 是这个时代的胜利者之一,但在 web 2.0 时代,网站和服务 Unkaopulity 的因素也逐渐变得复杂了。市场竞争中的优胜劣汰始终是最好的理由,“测试版”的标签也是向用户和监管部门双方规避责任的良好借口。无论选择国内还是国外的服务,web 2.0 所谓用户创造内容的特性往往成为其在辉煌时期突然消失的祸根,这种例子不必多说。
  糊里糊涂地,我们又让云计算走进了日常应用。一夜之间各类网络服务都被披上了“云”的外衣。我们何以建立云的 Kaopulity 模型?这将是一个综合了技术、政策与用户心理的难题。当然,我们经历的 Unkaopulity 多了去了,自己那点文件也值不得下大工夫维护其安全保密,重要的数据和应用本来就应该在可信域内部署和备份,想让云计算达到可用性与可靠性完美兼备是勉为其难。但是我觉得,超越了 Reliability 和 Security 范畴的、广义上的 Kaopulity,即像 Everyone.net、Webalias.com 那样十年如一日的精神,才是当前的互联网服务商需要倍加重视的——因为云时代的服务商承载的不仅仅是应用程序,而是他人的事业,自己的信用。

搜狗拼音与 Foxmail 引发的灵异邮件

2009/09/25 | 13:48 | 分类:Windows应用 | 标签: | 550次阅读

  当你发现你收到的多封邮件中,同一个人的名字都被“死”字代替,这是不是一件恐怖的灵异事件?这事就被我遇到了。不过经分析,这只是搜狗拼音输入法与 Foxmail 引发的一个小问题。

搜狗拼音与 Foxmail 引发的灵异邮件

  出问题的名字是“查老师”,“”在姓氏中读“zhā”。在搜狗拼音中,输入“zha”,“查”字的排名比较靠后;然而有一个与“查”字外形相似的“”字(注意下面是“且”而不是“旦”)却像李鬼一般地排在了“查”字之前(它做了 SEO 吧 :) )。“査”是一个不常用的 GBK 汉字,但是发件人使用的 Foxmail 客户端生成的 MIME 消息中,标称的 charset 却写的是默认的 GB2312(严格地说也算 bug)。于是在我的客户端里,“査”字(96CB)没有被当作 GBK 正确解码,它的第二字节(CB)与“老”字(C0CF)的第一字节(C0)结合,恰好构成了“死”字(CBC0)。
  提醒使用拼音输入法的同学,不要再把“查”误输入为“査”。如果怕输错,可以直接用“cha”代替“zha”。而在邮件客户端方面,可以设置发出的邮件编码,用 GBK 或 UTF-8 取代 GB2312,以免少数非常用汉字导致接收方解析出错,造成对方收到“死”这种很不礼貌的灵异邮件。

《我是一只 IT 小小鸟》杂想

2009/09/17 | 23:38 | 分类:团队合作 | 标签: | 904次阅读

  上个周日的 China-pub 九周年庆生会,我算是第一次以作者的身份出现在这类活动。尽管我们的《我是一只 IT 小小鸟》被安排在最后一场演讲,但在胡江堂张弦及博文视点编辑团队的精心策划下,还是取得了不错的宣传效果。在这个庆生会上,我竟遇到了两位我的 Blog 的读者(当然,不包括已经熟识的人),这让我欣慰的同时又感到了压力。毕竟自己每日才 100 多的访问量不能和国内那些名博相提并论,但既然有人关注自己的言论,那说话就要多负点责任。

《我是一只 IT 小小鸟》杂想
部分作者、编辑与先期读者合影

  这几天抽空把《小小鸟》的所有文章读完了。虽然我之前已经看过半数以上作者的初稿,但后来经过作者的反复修改和编辑的审校排版,最终章节分明的成品确实打消了我原先面对那一篇篇风格与组织迥异的 Word 文档的担忧。通过对两种目录、大小标题、不同版式和字体的应用,零散的故事有了清晰的脉络,方便读者快速定位到自己感兴趣的内容,这似乎是博文视点近期非技术类图书的主流风格。更重要的是内容的取舍,周筠老师不愧是经验丰富的出版人,懂得平衡作者的得意点与读者的期望点,让付印的每一段文字都能够尽可能地满足双方的需求。
  也谈两点我的杂想吧:
  1.读书。很多作者都在自己的兴趣爱好中列出了“读书”,还有不少作者专门讲述了自己与书结缘的一系列故事。刘未鹏徐宥两位网络名博还列出了自己的推荐书单(一软一硬、一横一纵呵)。也许是爱读书的人更容易产生写书的欲望吧?阅读和写作就像是 Unix 管道的输入与输出,一端的进程阻塞了,另一端就需要有所动作。我们不排除高昂简朝阳等人很可能是先有了技术图书的出版经历才被纳入了本书的作者团队,不过我想这并不至于影响作者的代表性,毕竟爱读、爱写才能对写作、出版的质量提供保证。有趣的是,不少作者的也将“旅行”写在了自己的兴趣爱好中,但限于本书主题,几乎没有相关的话题被提及。
  2.年龄。这个问题要从几个月前我加入本书写作团队的 Google Groups 说起。我在内部作自我介绍时使用了“年轻”、“新人”等词,因为我看到多数作者已经硕士毕业,而我刚刚研一。但看到书中每个作者章首页时,发现他们之中确有若干与我同年甚至更年轻;或是只比我大一岁但教育背景并不连续的。原来自己并不是年轻,而只是“经历轻”罢。没办法,我家那边人老实,入学年龄都是规规矩矩。这一年多在实验室帮两届硕士做过开题、答辩之类的秘书工作,看到平时称为师兄师姐的学生的档案年龄,有的比我要小一两岁,只能感叹而毫无解决方案。我能做的,只是给自己一个动力,一个更加珍惜时间的理由。
  刚刚在 China-pub 上看到,《小小鸟》已经进入了计算机类图书 7 日销售排行的第 22 名。希望我们能有不错的业绩。我会响应徐宥的建议,借此收入为公益事业献出微薄之力。

页面存档: 上页 1 2 3 4 5 6 7 8 ...44 45 46 下页