欢迎回到 delphij 的火星!


2019 年 12 月 24 日

DragonFly BSD Digest

2019 年 12 月 22 日

DragonFly BSD Digest

Lazy Reading for 2019/12/22

Accidental theme this week: roguelikes!  Maybe with me that’s not so accidental.

by Justin Sherrill at 2019-12-22, 01:51 下午

2019 年 12 月 21 日

DragonFly BSD Digest

In Other BSDs for 2019/12/21

I managed to miss the Thursday update to BSDNow (#329) – Michael W. Lucas is interviewed mostly about his unnatural love of gelato BSD books , and he’s always an entertaining talker.


by Justin Sherrill at 2019-12-21, 01:57 下午

FreeBSD Ports Vulnerability Alert

2019 年 12 月 20 日

DragonFly BSD Digest

True du on DragonFly

You probably type “du -sh *” reflexively when looking at disk usage, or at least I do.  On DragonFly, there’s also a -t option, which gives the simple file size on disk.  That’s the amount of data that would need to move when copied; that may differ from other amounts because of compression at the filesystem level.

by Justin Sherrill at 2019-12-20, 04:30 下午

FreeBSD Ports Vulnerability Alert

2019 年 12 月 19 日

OpenBSD Journal

e2k19 Hackathon Report: Stefan Sperling on GoT and wireless

Next up from the snowy Elk Lakes area with his Hackathon Report is Stefan Sperling (stsp@):

My hike to the Elk Lakes hut was more pleasent this time compared to last time (s2k17). Partly because the weather was better overall this time around. And I knew what to expect and had planned ahead better. I had left my thick and heavy jacket at home which had turned out to be a nuisance, being too warm and too heavy for hiking. I packed a light and thin rain jacket instead to protect against wind and rain, but we didn't get either so the jacket stayed in the bag. My backpack still felt a bit heavy on the hike in, but that was due to lunch snacks which were all eaten up by the time we hiked back out.

Read more…

2019-12-19, 08:56 下午

2019 年 12 月 18 日

DragonFly BSD Digest

Power vs serial

This is minor, but I’ll mention it because it might bite you someday: if you are using powerd to minimize CPU power usage, and also trying to push a high data rate through your serial port, you might drop characters.  It’s mentioned in the powerd(8) man page, which has an entertaining bugs section.

by Justin Sherrill at 2019-12-18, 04:28 下午

FreeBSD Ports Vulnerability Alert

2019 年 12 月 16 日

delphij's chaos

用 Pomerium 来实现基于身份的访问控制

Google 在十年前提出了一套名为 BeyondCorp 的零信任网络的安全方案。 这套方案想要完整地实现还是有一定门槛的,在这种模型下,企业内网不再作为一个安全边界存在,相反即使在内网进行的访问也必须进行和外网同样的鉴权与访问控制。 最终的改造方向是内网不再是一个特权网络,每个终端上部署的客户端证书主要是作为一项身份信息来使用。

在 BeyondCorp 方案中对用户比较可见的一项便是统一登录认证 SSO 和基于用户身份进行访问控制的反向代理。之前考虑过许多其他方案,包括使用 nginx 自己山寨一套,不过后来听 @yegle 同学的建议, 直接用 Pomerium 来实现了一套鉴权反向代理,这里把大致过程记录一下。

首先是安装。 FreeBSD 没有对应的 port,于是 做了一个。新用户可以直接用 pkg install pomerium 来安装了。

必须配置的一些选项包括 pomerium_enable (显然)。如果使用 Pomerium 来的做 https 服务,那么还需要配置 pomerium_cert_file(指向一个 wildcard 证书)和 pomerium_cert_key_file。除此之外, pomerium_shared_secret 和 pomerium_cookie_secret 应分别设置为两个随机串,不过如果没设置的话系统会自动每次启动时生成新的随机串。需要注意的是,假如需要使用标准的 https 端口 443,如果以系统默认的非特权用户来运行 Pomerium 的话,需要将 net.inet.ip.portrange.reservedhigh 设为小于 443 的值才行。

然后是配置。OAuth 2.0 需要一个回调 URL,Pomerium 中这个可以是 https://authenticate.corp.{example.com}。在 IdP (如 Google、Azure等等)完成身份验证之后,IdP会将用户转回这个URL完成后续的设置。

IdP相关的主要设置是 idp_provider、idp_client_id 和 idp_client_secret,后两项信息要从 IdP 那里获得。如果 IdP 提供了群组功能,可能还需要进行一些额外的设置,例如 G Suite 就要求服务账户必须能够以某种管理员的身份运行。

代理方面,在代理服务器后面受其保护的服务器应 验证 Pomerium 的请求头签名。除此之外,代理的配置其实是很简单的,如果是比较小的系统,用 allowed_users 就足够了。大一些的系统可以用 allowed_domains 和 allowed_groups。另一个潜在的坑是要注意后端服务器不要在做 redirect 时回自己的 URL,如果发生这种情况,需要把后端服务改对或者至少搞一层重写。

by Xin LI at 2019-12-16, 07:21 上午

2019 年 12 月 12 日

OpenBSD Journal

Meet Radiant Award Recipient Claudio Jeker

The Internet Security Research Group and partners have announced that Claudio Jeker (claudio@) is the third Radiant Award recipient. From the announcement:

We’re excited to announce the third Radiant Award recipient, Claudio Jeker.

When we at ISRG think about the greatest threats to Web security today, the lack of Border Gateway Protocol (BGP) security might top our list. Claudio's passion for networking, his focus on security, and his talent as a software developer are enabling him to make great contributions to fixing this and other Web security problems. In particular, he is making great contributions to OpenBSD and OpenBGPD.

Congratulations Claudio!

2019-12-12, 07:23 上午

2019 年 12 月 09 日

OpenBSD Journal

attention please: host's IP stack behavior got changed slightly

Alexandr Nedvedicky (sashan@) wrote to tech@ regarding a recent significant change:


commit from today [1] makes IP stack more paranoid. Up to now OpenBSD
implemented so called 'weak host model' [2]. The today's commit alters
that for hosts, which don't forward packets (don't act as routers).

Your laptops, desktops and servers now check packet destination address
with IP address bound to interface, where such packet is received on.
If there will be mismatch the packet will be discarded and 'wrongif'
counter will be bumped. You can use 'netstat -s|grep wrongif' to
display the counter value.

It is understood the behavior, which has been settled in IP stack since 80's,
got changed. tech@openbsd.org (or bugs@openbsd.org) wants to hear back from you,
if this change breaks your existing set up. There is a common believe this
change won't hurt majority (> 97%) users, though there is some non-zero risk,
hence this announcement is being sent.

thanks and

[1] https://marc.info/?l=openbsd-cvs&m=157580332113635&w=2

