Nginx根据Accept-Language的简繁体支持

这个功能开启很久了,但直到昨天才发现遗漏了atom.xml……

我想根据HTTP首部的Accept-Language决定提供简体或繁体的文件。在Chrome中,chrome://settings/languages可以设定偏好语言,浏览器会据此设置Accept-Language首部。较好的处理方式是解析该字段,获取qvalue,根据优先级选取最恰当的语言。但仅用于支持简繁体,我想用取巧的办法:忽略优先级,只要Accept-Language里出现了zh-Hantzh-TWzh-HK等字样,就返回繁体,否则返回简体。

Read More

指定dynamic linker以使用高版本GCC

今天有人问怎么在没有root的不可更新老旧Linux环境里使用高版本GCC,主要困难在于GCC对glibc版本有一定要求。假设使用现成的GCC二进制包,解压到本地后执行gcc,报错:/lib64/libc.so.6: version `GLIBC_2.14' not found,即系统glibc的libc.so.6中缺乏更高版本的符号(参考info '(ld) VERSION')。使用新符号通常表示API有更新,不过很多时候旧版本的库也能用,可能有两个原因:一是编译机器的库版本可能较新,soname版本号较高,编译出来的可执行文件也会有较高的版本要求;二是源文件因保守指定了较高的版本号,实际上旧版本也能用。

比如最近ncurses主版本号更新到6,/usr/lib/libncursesw.so.5变成了/usr/lib/libncursesw.so.6,导致很多可执行文件没法用了:

Read More

皈依Emacs

这应该算第三次使用Emacs了。第一次是在2009年,NOI 2009酱油后下决心好好学习Linux,Philip Xu前辈我指引了两天,发现Linux这个未知世界竟然有这么多好玩的软件。编辑器之神Vim用了一阵子了,NOIP 2009前若干天开始探索神的编辑器Emacs,使用Emacs Lisp配置,实现与Vim相似的设定效果需要多出好多代码,因此不久又回到Vim。大概2010下半年又用起Emacs,这次好好折腾了一把。当时Vim的插件生态还围绕vim.org(现在逐步转战GitHub了),Emacs倒是有个http://www.emacswiki.org,尝试了Mew、ERC、AUCTeX、haskell-mode、org-mode等好多东西。很多文件类型的解析、自动缩进支持比Vim对应物好不少,插件质量感觉也稍高。

Read More

J语言初探

先看些例子,感受一下J的魅力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+/\ i.6 NB. prefix sum of 0~5
0 1 3 6 10 15
(+/ % #) 2 3 4 5 NB. mean
3.5
*/~ 1+i.9 NB. multiplication table
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
({.;#)/.~ 'abbccc'
┌─┬─┐
│a│1│
├─┼─┤
│b│2│
├─┼─┤
│c│3│
└─┴─┘

Read More

一次服务器BMC固件逆向经历

导出文件

访问BMC默认开启的Web管理界面http://$ip,开启ssh服务,之后即可以执行ssh root@$ip,得到一个受限的管理界面,功能很少,没有系统shell。

在服务器上执行ipmitool fru可以查找到设备型号,使用厂商提供的flash备份工具导出flash,比较慢,每秒200多KB。在BMC网页界面的BMC System Audit Log中看到BMC的Linux系统日志:

Read More

常数空间Invert Binary Tree与仿Morris法后序遍历

今天在地铁上浪费了好多时间……呜呜……做其他事都没有效率,就利用这些时间写字了。

前几天LeetCode的Invert Binary Tree火了。名称有点糟,无法准确描述要求。

主要思路是遍历二叉树,把访问操作修改为交换左右孩子,每个节点都交换一次即可。

如果采用前序或中序遍历,则子树交换发生在遍历某棵子树之前,会引起麻烦。因此我想到了后序遍历,在遍历完子树后再交换左右孩子,重心就是如何实现常数空间复杂度的后序遍历。某些资料/问题称之为Morris post-order traversal。

Read More

jq实现原理——字节码

jq所用的DSL是一门dataflow language,程序中编写的几乎所有结构都是filter,函数(比如def foo(f) f;)接受filter为参数,产生filter。jq程序描述了如何把各个filter组合起来产生更复杂的filter,在执行时把输入数据(若干JSON)变换得到输出(若干JSON)。

jq独特的地方在于它的控制结构是由if和backtracking实现的。由于变量赋值后不可修改,因此迭代无法通过跳转和可变状态实现。

jq把程序编译成字节码后解释执行。字节码是栈式的(参看后缀表达式计算器、Forth),处理的值是JSON,执行时当前结果和临时变量等都存放在data stack上,并提供了很多指令用于处理data stack。下面用$s$表示data stack,左边是栈顶:

持续更新中

Read More