Posted 星期五, 2009-10-02 22:44 by adoal
标准 MBR 从偏移量 0x1b8 开始的 4 个字节是签名,用来标识一个磁盘。这个标记在大多数操作系统里并没有使用,而且很容易被改写掉。 Windows 使用签名来作为识别磁盘的依据,并结合卷的起始偏移量来判定如何分配盘符,如果某个卷的 (签名, 起始偏移量) 组合和盘符的对应关系已保存在注册表里,就给它分配相应的盘符。
直到 Windows 5.x 系列, MBR 签名并不影响 Windows 基本系统的启动过程。 NTLDR 在 boot.ini 里读取的启动配置,磁盘标识是按照 BIOS 约定来编号的。也有资料表明 MBR 签名可以被用于帮助 Windows 在 BIOS 无法处理的情况下完成启动,但并不是强制的。所以操作系统安装程序、磁盘分区管理软件和启动管理软件把 MBR 签名改写之后, Windows 的启动不受影响。也许正是因为如此,这些软件(包括 Windows 自己的安装程序)改 MBR 的时候并不会小心翼翼保留 MBR 签名的值。
然而在 Windows 6.x 时代,这种做法就行不通了。 Windows 6.x 的启动信息放在 BCD 里,不再使用 BIOS 的磁盘编号和 MBR 分区表编号来寻找启动卷,而是 (签名, 起始偏移量) 组合。这样,如果意外改写了 MBR 签名(或者把启动卷移动了位置),就会造成无法启动。然而不幸的是相当多的操作系统(包括 Windows 5.x 在内)的安装程序以及启动管理软件都会去改写 MBR 签名;幸运的是,修复并不麻烦。可以把 MBR 签名改回来,也可以用 Windows 6.x 的安装盘或者 PE 启动盘去修复。
另外网上还有文章说明可以让 Windows 不检查 MBR 签名确定系统盘,从哪个盘引导的就把哪个盘作为系统盘:
BCDEDIT /set {bootmgr} device boot
BCDEDIT /set {default} device boot
BCDEDIT /set {default} osdevice boot
对于引导盘和系统盘一致的情况应该是好用的。
在不远的将来,使用 UEFI boot 和 GPT 分区表的系统将不存在这个问题,因为在 GPT 分区的磁盘里 MBR 只是起防犯旧式软件误操作的作用。操作系统识别卷的依据是 128 位的 GUID,没必要再用 (签名, 起始偏移量) 这种组合了。而移动卷的位置也不会带来什么问题。
Posted 星期日, 2009-07-26 02:25 by adoal
某域名十多年的邮件服务。期间硬件和软件换了好几次。近期将要停止服务。可能这次启用 SPF + greylisting 是我给此域名做的最后一次邮件服务配置了。
安装(Debian下)
$ sudo aptitude install postgrey postfix-policyd-spf-python
配置
[...]
policyd-spf_time_limit = 3600
smtpd_restriction_classes = mfrom_passed_spf
smtpd_recipient_restrictions =
[...]
reject_unauth_destination,
# 一定要放 在reject_unauth_destination 后
#否则会成为 open relay
check_policy_service unix:private/policyd-spf,
check_policy_service inet:127.0.0.1:60000,
# 后续检查
[...]
permit
mfrom_passed_spf =
# 后续检查
[...]
permit
使用 Postfix Restriction Class,只有 SPF 返回值不是 Pass (即 SPF 中性或临时错误)时才检查 greylisting 策略,这样可以减少 greylisting 延迟带来的用户体验变差。
- /etc/postfix-policyd-spf-python/policyd-spf.conf
[...]
Mail_From_reject = Fail
Mail_From_pass_restriction = mfrom_passed_spf
要注意 policyd-spf.conf 中字段名和值的大小写。
[...]
policyd-spf unix - n n - 0 spawn
user=policyd-spf argv=/usr/bin/policyd-spf
也许用 ppolicy 更合理一点,一个模块化的 policy server 完成多种功能,通过 Python 脚本来配置检查流程。不过看起来比较复杂,也不知道以后有没有机会玩了。
Posted 星期三, 2009-04-22 16:07 by adoal
前面说的那个在 Lenny domU 里的 PHP 解释器会在访问 Drupal6 的管理页面时停住的问题,其实是误会。问题还是出在 Drupal6 本身,它的更新模块试图直接连 Internet 时如果在内网时连不上,就阻塞在那里了,而且也没法设置代理。之所以我误以为真机上的没这问题,是因为那台真机是通过 NAT 出去的。试了一下把 domU 的 IP 加进 NAT 就好了。为这事还在 Debian bug mailing list 里报告了一下,真丢人。顺便看了一下 Drupal 网站上关于这事的讨论 [DRUPAL7881] ,从 2004 年开始就有,期间也有不少人发过各种简易 patch 但是基本上没啥定论。
Posted 星期二, 2009-04-21 00:08 by adoal
用于 Drupal6 的版本,加上了 Pygments 对代码做彩色语法显示。还是很简陋而且乱糟糟的,有很多地方要完善。
需要在主题的 style sheet 里设置菜色显示的颜色方案。 Acquia Marina 有个好处是可以把自己修改的设定加在 local.css 里这样升级的时候就安全了。
#content {
font-size: 133%;
}
#comments h2.comments {
text-transform: none;
font-variant: small-caps;
}
h2.title {
text-transform: none;
font-variant: small-caps;
}
pre {
font-family: "Consolas", monospace;
}
.literal {
text-decoration: none;
background-color: #fbeddd;
border-width: 0 0 1px 0;
border-style: none none dashed none;
}
/* code-block highlight scheme for Pygments output */
.highlight {
background-color: #ddedfb;
border-style: solid;
border-color: #0099cc;
border-width: 1px 0 1px 0;
margin: 1em 0;
padding: 0.5em 1em;
}
/* css genetated from gen_pyg_style.py should be appended here*/
上面是针对自己的喜好改的 local.css 内容,代码彩色语法的 css 可以用下面的脚本生成,加在 local.css 后面。
#!/usr/bin/python
import sys
from pygments.formatters import HtmlFormatter
style='friendly'
if len(sys.argv) > 1:
style = sys.argv[1]
print style
f = HtmlFormatter(style=style)
print f.get_style_defs()
另外 settings.php 最好也改一下
1 <?php
2 $db_url = '<database url...>';
3 $db_prefix = '';
4 $update_free_access = FALSE;
5 $conf = array(
6 'reverse_proxy' => TRUE,
7 'reverse_proxy_addresses' => array('x.y.z.w',),
8 'allow_insecure_uploads' => 1,
9 );
6、7 行是放在反向代理后面而本服务器又没做特别设置时的必要措施。8 行是因为 Drupal 默认会在上传文件时把多段扩展名加个下划线,譬如 .tar.gz 的改成 .tar_.gz 的样子,号称为了安全,但相当丑陋,我不需要这种安全。
Posted 星期六, 2009-04-18 17:57 by adoal
冒着来信延迟会被领导骂的危险启用了 postgrey,结果领导还没骂,发现自己先受不了,因为原先习惯了垃圾邮件,现在一天收收不到两三封,于是总担心服务器是不是坏了,嘿嘿。
Posted 星期二, 2009-04-07 17:42 by adoal
以前 Etch + Etch / Xen-3.0.3 的时候没遇到问题,现在 dom0 升级了之后, domU 里的时间不对了。当时没仔细看,然后遭遇同事投诉邮件时间不对,汗颜。
网上查了一些办法,试了都不行。配置到错得最严重的时候差了 16 个小时,狂晕。
后来重启了一下 dom0 所在的硬件,居然就好了。看来在原来 UTC=no 的机子上改 UTC=yes 之后还是重启可靠,仅仅用 hwclock 在线同步来同步去是不靠谱的。
domU 认为 dom0 发送过来的时间是 UTC,这也是 Linux kenrel 的默认行为。真机上的 dist 往往可以在启动时通过 hwclock 进行时区调整,而 domU 里没有 RTC 设备所以这个办法就不行了,还是老老实实在 dom0 的 RTC 里用 UTC 存储时间吧,反正 dom0 的服务器上不会装 Windows 搞双启动。
设置 domU 使用独立的时间,然后通过 NTP 同步也是个可行的办法,但太重量级了,没必要。
Posted 星期四, 2009-04-02 22:01 by adoal
Lenny 正式发布之前终于解决了 dom0 的问题,好像是从蜥蜴那里抄来的 backport 吧,反正不是 pv_ops 的方案。于是最近忍不住把一个运行很好的 dom0 从 Etch 升到 Lenny 了,不为别的就为了 PyGrub,没出息。还好对原来的 Etch/domU 没啥影响而且牠能在 domU 内自己升自己的 kernel 也确实挺方便的。然后又装了个 Lenny/domU,折腾得晕。主要问题及解决办法:
- 启动 Lenny/domU 过了 crond 之后就失去反应了,但网络是通的,想不明白问题在哪里,干掉重装了几次都不行。而 Etch/domU 就没这毛病。后来谷歌得知新版的 Xen domU 更改了处理 console 的方式(而 Etch 里用的还是 Xen 3.0.3 的),其实系统启动好了只是 tty 没跟 console 挂在一起而已。遂在 domU 的内核参数里加上 xencons=tty ,或者把 /etc/inittab 里的 getty 项改成
1:2345:respawn:/sbin/getty 38400 hvc0
这种样子即可。前一种方法比较传统而后一种比较现代。回头想想, debootstrap 安装的时候没装 ssh server 是个失误,如果启动之前补装了就可以远程登录了。
- Lenny 里的 update-grub 非常之脑残一定要去找根分区所在的硬盘,问题是我用 LVS 装的,把 dom0 的 LV 导入 domU 当文件系统(没用整个 xvd),这样是不可能找到硬盘的,于是 update-grub 出错,于是一直 broken…… 最后的解决办法是在 rc.local 里加了这么一句:
XVDADEV=/dev/xvda
if test ! -e $XVDADEV; then mknod $XVDADEV b 202 0; fi
并且在 grub 的 device.map 里建立映射,相当无语啊。后来想了想,其实可以在 /etc/kernel-img.cong 里去掉 update-grub 的那两项。在 domU 里装一大堆 kernel 把 grub 启动菜单搞复杂根本没必要,只要有一项就够用。而且即使 testing 的 kernel 版本号也不会经常变,需要的时候手工改一下即可。
另外,把这个 Drupal 站移到 Lenny guest 里会出问题,访问管理页面时 php5 锁住不动了,不论用 FastCGI 方式还是 Apache module 方式都如此,很不解。还是放在外面吧。
Posted 星期四, 2009-03-26 23:57 by adoal
最近对本站动了两次手脚。
稍远的一次是从 5.X 升级到了 6.X,按照 Drupal 的升级指南一步一步来就行。中间有个意外, 自己写的 5.X 山寨版 reStructured Filter 在升级之后挂了。于是找了个Markdown Filter 的例子把框架扒出来套用了一下搞定。中途不小心破坏了一个 node 的内容,修复之。今天才发现写东西的时候用不了这个 filter 了,遂修正了一下被剥夺的权限。似乎还有些不太对,留着慢慢修吧。
稍近的一次是把后台数据库从 MySQL 迁移到了 PostgreSQL,用写迁移指南 [DRUPAL15793] 那位老兄的话来说“I'm not a MySQL fun” :D 话说我觉得这里 fun 应该是 fan 才说得通。
指南里的三个问题,第一个不管,因为我数据库是 UTF-8 的;第二个要打上补丁,其实就是添了一个字母 E;第三个先不管,反正现在用到的模块不存在这问题。
但是按照指南的步骤搞好以后,站点统计会报错。根据提示信息并搜索并思考得知,PostgreSQL 是没有 CONCAT 函数的,于是 Drupal 自己写了个 SP 加进来,但不幸的是调用的时候参数类型不匹配。真是相当莫名其妙,不知道以前的版本它是怎么搞的。于是手工写了个重载的 CONCAT 搞定之。期间反反复复 DROP 库重建好几次,因为忘了在新库里开启非默认模块,而这东西在迁完库之后再开启是无效的。
以后的子版本升级得小心 E 的问题,至于 重载的CONCAT 应该不会被干掉的。。
瞎折腾啊。
Posted 星期一, 2008-08-18 08:58 by adoal
跟用 Apache 相比小有一点麻烦,需要配置一下。
location ~ /zope(/|$) {
fastcgi_pass unix:/var/run/plone-site.sock;
include /etc/nginx/fastcgi_params;
set $fixed_content_length $content_length;
if ( $fixed_content_length = "" ) {
set $fixed_content_length "0";
}
set $path_info "";
if ( $document_uri ~ "^/zope/(.*)$" ) {
set $path_info $1;
}
fastcgi_param CONTENT_LENGTH $fixed_content_length;
fastcgi_param PATH_INFO $path_info;
fastcgi_param SCRIPT_NAME /zope;
}
主要原因是, Zope 对 SCRIPT_NAME 和 PATH_INFO 两个参数的要求是以 Apache 方式为基准的, Nginx 的方式无法分辨出访问的对象标识。看了一下 CGI 标准,应该是 Nginx 的做法站不住脚,但好在可以通过配置来解决。另外, Zope 直接把 CONTENT_LENGTH 的值(字符串)丢给 aoti 而这个函数在字符串为空时会抛出异常, Zope 没考虑到这一点,所以也要修正一下。
顺便感慨,把这条技巧加到 Nginx Wiki 里的时候,看了一下历史变动,里面有相当多的中文 spam 广告被管理员删掉的记录,汗啊。
Posted 星期三, 2007-12-05 23:09 by adoal
自某年某月某日起,某 Plone 服务出现一个严重问题,上载文件稍微大一点就会出错。当时懒得折腾,今天领导敦促,于是试图解决之。直觉告诉我问题不在 Zope 里,前端的 Apache 出问题的可能性比较大。看日志,果然如彼:
[Wed Dec 05 13:54:30 2007] [error] [client ##.##.##.##] request body exceeds maximum size for SSL buffer, referer: ...
[Wed Dec 05 13:54:30 2007] [error] [client ##.##.##.##] could not buffer message body to allow SSL renegotiation to proceed, referer: ...
骨骼了一下,发现 [ASF39154] 提到了这个问题,回答是:
This does not work on directory level with large files, because we currently do not buffer the request body on disk but only 128k at max in memory. Moving SSLVerifyClient require to virtual host level will make it work (see also PR12355)
好吧,虽然我用的是 SSLVerifyClient optional 不过原因是一样的,于是照做,把这个东西搬到 <VirtualHost> 上下文里,于是问题解决了。隐约回忆一下,似乎当初用 Plone 默认登录方式的时候是没这问题的。据传 Apache 这样设计是为了防止被 DoS 死,大汗!
不过这个 virtual host 里除了 Zope 还运行着其它东西,试验了一下在其它 <Location> 上下文里加入 SSLVerifyClient none 还是要做一次可选的验证,似乎不起作用,不解。先不管了,大不了另找个机子移过去。