[2] https://en.wikipedia.org/wiki/Host_model

Read more…

2019-12-09, 02:44 上午

2019 年 12 月 04 日

OpenBSD Journal

e2k19 Hackathon Report: At e2k19 nobody can hear you scream (Claudio Jeker)

Fresh from the just concluded e2k19 hackathon, Claudio Jeker (claudio@) writes in:

After 2 years it was once again time to pack skis and snowshoes, put a satellite dish onto a sledge and hike through the snowy rockies to the Elk Lakes hut.

Read more…

2019-12-04, 05:09 下午

2019 年 12 月 02 日

OpenBSD Journal

syscall call-from verification

Theo de Raadt (deraadt@) has committed code for a new exploit-prevention mechanism:

Repurpose the "syscalls must be on a writeable page" mechanism to
enforce a new policy: system calls must be in pre-registered regions.
We have discussed more strict checks than this, but none satisfy the
cost/benefit based upon our understanding of attack methods, anyways
let's see what the next iteration looks like.

This is intended to harden (translation: attackers must put extra
effort into attacking) against a mixture of W^X failures and JIT bugs
which allow syscall misinterpretation, especially in environments with
polymorphic-instruction/variable-sized instructions.  It fits in a bit
with libc/libcrypto/ld.so random relink on boot and no-restart-at-crash
behaviour, particularily for remote problems. Less effective once on-host
since someone the libraries can be read.

The full commit details are well worth reading, as is the manual page for the (new) msyscall(2), and some associated discussion on tech@.

As this change involves ABI breakage, upgrading via snapshots is the easiest way to avoid trouble.

2019-12-02, 10:58 上午

2019 年 11 月 25 日

FreeBSD News Flash

July-September 2019 Status Report

The July to September 2019 Status Report is now available.

2019-11-25, 08:00 上午

2019 年 11 月 12 日

FreeBSD Security Advisories

2019 年 11 月 04 日

FreeBSD News Flash

FreeBSD 12.1-RELEASE Available

FreeBSD 12.1-RELEASE is now available. Please be sure to check the Release Notes and Release Errata before installation for any late-breaking news and/or issues with 12.1. More information about FreeBSD releases can be found on the Release Information page.

2019-11-04, 08:00 上午

2019 年 10 月 18 日

FreeBSD News Flash

FreeBSD 12.1-RC2 Available

The second RC build for the FreeBSD 12.1 release cycle is now available. ISO images for the amd64, armv6, armv7, arm64, i386, powerpc, powerpc64, powerpcspe, and sparc64 architectures are available on most of our FreeBSD mirror sites.

2019-10-18, 08:00 上午

2019 年 10 月 11 日

FreeBSD News Flash

FreeBSD 12.1-RC1 Available

The first RC build for the FreeBSD 12.1 release cycle is now available. ISO images for the amd64, armv6, armv7, arm64, i386, powerpc, powerpc64, powerpcspe, and sparc64 architectures are available on most of our FreeBSD mirror sites.

2019-10-11, 08:00 上午

2019 年 08 月 20 日

FreeBSD Security Advisories

2019 年 08 月 04 日

delphij's chaos

将 Windows 10 的系统时钟时间设置为UTC


在 64-位 Windows 10 系统中,以管理员身份运行:

reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_QWORD /f

即可让 Windows 也把系统时钟当作 UTC 而不是本地时间了。

by Xin LI at 2019-08-04, 07:06 上午

2019 年 07 月 03 日

车东 Blog ^ 2

Perl 5.22以后的语法更新:Unescaped left brace in regex is illegal here in regex; marked by <-- HERE in m/\"%{ <-- HERE Referer}i\"/ at ./awstats.pl line 9045.


Unescaped left brace in regex is illegal here in regex; marked by -- HERE in m/\"%{ -- HERE Referer}i\"/ at ./awstats.pl line 9045.

As written by @Leobaillard you can use his patch. If you want to fix this with your editor (vi) you can go to line 3936 and make the following changes
$ vi buildroot/output/host/usr/bin/automake
goto line :3936 and change
$text =~ s/\${([^ \t=:+{}]+)}/substitute_ac_subst_variables_worker ($1)/ge;
$text =~ s/\$\{([^ \t=:+\{\}]+)\}/substitute_ac_subst_variables_worker ($1)/ge;
The error is with automake and perl v5.26.

从perl v5.22开始:不再推荐在正则表达式中使用 {,而且如果没有转义 \{ 会有错误警告,从v5.26开始:不仅有警告,还会有语法错误提示。

2019-07-03, 04:11 下午

2019 年 05 月 17 日

delphij's chaos


加州光照充足,在换了油电混合车并安装了空调以后,我目前每年的用电量大约是每年6000 kWh(此前每年的用电量大约是2400 kWh)。随着加州电价的逐年提高,安装太阳能发电终于不再是一件不经济的事情了。

根据贵厂的 Project Sunroof 估计,我家屋顶每年的可用光照时间大约是 1903 小时,其中有 1357 平方英尺(大约126平方米)的面积可以用来安装太阳能板。经过和数家(马老板的 Tesla 即原 SolarCity、 Costco 合作的 SunRun,以及同事推荐的 SunWork)太阳能板安装公司的询价,最终选择了采用 10 块太阳能板、微型逆变器(microinverter)的方案。其中, SunWork 是一家致力于推广太阳能发电的 501(c)(3) 非盈利机构(他们要求客户在12个月内的电费低于 $100;对于使用了电车的用户,这些用户在购买电车之前的12个月内应满足此条件),因此报价比其他供应商低了 1/3 左右。

由于太阳能板产生的是直流电,需要使用逆变器将其转换成交流电之后才能使用。常见的逆变器可分为三种:第一种是组串式逆变器,这种逆变器最便宜,适合直接能无遮挡地获得阳光照射的地方,缺点是它是将太阳能板串联起来并使用一个大逆变器完成工作,故当一块太阳能板出现问题时可能会导致整个系统停止工作或性能大大降低,并且这个中央逆变器本身是一个单点故障环节。第二种是 Power Optimizer,这种系统比组串式逆变器贵一些,它会将太阳能板发出的直流电保持在适宜的电压,以利于中央式逆变器将其转换为交流电。第三种是微型逆变器,这种方式最贵,逆变器和 Power Optimizer 类似,也是装在太阳能板下面,但区别是在那里就直接转换为交流电了。由于中央式逆变器的工作电流较大,因此通常其使用寿命在10-12年左右,而微型逆变器和 Power Optimizer 的使用寿命则要长的多(厂家通常保固25年)。由于采用了 Power Optimizer 的系统依然有一个中央的逆变器,因此在其使用寿命范围内通常会需要换一次,故而我选择了使用微型逆变器的设计方案。

在2月底基本完成报价和比较之后,我和 SunWork 大致确定了在 5 月 11 日进行安装。SunWork 的工作人员基本上都是志愿者,因此我也参与了一部分安装工作。随后,圣荷西市政府于 5 月 13 日完成了合规审查,我们在 5 月 14 日向太平洋瓦斯及电力公司提交了并网发电申请,并于 5 月 16 日收到了并网发电许可。

by Xin LI at 2019-05-17, 07:17 上午

2019 年 02 月 20 日

车东 Blog ^ 2

免费版StatPlus在Mac Excel 2016 v16以上版本集成菜单安装:Excel 加载项 ==> 启用StatPlusMacAddin

上门课要用Excel的分析插件,但Excel Mac版缺省没有:需要安装AnalystSoft的StatPlus插件。标准的安装步骤如下:可以启用相应的Excel集成菜单。
1 从官网下载StatPlus for Mac安装包并解包
2 移动StatPlus到“应用程序”并打开StatPlus;
3 从StatPlus的菜单中选取SpreadSheet并启用Excel菜单集成模式:
Excel menu integration: Statplus mac

低版本的Excel(包括Microsoft Office Excel 2011 2013 2016 v15及以下)会重启Excel并显示集成菜单:
Mac Excel 2011: StatPlus 6

但如果Excel是2016 v16版本以上(包括Excel 2019)则会收到以下提示:

Latest Excel 2016 versions (v16+) require additional step to enable StatPlus integration. Please follow the 'Integration with Excel 2016 v16' steps from the registration letter or contact us if you have any questions.

其实注册邮件里面根本没有任何关于v16+的提示,官网也上没有任何关于Excel 2016 v16版本如何启用Excel菜单集成的帮助入口:通过在线帮助提交问题会收到一个手动启用操作方法的回复,按提示在Excel 2016 v16.22上安装设置验证如下:

2019-02-20, 01:41 下午

2019 年 01 月 02 日

delphij's chaos

修复 MySQL 编码问题

有个疑似 OCD 患者最近抽风升级了一下 MySQL 数据库,然后发现 blog 里面全都变成了乱码。

那乱码的模式一看就是把 utf8 直接扔进了 latin1 的数据库,一看 SHOW CREATE TABLE mt_entry 发现果然如此。

略有些慌神,看了 MySQL 文档发现用 ALTER TABLE 的 CONVERT TO 硬来有点不太行好,遂想到可以试试看 mysqldump,于是做了:

当作 latin1(不然会再按 utf8 编码一次):

mysqldump mt_delphij --default-character-set=latin1 -r utf8.dump

把里面的 CHARSET=latin1 替换为 CHARSET=utf8:

sed -e s,CHARSET=latin1,CHARSET=utf8,g < utf8.dump > utf8.dump.edited

删掉其中的 SET NAMES latin1。


mysql -uroot -p --default-character-set=utf8 mt_delphij
mysql> SET names utf8;
mysql> SOURCE utf8.dump.edited;

还好没用到 zfs rollback。

by Xin LI at 2019-01-02, 07:57 上午

2018 年 06 月 05 日

车东 Blog


1 用 cronolog 干净,安全地轮循apache“日”志
2 用 sort -m 合并排序多个日志
或者用: clfmerge合并日志
1 先介绍apache日志的合并方法;
2 然后根据由此引出的问题说明日志轮循的必要性和解决方法,介绍如何通过cronolog对apache日志进行轮循;



越来越多大型的WEB服务使用DNS轮循来实现负载均衡:使用多个同样角色的服务器做前台的WEB服务,这大大方便了服务的分布规划和扩展性,但多个服务 器的分布使得日志的分析统计也变得有些麻烦。如果使用webalizer等日志分析工具对每台机器分别做日志统计:
1 会对数据的汇总带来很多麻烦,比如:统计的总访问量需要将SERVER1 SERVER2...上指定月份的数字相加。
2 会大大影响统计结果中唯一访客数unique visits,唯一站点数unique sites的等指标的统计,因为这几个指标并非几台机器的代数相加。


webalizer log1
webalizer log2
webalizer log3

因为一个日志的分析工具不是将日志一次全部读取后进行分析,而且流式的读取日志并按一定时间间隔,保存阶段性的统计结果。因此时间跨度过大(比如2条日志 间隔超过5分钟),一些日志统计工具的算法就会将前面的结果“忘掉”。因此, log1<<log2<<log3直接文件连接的统计结果还是:只有log3的统计结果。


log1 log2 log3
00:15:00 00:14:00 00:11:00
00:16:00 00:15:00 00:12:00
00:17:00 00:18:00 00:13:00
00:18:00 00:19:00 00:14:00
14:18:00 11:19:00 10:14:00
15:18:00 17:19:00 11:14:00
23:18:00 23:19:00 23:14:00

00:15:00 来自log1
00:15:00 来自log2
00:16:00 来自log1
00:17:00 来自log3
00:18:00 来自log2
00:19:00 来自log1

%h %l %u %t \"%r\" %>s %b
具体的例子: - - [03/Apr/2002:10:30:17 +0800] "GET /index.html HTTP/1.1" 200 419

cat log1 log2 log3 |sort -k 4 -t " "
-t " ": 日志字段分割符号是空格
-k 4: 按第4个字段排序,也就是:[03/Apr/2002:10:30:17 +0800] 这个字段
-o log_all: 输出到log_all这个文件中

但这样的效率比较低,要知道。如果一个服务已经需要使用负载均衡,其服务的单机日志条数往往都超过了千万级,大小在几百M,这样要同时对多个几百M的日志 进行排序,机器的负载可想而之……
其实有一个优化的途径,要知道:即使单个日志本身已经是一个“已经按照时间排好序“的文件了,而sort对于这种文件的排序合并提供了一个优化合并算法: 使用 -m merge合并选项,
因此:合并这样格式的3个日志文件log1 log2 log3并输出到log_all中比较好方法是:
sort -m -t " " -k 4 -o log_all log1 log2 log3
-m: 使用 merge优化算法

有的系统能处理2G的文件,有的不能。有的程序能处理大于2G的文件,有的不能。尽量避免大于2G的文件,除非确认所有参与处理的程序和操作系统都能处理 这样的文件。所以输出后的文件如果大于2G,最好将日志gzip后再发给webalizer处理:大于2G的文件分析过程中文件系统出错的可能性比较大, 并且gzip后也能大大降低分析期间的I/O操作。



让我们关心一下数据源问题:webalizer其实是一个按月统计的工具,支持增量统计:因此对于大型的服务,我可以按天将apache的日志合并后送给 webalizer统计。WEB日志是如何按天(比如每天子夜00:00:00)截断呢?
mv /path/to/apache/log/access_log /path/to/apache/log/access_log_yesterday
的话:你还需要:马上运行一下:apache restart 否则:apache会因为的日志文件句柄丢失不知道将日志记录到哪里去了。这样归档每天子夜重启apache服务会受到影响。
cp /path/to/apache/log/access_log /path/to/apache/log/access_log_yesterday
echo >/path/to/apache/log/access_log

但cp不可能严格保证严格的0点截断。加入复制过程用了6秒,截断的access_log_yesterday日志中会出现复制过程到00:00:06期 间的日志。对于单个日志统计这些每天多出来几百行日志是没有问题的。但对于多个日志在跨月的1天会有一个合并的排序问题:
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:23:59:59 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]

要知道[01/Apr/2002:00:00:00 这个字段是不可以进行“跨天排序”的。因为日期中使用了dd/mm/yyyy,月份还是英文名,如果按照字母排序,很有可能是这样的结果:排序导致了日志 的错误
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:23:59:59 +0800]
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:23:59:59 +0800]

这些跨天过程中的非正常数据对于webalizer等分析工具来说简直就好像是吃了一个臭虫一样,运行的结果是:它可能会把前一个月所有的数据都丢失!因 此这样的数据会有很多风险出现在处理上月最后一天的数据的过程中。

1 事后处理:
grep -v "01/Apr" access_log_04_01 > access_log_new

修改SORT后的日志:所有跨天的数据去掉。也许对日志的事后处理是一个途径,虽然sort命令中有对日期排序的特殊选项 -M(注意是:大写M),可以让指定字段按照英文月份排序而非字母顺序,但对于apache日志来说,用SORT命令切分出月份字段很麻烦。(我尝试过用 "/"做分割符,并且使用“月份” “年:时间”这两个字段排序)。虽然用一些PERL的脚本肯定可以实现,但最终我还是放弃了。这不符合系统管理员的设计原则:通用性。 并且你需要一直问自己:有没有更简单的方法呢?
还有就是将日志格式改成用TIMESTAMP(象SQUID的日志就没有这个问题,它的日志本身就是使用TIMESTAMP做时间时间戳的),但我无法保 证所有的日志工具都能识别你在日期这个字段使用了特别的格式。

2 优化数据源:
最好的办法还是优化数据源。将数据源保证按天轮循,同一天的日志中的数据都在同一天内。这样以后你无论使用什么工具(商业的,免费的)来分析日志,都不会 因为日志复杂的预处理机制受到影响。

首先可能会想到的是控制截取日志的时间:比如严格从0点开始截取日志,但在子夜前1分钟还是后一分钟开始截取是没有区别的,你仍然无法控制一个日志中有跨 2天记录的问题,而且你也无法预测日志归档过程使用的时间。
1 不中断WEB服务:不能停apache=>移动日志=>重启apache
2 保证同一天日志能够按天轮循:每天一个日志00:00:00-23:59:59
3 不受apache重启的影响:如果apache每次重启都会生成一个新的日志是不符合要求的
4 安装配置简单

首先考虑了apache/bin目录下自带的一个轮循工具:rotatelogs 这个工具基本是用来按时间或按大小控制日志的,无法控制何时截断和如何按天归档。
然后考虑logrotate后台服务:logrotate是一个专门对各种系统日志(syslogd,mail)进行轮循的后台服务,比如SYSTEM LOG,但其配置比较复杂,放弃,实际上它也是对相应服务进程发出一个-HUP重启命令来实现日志的截断归档的。

在apache的FAQ中,推荐了经过近2年发展已经比较成熟的一个工具cronolog:安装很简单:configure=>make=> make install

TransferLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/access.log"
ErrorLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/errors.log"

而2003 2003/01 和 2003/01/01 如果不存在的话,将自动创建

所以,只要你不在0点调整系统时间之类的话,日志应该是完全按天存放的(00:00:00-23:59:59),后面日志分析中: [31/Mar/2002:15:44:59这个字段就和日期无关了,只和时间有关。

#%w weekday
TransferLog "|/usr/sbin/cronolog /path/to/apache/logs/%w/access_log"

重启apache后,除了原来的CustomLog /path/to/apche/logs/access_log继续增长外,系统log目录下新建立了 3/目录(测试是在周3),过了一会儿,我忽然发现2个日志的增长速度居然不一样!
我设置CustomLog使用的是combined格式,就是包含(扩展信息的),而TransferLog使用的是缺省日志格式,看了apache的手 册才知道,TransferLog是用配置文件中离它自己最近的一个格式作为日志格式的。我的httpd.conf里写的是:
LogFormat ..... combined
LogFormat ... common
CustomLog ... combined
TransferLog ...

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
TransferLog "|/usr/local/sbin/cronolog /path/to/apache/logs/%w/access_log"

CustomLog "|/usr/local/sbin/cronolog /path/to/apache/logs/%w/access_log" combined


/bin/cp -f /path/to/apache/logs/`date -v-1d +%w`/access_log /path/for/backup/logs/access_log_yesterday

date -v-1d +%w
-v-1d: 前1天,而在GNU/Linux上这个选项应该是date -d yesterday
+%w: weekday,由于使用的都是标准时间函数库,所有工具中的WEEKDAY定义都是一样的 0-6 => 周日-周六

另外一个问题就是在cront中需要用:rm -f {} ; 而不是rm -f {}\;
5 0 * * * /bin/cp /path/to/logs/`date -v-1d +\%w`/access_log /path/to/for_sync/logs/access_yesterday
37 10 * * * /usr/bin/find /home/apache/logs/ -name access_log -mtime +1 -exec /bin/rm -f {} ;

但这次日志是追加到3/access_log还是重新创建一个文件呢?>>access_log or >access_log?
[01/Apr/2002:23:59:59 +0800]
[01/Apr/2002:23:59:59 +0800]
[08/Apr/2002:00:00:00 +0800]
[08/Apr/2002:00:00:00 +0800]

解决方法1 把每天的cp改成mv
解决方法2 每天复制完成后:删除6天以前的access_log日志
find /path/to/apache/logs -name access_log -mtime +6 -exec rm -f {}\;


#backup old log
/bin/cp -f /home/apache/logs/`date -d yesterday +%w`/access_log /home/apache/logs/access_log_yesterday

#remove old log
/usr/bin/find /home/apache/logs -name access_log -mtime +6 -exec rm -f {}\;

#analysis with webalizer

1 用 cronolog 干净,安全地轮循日志
2 用 sort -m 排序合并多个日志





Cronolog http://www.cronolog.org 已经不再更新



by 车东 at 2018-06-05, 02:48 下午

2018 年 04 月 07 日






by 西乔 at 2018-04-07, 07:21 下午

2018 年 04 月 06 日


PRESSone test




by 西乔 at 2018-04-06, 04:12 上午

2017 年 12 月 08 日

车东 Blog ^ 2


0 代码因素:一些js构造链接打开的模式会造成referer丢失,解决方法是尽量避免windows.open meta refresh等;
1 代码+浏览器因素:meta js打开新窗口 部分浏览器会丢失
2 协议因素:https协议降级http,解决的方法是靠https端增加声明,比如:通过meta的方式:referer meta

<meta name="referrer" content="no-referrer|no-referrer-when-downgrade|origin|origin-when-crossorigin|unsafe-url">

目前搜索引擎https后的页面:Google用的是orgin 百度用的always
或者通过http header的方式,总体来说,这些问题是可以通过代码修复的。

3 多核浏览器切换内核/隐私浏览模式,部分第三方浏览器版本会丢referer,360支持renderer 标签,可以强制使用某种内核进行页面渲染,比如:webkit。
4 浏览器的各种鼠标手势等高级功能,会丢失referer,
5 来自移动app:微信 微博的点击;

2017-12-08, 12:35 下午

2017 年 09 月 02 日

车东 Blog ^ 2



n年没有接触SEO了,最近发现现在的搜索引擎优化已经和以前完全不一样了。 自从各大搜索引擎(Google2011年,百度2015年)https化以后,网站获得自己的搜索来源关键词都变得非常的麻烦,最近几年百度/Google等搜索引擎已经全面取消referer中的关键词传递, 除了搜索自身的网站,实时拿到用户搜索来源关键词基本不可能了。

通过https+取消referer中的关键词传递,可以有效避免电信运营商劫持流量获取用户搜索行为,但本来应该得到用户搜索意图信息的目标网站也失去了这个便利。 如果搜索来源关键词量很大,网站使用百度统计的网站可以通过百度统计的“预定全部关键词”功能来全部导出(百度统计各种前端报表导出一般只能导出1000)数据可以隔天拿到:全部关键词和对应的搜索次数的关键词下载包,需要每天手工下载,百度统计的api目前不支持压缩包的下载。


百度云还有两外一个收费服务:1¥/千次 实时解析referer中的百度关键词:搜索Referer API

2017-09-02, 12:41 下午

2017 年 06 月 06 日

车东 Blog ^ 2


awk -v RS='\r\n' foo.log

Unix 用\n行末结尾
Mac 用\r行末结尾
PC 用 \r\n行末结尾

2017-06-06, 06:16 上午

2017 年 03 月 15 日

Kang Liu


CCIE 10 years

" data-medium-file="https://www.liukang.com/wp-content/uploads/2017/03/CCIE_10_BW.jpg" data-large-file="https://www.liukang.com/wp-content/uploads/2017/03/CCIE_10_BW.jpg" class="wp-image-1222 size-full" src="https://www.liukang.com/wp-content/uploads/2017/03/CCIE_10_BW.jpg" alt="CCIE 10 years" width="150" height="150" />CCIE #17564 Kang Liu

前几天考完了CCIE的笔试做重认证,今天登陆CCIE portal看到可以使用这个可以给“老人”用的新的logo了。是啊,已经10年了……







以前在准备CCIE的时候,曾经在NetPro论坛上看到过这样的一段话,也写下了 Be a real CCIE这个帖子

In most situations, when someone obtain a CCIE, it tells me that person is willing to go through the pain and sacrifice to obtain this achievement and therefore, deserve a lot of my respect

10年前的我,也许没有完全理解这段话,或多或少的只关注到了那些技术和所谓pain and sacrifice。

现在再反思一下10年前的那段经历,除去学习知识之外,更多的是自己主动的走出了所谓的”舒适区/comfort zone”,去挑战自我并创造了更多更大的机会。

10年之前的我想不到10年之后现在自己做的这份工作。再过10年的我呢? CCIE 10年只是个开始,写篇文章小小的记录和庆祝一下,再出发吧!

by kang at 2017-03-15, 12:36 下午

2017 年 01 月 05 日

Kang Liu






Sub Macro1()
 Dim vDirectory As String
    Dim oDoc As Document
    vDirectory = "C:\some_dir\"
    vFile = Dir(vDirectory & "*.*", vbNormal)
Do While vFile <> ""
Set oDoc = Documents.Open(FileName:=vDirectory & vFile)

ActiveDocument.SetCompatibilityMode (wdWord2010)
ActiveDocument.BuiltInDocumentProperties("Author") = "liukang"

ActiveDocument.Range.Font.Name = "宋体"
With ActiveDocument.Sections(1)
.Footers(wdHeaderFooterPrimary).Range.Font.Name = "宋体"
.Headers(wdHeaderFooterPrimary).Range.Font.Name = "宋体"
.Footers(wdHeaderFooterFirstPage).Range.Font.Name = "宋体"
.Headers(wdHeaderFooterFirstPage).Range.Font.Name = "宋体"
End With
With ActiveDocument.Sections(1).Range.ParagraphFormat
        .SpaceBeforeAuto = False
        .SpaceAfterAuto = False
        .WordWrap = True
End With
    ActiveDocument.EmbedTrueTypeFonts = True
    ActiveDocument.SaveSubsetFonts = True
    ActiveDocument.DoNotEmbedSystemFonts = False
    vFile = Dir
End Sub



by kang at 2017-01-05, 02:32 下午

2016 年 01 月 11 日

车东 Blog

拉斯维加斯 CES 2016 观感

1 参加CES的中国厂商: 高调 vs. 平庸 法拉第电动的发布第二天在现场观察了一下:前去拍照的人挺多,很多人也是被前卫的造型惊呆了,听到不少人说:amazing, fantastic,也有人说ridiculous,另外一个比较抓眼球的是载人的亿航无人驾驶飞机。为乐视汽车/亿航的“高调”捏把汗,这些厂商如果今天挖了坑,可能需要国内同行用好几代产品去填。 相比互联网风格厂商的过于高调,中国传统家电厂商普遍缺乏创意:虽然展厅面积越来越大了,但展示的内容很空洞,产品定位相比较日韩厂商完全跟随,没特色。CES的参观者很多都是冲着新概念和开脑洞来的,如果只是把商场的专柜搬过去:就是完全浪费了在主会场的机会,需要订单的不如去参加广交会更好啊。 当然了,个人并非完全赞同互联网背景厂商的策略,但至少他们在CES主会场做了该做的事情,营销上还是及格的。传统家电厂商则完全还停留在去摆摊的阶段。 2 电动车:辅助驾驶 vs. 全自动 / 低速 vs. 高速 电动车分成高速电动车和低速电动车两个领域。 高速电动车和汽车领域在这届展出了大量和自动驾驶相关的技术:自动驾驶今年是热门,但我怎么觉得离得很远呢,或者自动驾驶根本不应该首先是个人使用的目标呢,自动驾驶有可能先在货运领域和全封闭道路环境下实现,而且自动驾驶的基础目前是图像视觉识别和雷达,成本过高,受气候等环境变化的影响太大。而且就算是自动驾驶实现了:也非常担心实际环境中的复杂变数。 更现实的是辅助驾驶/辅助停车有可能会短期内大量普及:类比下自动挡和倒车雷达在家用汽车领域的普及速度。 这次起亚KIA的智能驾驶解决方案挺实用的: 比如盲点区域的物体检测/报警:并线时候检测盲点区域和可能进入的车辆,减少碰撞, 并线报警:如果是无意识下的偏离当前车道会有并线警告; 遇到紧急情况的自动制动:避免追尾; 还有不规范的远光灯使用: 其他车辆灯光靠近后自动关闭远光灯(在某些国家应该强制配备) 根据道路坡度自动调整远光灯角度 相比高速电动车:低速电动车产品因为没有太多安全方面的强监管,反而有更快的进化速度。在滑板车领域:今年NineBot的展台比去年大了10倍:关注尝试的人非常多。通过在便携性,易学性上的改进,相信会比SegWay有更好的表现。能够放进一般汽车后备箱的两轮电动自行车/滑板还会有额外更多的使用场景。 3 VR 裸眼 vs. 头盔 各种全景摄像工具越来越成熟:让VR内容制作成本越来越低。但头盔真的是消费VR内容最佳的方式吗?尤其是家用场景下:一直像盲人一样戴着眼镜恐怕不是一般人可以习惯的。上次在MakerFaire 感受比较好的是理光的一个球幕投影,也许未来会有专用小帐篷来观看VR/球幕内容。 拉斯维加斯开车/停车都不方便,不如Uber、Taxi,虽然散场后叫车/等车非常麻烦。最好还是提前租在会场附近的酒店/民宿。

by 车东 at 2016-01-11, 06:32 上午

1英里 =1760 码 = 5280英尺

闹笑话了,最近在湾区开车的时候用Google地图导航: 导航总是在显示还有0.2英里的时候告诉我,还有1000英尺(我理解是还有200英尺啊)? 明明还有100英尺(我理解是还有0.1英里),怎么立刻就该拐弯了? 这不会是谷歌地图的Bug吧? 后来一查才知道:1英里等于5280英尺,怪不得…… 把1英里当成1000英尺不止我一个吧?

by 车东 at 2016-01-11, 05:57 上午

2015 年 10 月 17 日

delphij's chaos

假设 3721 = x * y,其中x, y 均为整数,则 x+y 最大是多少?


已知 x、y 为整数,由于 3721 是正整数,因此 x、y 符号相同且均不为0。又,题目所求是 x+y 的最大值,故只需考虑 x、y 的正整数解情形。

由 x * y = 3721,令 y = 3721 / x,则 x + y = x + 3721/x。由于 x > 0 且为整数,可知所求为符合条件的 max(x2 + 3721),或 max(x)。

将 3721 开方得到正整数 61。由此可知 x = y = 61 是 xy=3721 的一个整数解。61 是质数,于是很想当然地得到了错误答案 = 61+61 = 122。掉到这个坑里的主要原因是想太多了,实际上题目最终要求的是 x 的最大正整数解,换言之,此类问题:已知C为正整数,C = x*y,求 max(x+y) 的结果应该是 (C+1),不需要任何超出小学算术的计算。本题中的正确答案为3722。

by Xin LI at 2015-10-17, 01:20 上午

2015 年 09 月 21 日

delphij's chaos


razor 同学对于 Xcode ghost 的事情的评价是:这也太不注意卫生了。个人深以为然。

技术细节、影响等等,已经有很多大牛写过很好的文章来介绍。但是我想问的是,这事完了吗?在我看来远远没有,根据有关厂商的介绍,想要装上这个下了马的 Xcode,首先得从 App Store 以外的渠道去下载,其次还得允许运行来自 'Anywhere' 的应用程序,或者开发人员习惯于绕过系统的数字签名检查。

我看到的至少有这么两个问题:1. 开发人员常态化地使用并忽略未经签名的工具(非常不重视卫生,我认为这个事情基本上和一个厨师在上班时间去上厕所,回来工作之前不洗手是一样的性质)。2. 具有这种态度的开发人员同时拥有发布权限(管理者玩忽职守)。

我认为基本上这次出现问题的 iOS 应用开发者都应该进行特别标记,并改进其发布流程之后才允许继续发布新的应用程序。自然,每一个直接导致问题的开发者都是负有责任的,但允许这样问题出现,并在事后用公关稿文过饰非的企业及其管理者更有责任。这种攻击已经持续了数月,到底有多少不同的版本受到影响?也许只有 Apple 能够提供相关数据了。

当然,对于手机应用安全厂商来说,也许这是一次难得的商机,因为 iOS 设备用户和 Apple 之间的信任被这种攻击直接打破了。事实上,国内某前越狱团队已经制作了一款采用企业证书的扫描程序(我并不怀疑该团队提供这样的程序是出于好意,但出于谨慎,个人建议不要使用,因为我们并不知道该团队手中是否拥有更多提权漏洞,或者后续版本是否会做一些其他事情)。


by Xin LI at 2015-09-21, 07:46 上午

2015 年 08 月 30 日

delphij's chaos




OpenBSD 的 spamd 是一个反垃圾邮件陷阱软件,它的主要功能是灰名单(SMTP协议要求客户端在一段时间之内重试投递),但又有一个个人很喜欢的特性:以极慢的速度回应发送垃圾邮件的服务器(默认配置为1秒一个字符,最高可以到10秒一个字符)。对发送垃圾邮件的人来说,这样做会显著地降低他们发出垃圾邮件的能力。

结构上,spamd 会修改服务器上的防火墙的转发规则中的地址,简而言之,是维持一份动态的白名单(由通过了灰名单测试的IP形成),所有不符合白名单的IP都转到 spamd 处理。如果符合白名单,则直接正常转到MTA去处理。


由于我的机器内存够用,所以将 spamd 配置为最大拖住1024个连接。灰名单最短等待期设置为 1 分钟,灰名单过期时间设置为 4 小时;白名单过期时间设置为 36 天。



grep 'Passed CLEAN {AcceptedInbound}' maillog* | \
cut -f3 -d[ | cut -f1 -d] | grep -v : | sort | uniq -c | \
sort -n | awk '{ if ($1 > 20) print $2; }' | sort -n | \
xargs spamdb -a

来将过去几天的 Amavisd 认为没问题的地址加入本地白名单。

最后可以用 spamdb -Ta 来添加一些陷阱地址。陷阱地址是那种故意流出,但绝不应该收到邮件的地址。

by Xin LI at 2015-08-30, 02:22 下午



by Xin LI at 2015-08-30, 02:12 下午


今天的一个偶然的发现。FreeBSD clang version 3.6.1 (tags/RELEASE_361/final 237755) 20150525。clang 3.8 2015/07/20 的版本同样有此问题。

之前, FreeBSD 上 strndup(3) 的实现是这样的:

char *
strndup(const char *str, size_t n)
	size_t len;
	char *copy;

	len = strnlen(str, n);
	if ((copy = malloc(len + 1)) == NULL)
		return (NULL);
	memcpy(copy, str, len);
	copy[len] = '\0';
	return (copy);

而 OpenBSD 上的实现,则是这样的:

char *
strndup(const char *str, size_t maxlen)
	char *copy;
	size_t len;

	len = strnlen(str, maxlen);
	copy = malloc(len + 1);
	if (copy != NULL) {
		(void)memcpy(copy, str, len);
		copy[len] = '\0';

	return copy;

检查 clang 输出的结果,发现 clang 优化后,FreeBSD 版本会比 OpenBSD 版本多一个 xor %eax, %eax (amd64),显然是为了 return (NULL),从而多出两个字节。而 GCC 则将两份源代码编译成同样的结果(因为在这个 if block 中,已经知道 copy == NULL,因此并不需要将 %rax 清零)。

by Xin LI at 2015-08-30, 02:04 下午

2015 年 07 月 28 日

delphij's chaos


今天搞了一个 大新闻。如果你用BIND并且今天之前没打过补丁的话,请读到这里为止,立即去补吧。

我觉得还是得提高知识水平。做 freebsd-update 补丁的时候,赫然发现修改的文件中有一个不认识的:



	libprivatessh.so.5 => /usr/lib/libprivatessh.so.5 (0x800849000)
	libgssapi.so.10 => /usr/lib/libgssapi.so.10 (0x800ada000)
	libcrypto.so.7 => /lib/libcrypto.so.7 (0x800ce3000)
	libc.so.7 => /lib/libc.so.7 (0x8010da000)
	libprivateldns.so.5 => /usr/lib/libprivateldns.so.5 (0x801482000)
	libcrypt.so.5 => /lib/libcrypt.so.5 (0x8016de000)
	libz.so.6 => /lib/libz.so.6 (0x8018fe000)

还用了 Kerberos,等等,ssh?man slogin出来一个SSH的manpage,一个字没提slogin的事情。

ls -li一看才恍然大悟:

4574 -r-xr-xr-x  2 root  wheel  179000 Jul 19 00:19 /usr/bin/slogin
4574 -r-xr-xr-x  2 root  wheel  179000 Jul 19 00:19 /usr/bin/ssh


by Xin LI at 2015-07-28, 10:15 下午

2015 年 07 月 09 日


New Beginning


It has been a while since my last post. A lot has happened. The most important one is that I have come back to China to join the fruit company everyone loves or hates.

It’s a new beginning for me, almost three years ago I joined Opera to build their new Mac browser from scratch. It’s an opportunity that few programmers could ask for. I met some incredibly talented colleagues and became really good friends with many of them. To sum up, the jump to Opera is a decision I will never regret.

But that’s a small jump compare to the one I just made. After moved to Norway for five years, I’m moving back to Beijing for a new job.

After working on desktop UI programming for a while I realized that I still prefer lower level work involving frameworks and APIs. I still love working on text and fonts in particular. Fortunately, this new job is exactly about those stuff.

Of course, the job is not supposed to be easy and being remote for a while is going to be tough. But I’m still positive about this new beginning. We will see.

by jjgod at 2015-07-09, 02:28 下午

2015 年 07 月 06 日

delphij's chaos


phk 老大如此 吐槽

One week until the leap-second. If you haven't tested your IT-system already, it is too late now. Good luck if you're in California or Japan.


关于时间,A core 几年前写过一个 时间是什么? 的系列: 序言 续一 续二 续三

为了兼顾天文观测获得的时间 UT1 (更符合普通人的需要)和由铯-133原子震荡获得的时间 TAI (更稳定),将两者综合一下就获得了协调世界时 UTC。UTC 和 UT1 之间的差距永远保持在 1 秒以内。UTC 中的一秒和 TAI 相同,但 UTC 和 UT1 保持最多一秒的差距,这是通过 IERS 在 UTC 事件中人为插入或减少闰秒这样的人为调整来实现的。从1972年这套系统投入运营到今天为止,总共插入了35个闰秒(2015年6月30日还将再插入一个闰秒)。

闰秒只在每年的6月30日和12月31日的UTC时间 23:59:59 之后插入,表示为当天的 23:59:60。


Unix 时间是从 UTC 时间1970年1月1日0时0分0秒起的秒数,但不计入闰秒。这一定义后来又被 POSIX 继承并成为了标准。由于 Unix 时间没有考虑闰秒,因此如何表达闰秒在 POSIX 中是没有定义的。换言之,UTC 时间 2015年6月30日23:59:59的Unix时间是1435708799,2015年7月1日00:00:00的Unix时间是1435708800,两者之间的这个闰秒,根据标准就只能用两个时间之一代替了。很明显,这样一来,在闰秒本身或它后面那一秒,在 Unix 时间戳看来就是完全一样的了。)

这会带来什么问题呢?假如我们令 23:59:59 = 23:59:60,那么如果有事件 A、B 分别发生于 23:59:59.2 和 23:59:60.1,则在 Unix 看来,B发生在A之前,而实际上应该是相反的结果。这样一来,一些程序,例如 POSIX 线程库中某些等待时间采用的是绝对时间,由于闰秒的原因,这些等待可能会提前或推后1秒才会唤醒。又比如,依赖于文件时间戳的应用,如make等,可能会误认为某些文件的修改时间发生了倒序问题,而将已经联编过的文件再联编一遍。一般来说,这些都不至于导致太大的问题,但假如应用依赖于精确的时间,而同时又假定时间戳不会重复的分布式系统来说,这个问题就可能产生比较严重的后果了。


如果内核支持,NTP 在发现闰秒时,将向内核宣示这一现象(STA_INS 或 STA_DEL),并由后者进行适当的处理。内核的状态机将经历 TIME_OK -> TIME_INS -> TIME_OOP -> TIME_WAIT -> TIME_OK 的变化。在 FreeBSD 的实现中,CLOCK_MONOTONIC 的时间戳将持续前进,CLOCK_REALTIME 的时间戳在 TIME_INS 到 TIME_OOP 状态变化时将倒回前一秒。


对于没有使用 ntp/ptp 的机器来说,由于它们本来也无法精确计时,因此自然也就无所谓闰秒了。事实上,这些机器很可能完全不知道闰秒的存在。

对于使用了 ntp/ptp 的机器来说,时间戳可能会出现绕回现象。Google针对闰秒的对策 中提到,他们将引入一个基于余弦函数的调整量(1.0 - cos(pi * t / w)) / 2.0,其中w是闰秒的延展时间。利用余弦函数在0、pi两点的导数为0的特性,这一做法可以避免出现跳变。在延展窗口内,系统时钟由于这种调整被人为变慢。这种做法避免了由于时间戳绕回现象导致的问题,但会导致 Unix 时间戳在某个时间段内不准,不过考虑到反正它也不准(因为符合POSIX标准就不能表示闰秒了)所以似乎也就只能大丈夫了?

另一种比较常见的做法是使用 ntpd 的 -x 参数,不过与Google的做法相比,这种做法引入的随机性更大(Google的做法,整个w周期内的时间戳是点点连续且单调递增的)。

by Xin LI at 2015-07-06, 10:07 下午

2015 年 06 月 23 日

delphij's chaos


作为十几年的 tcsh 拥趸,我最近改信了 zsh。

基于 Robby Russell 的 Oh My ZSH 搞了一套自己的 Oh My ZSH,可以用 ZSH_THEME="delphij" 来启用我的配置,其外观、行为大致与我之前的 csh 配置相同。

经过PGP签名的tag版本可以在 这里 找到(请自行使用安全的方法获得我的PGP公钥)。


$ ZSH=~/.oh-my-zsh
$ git clone --depth=1 --branch=delphij-20150522 https://github.com/delphij/oh-my-zsh.git $ZSH
$ cd $ZSH
$ git tag --verify delphij-20150522
# 以上复制一份tag过的 Oh My ZSH 并验证其签名。
# 如果有之前的.zshrc请自行备份。
$ cp $ZSH/templates/zshrc.zsh-template ~/.zshrc
$ sed -i '' -e "/^export ZSH=/ c\\
export ZSH=$ZSH
" ~/.zshrc
$ sed -i '' -e "/export PATH=/ c\\
export PATH=\"$PATH\"
" ~/.zshrc
# 以上使用模板覆盖.zshrc并复制已有的PATH配置。
chsh -s `which zsh`
# 将shell改为zsh

需要注意的是,由于 zsh 并非系统自带的 shell,因此保留一个非 zsh 的 root 账户会是个好主意。

by Xin LI at 2015-06-23, 03:03 下午

2015 年 05 月 29 日

delphij's chaos


对口相声选段:Node.js Is Bad Ass Rock Star Tech。视频:

p1: And in conclusion we have found Apache to be an excellent server for our web applications. Any questions?

p2: Yes, I have a question. Why didn't you use node.js? node.js is an event driven, non-blocking IO server that can be used to build high-performance web applications.

p1: That is an excellent question. We evaluated several alternative web servers and concluded, that while options like node.js are very interesting, Apache meets our needs and has a solid track record.

p2: But it doesn't have performance. Everybody knows that Apache applications are slow because they use blocking IO and have context switches.

p1: That's a commonly held belief that threaded web servers are somehow less performant or as scalable than event based servers. In fact, if you measure carefully, you will find that both models have similar performance characteristics.

p2: Threads don't scale. Simple as that.

p1: That may have been true 10 years ago. Its not true today.

p2: node.js will run circles around Apache because Apache was built before asynchronous was discovered.

p1: This is where I typically stab myself repeatedly in the ears with a fork until I stop hearing you. I've looked at node. It uses a single threaded loop that dispatches events to handlers. Its a proven model that solves some concurrency problems but at the cost of code complexity.

p2: It gives techies like me the control to wring every last CPU cycle out of our servers.

p1: It must feel empowering to be totally responsible for the performance of your application. To be always on the lookout for blocking operations that should be split into little pieces each perfectly tailored for concurrent throughput. All the complexities of assembler with all the speed of JavaScript.

p2: I'm a total speed junkie

p1: Do you know what this reminds me of?

p2: The invention of the transistor.

p1: It reminds me of the invention of threads. Threading libraries do exactly what your doing manually. They break up pieces of code to be executed intermittently, switching from instructions that are waiting on IO to instructions that are ready to run, but your sequential code stays intact. You may recall sequential code. Its the code that you can read.

p2: But its slow as a dog

p1: Your asynchronous program is like something from a 19th century Gothic horror story. Drunk with your own sense of power, you reassemble pieces of code that were once coherent, stitching them together with event loops and callback functions, until your monster, grotesque and menacing, is ready to be brought to life in a JavaScript VM. You throw the switch and the hideous creature awakes, rises, and lurches forward. you're simultaneously elated and terrified that something so unnatural code work at all. When you realize what you've unleashed, the pure immorality of it, your creation reaches out with its bloody, mangled arms, and strangles you.

p2: But its fast as hell

p1: If your willing to suffer complex code for performance, why not write an nginx module and see?

p2: node.js is the most bad-ass rock-star tech to come out since Ruby On Rails.

p1: As much as I want to be an optimist and look forward to human progress, people like you make stop me dead in my tracks. Your a fanatic in the church of technology fashion. I could present you with fact after fact after fact of why your thinking of asynchronous programming is completely wrong. But why bother when you equate technology to rock bands, and fancy yourself a software hipster by wearing your node.js t-shirt and celebrate horrible code. Maybe your cool, hell, maybe you have groupies. But when it comes to knowing what the f*ck you're talking about, you have the facilities of a parrot who says "non-blocking" over and over again.

p2: Non-blocking is the secret in the asynchronous sauce. With it, you go fast. Without it, you go slow.

p1: Do you know when humans discovered that the world was round?

p2: 1492. Columbus sailed the ocean blue.

p1: It was 240 BC by a Greek mathematician named Eratosthenes. He conducted a simple experiment using the length of shadows and the distance between cities to not only prove the earth is round, but to also calculate its circumference.

p2: Sounds low-tech.

p1: It was utterly brilliant. But somehow, for one and a half millenia, it was common knowledge that the earth was flat. Hundreds and hundreds and hundreds of years in daft ignorance. How in mother-f*cking hell does this happen?

p1: It was you. You who makes claims about thread performance without measuring. You who claim hacking your code with a machete, turning it inside out into a twisted, unrecognizable mess will somehow make it go faster. You, who spend your time alternating between problems that are already solved and problems that don't actually exist. You are the reason science was set back 1,000 years. The reason we have not cured cancer. The reason we have not solved world hunger.

p1: Its because of you, mother f*cker, that we are not all using Lisp.

p2: I'm sorry, what was that last part again?

p1: Never mind.

p2: Did you just say Lisp?

p1: You misheard me.

p2: I could've sworn you just said lisp.

p1: If there are no other questions, this concludes my presentation.

by Xin LI at 2015-05-29, 08:23 下午

Powered by Planet! run by Xin LI [homepage, blog] using template $Phantasm: delphijweb/planet_cron/delphij/index.html.tmpl,v 1.22 2010/03/29 23:40:04 delphij Exp $
Last updated: 2019-12-24, 07:46 上午