Another afternoon wasted: How to choose two fonts with fontconfig

After upgrading to Ubuntu 16.04, the font in my GNOME is a mess (again). So I spent another afternoon trying to figure out how to choose the fonts I need using fontconfig.

This is what I achieved using Source Sans Pro and Source Han Sans CN. The default was to use DejaVu Sans and SimSun.

My goal is to use two fonts, an English one for displaying generic characters, and a Chinese one for, um, Chinese. Although I can use a single Chinese font for both, but the English characters displayed in Chinese font is disastrous. So basically I want to tell fontconfig to use the two fonts in a preferred order: Use English one wherever possible, and fallback to the native one when the former can’t do the job.

Actually I have solved this before, but I forgot what I did back then. So I had to spend another afternoon Googling and reading their long and non-standardized docs on how to express my request in their weird XML tags. After several attempts, I found that the following configuration works just fine.

The whole XML below should be saved as ~/.config/fontconfig/conf.d/99-xiaodu.conf (create non-existent folders when needed), which is the preferred location for user-specific fontconfig files.

Basically this file tells fontconfig, when the locale is zh-cn (Chinese), it should to prepend the two fonts (English and Chinese) to the matching list; otherwise just prepend the English one.

Notice that the first font in each <edit> block is the English font, where the second is the native font. You should replace the language code (RFC3066 style) and all six font names using your favorite text editor, with respect to the fonts’ types (sans, serif or mono). If you want to test your work, use fc-match with something like $ LANG=zh-CN fc-match -s sans | head -2.

I just hope one day there would be a nice GUI for all this crap.

中文摘要:这篇文章介绍如何在 Ubuntu 中通过配置 fontconfig 同时选择要使用的英文和中文字体,使用英文字体显示一般字符,中文字体显示中文字符。

回忆一下 360 实习编程题


1. 两个人A、B,从一个整数范围(说是N,目测是[1,N],题出的非常模糊)里面各选一个数a和b,然后用一个均匀随机生成器在范围里生成一个数c,看谁离c近赢,相同距离算b赢。


样例:3 1 (输出2)、4 3 (输出2),完美的避开了是0还是1开始的问题……

</题干> 卤煮做了40%(还做出过20%,应该是5个点),还想出一个边界条件没写对,不知道剩下的错在哪里。

2. 给定字符串s,由a~z和小数点“.”组成,定义操作a(s),表示将s中最早出现的连续两个点替换成一个点;定义函数f(s),表示进行多少次操作a可以使得字符串中没有连续的点。


样例:原来的巨长无比,我就随便编一个:4 1 a..b 4 . (输出2)。

</题干> 水题,只要注意是1开始这个大坑。读入后先计算原始的f(s),然后每次操作后,拿出操作位左右各一位,判断这三位在变化前后的diff,加到原始f(s)即可(当然,过后要真的替换)。




Prevent a package from being installed on Ubuntu / 在 Ubuntu 系统中阻止安装某个软件包

This article shows how to prevent a certain package from being installed, manually or as a dependency, on Linux systems using apt (apt-get) like Ubuntu and Debian.
这篇文章介绍如何在使用 apt (apt-get) 的系统上(例如 Ubuntu 和 Debian),防止某个软件包被安装,包括手动或被依赖。

It utilizes the “pinning” feature of apt, which you can read about in detail with man apt_preferences .
使用的原理是 apt 的 “pinning” 功能,可以通过  man apt_preferences 获取详细文档。

  1. Say we want to block “ttf-mscorefonts-installer” from being installed, which is a recommended dependency of “ubuntu-restricted-extras”. When we use  apt-get install ubuntu-restricted-extras , the package will be automatically installed. If we use the “–no-install-recommends” switch, many other packages will be ignored, but we just want to block that one specific package.
    假设我们不想安装 “ttf-mscorefonts-installer” 软件包,但它是 “ubuntu-restricted-extras” 的推荐依赖。如果我们使用  apt-get install ubuntu-restricted-extras 命令,则依赖软件包也会自动安装。我们可以用 “–no-install-recommends” 开关阻止推荐依赖,但是同时会阻止其它很多软件包。接下来的方法适用于只阻止特定的一个软件包。
  2. In the folder “/etc/apt/preferences.d” we create a plain text file “block-package”, with the following contents:
    在 “/etc/apt/preferences.d” 文件夹中创建一个文本文件 “block-package”,内容如下:
  3. With a negative priority, the package will not be installed either manually or as a dependency when using apt-get.
    由于设置了负优先级,在使用 apt-get 时,这个软件包无论手动还是依赖都不会被安装。


Debugging random lagging on Android

My Samsung tablet with Android (4.4.2, rooted) has been experiencing random lagging for a while. This affects me most when I’m playing games on it. Earlier today I finally decided to find the root of the problem.

Finding the cause

The ultimate solution is to know which application is causing the lag and disable it. I first went to Settings > General > Developer Options (If you don’t have it, go to Settings > General > About phone/device and tap “Build number” 7+ times to enable it), and ticked “Show CPU usage”. Then you would see an overlay on the top-right corner of your device showing the top (like the Linux command) processes, similar to the image below.

Then I used my device to play games, and wait for the random lagging to happen. When the device start to response slowly, I watched the CPU usage overlay and see “gzip” topping the list. If you are not familiar with Linux, gzip is a compression tool similar to RAR or 7-Zip.

Wrapping (first attempt)

I was expecting some Android application to cause the lagging, instead it’s a command gzip that can be called by anyone. The problem became finding out who called it. Since my device is rooted, I decided to replace the original gzip binary with a wrapper that can log who called it before actually gzipping. Here is the wrapping bash script I used (first version, read on for second version):

The script does the following: (1) Log the time, user ID (the $EUID variable turns out to be useless, but id worked) and command line parameters to $LOGFILE (a plain text file in the internal storage); then (2) hand over the control to real gzip so that it doesn’t break the gzip functionality.

Then I used Root Explorer to rename /system/bin/gzip to /system/bin/gzip.real, and put my script to /system/bin/gzip (remember to modify the permission to be the same as gzip.real, usually 0755).

After using the device for a while and several lagging happened, I read the logging file and got these lines:

Observe that id produced “uid=2000(shell) gid=2000(shell) ...” and the command called is “gzip -6“. This means gzip was called by the shell user, not a specific application, and the data to be compressed was piped in to gzip and then piped out, since there are no input or output file names. (Spoiler: Actually this has shown “context=u:r:dumpstate:s0” which indicated that it was called by “dumpstate“, but I didn’t realize for the first time.)

Wrapping (second attempt)

Then I decided to take the surveillance up a level, and used the following wrapper in place of the first version:

The difference between it and the previous one is that, it uses Busybox’s “pstree” command to output the process tree of that moment, and “tee” command to record the data piped in and pipe it out again. In order for this to work, I downloaded busybox-armv7l binary (my device has ARMv7 architecture) from the official website and put it to /system/bin/busybox0 with the same permission as gzip.real. You can also use Busybox installer apps and modify the busybox path accordingly.

After a while, I got the following log this time:

Observe that [8691] is the gzip wrapper’s PID, and it’s called by “dumpstate“, which is then called by “debuggerd“. The wrapper also logged the data to be compressed, which is 5 MB long and takes 0.14s to be compressed on my PC instead of a poor mobile device.

Final solution

A quick Google told me this is for developers to debug the system state, and since I’m not a developer in this area, I decided to disable it once for all. This is done by using Root Explorer to revoke the execute permissions from the two binaries /system/bin/{debuggerd,dumpstate}.

Now the lagging is gone.


题注:本文记录的是一项发生在 2015 年 8 月的真实事件。博主是原版 Shadowsocks 用户,下面原文的全文可以在文末的地址看到。无论读者是出于因为什么原因看到这篇文章,是 Google 搜索的还是听人忽悠来的,请搞明白文章的背景。另外,希望读者能保持一定的理性,不要“精虫上脑”、一听到“妹子”就管不住自己。互联网上一条狗也可以假装是妹子

因为这篇文章引来的麻烦浪费了我太多时间,本文关闭评论并不再更新。想 DDoS 攻击的请便,反正已经用上了 CDN。有些人傻呵呵的以为自己“攻击”了几个小时,其实服务器才用了 1Mbps 的带宽,建议不要浪费绳命,让自己投入到更有意义的事情中。

16.12.25 更新:说好不更新的,结果还是更新了,堕落到跟某些**一样的水平。

看看这智商真捉鸡啊!正常人都能看懂上面一段斜体的因果关系:因为删一些脑残粉的评论太烦,所以关评;因为被人 DDoS,所以上了 CF。分开两句话的内容也能合成出“正义使者攻击反动网站,博主胆小如鼠关闭评论”的大标题,跟官媒学的这一套也是可以的。还真把自己当什么大V,让脑残粉群起攻之,胆小如鼠的博主都真的笑、笑出声了。

最后加一句:原版 Shadowsocks 软件并没有停更,而且也加入了某些反检测、反攻击的新特性。你们教主很多代码也都是直接 merge 过去的,点开 Commits 就能看到了。要用哪个版本是每个人的自由,但是请不要歪曲事实。还是开头那句话,只是记述真实事件,供参考。

个人建议使用原版 Shadowsocks 软件,比较安全。

以下内容,黑色为 ShadowsocksR 作者的原文,蓝色为本博客(微博 @_小噗)的评论。

背景:某作者([email protected])用了[email protected]的shadowsocks-csharp(现在叫shadowsocks-windows)的代码,原始代码是GPL的,然而新作者发布了二进制但不开源,原作者吐槽了一下,新作者发了这么一篇然后撂蹶子走了。



另外,如果你发现某个需求是很有必要的,但和作者说了这个需求但作者不做,和你说“NO”,怎么办?(好问题,接着看)正如三个月前我就和作者说过UDP功能很有用,但作者就说PC上用UDP不如路由器上做。结果呢,那就自己做一个,把功能实现出来,(到这为止都说的非常好呀)把其它人的需求也引发出来,进而通过市场压力迫使作者把这个功能做出来就行了。(哈哈哈哈哈,为什么作者一直在说“市场压力”呢,我们继续赏文)但是你说你不会写代码,或者你写的实现不太好?没关系,我也是新手,我读的经济学,(当当当当!揭晓了!)我不是程序猿,开始动手改代码前我的C#才学了一星期,连select模型是啥也不知道,就算现在也不知道epoll是什么玩意儿,写的代码只能让机器能跑。你要是觉得和我联系也没有问题的话,那就发邮件到mmgac001[at]gmail[dot]com (诚心的打码)



1. 最大的亮点,你给作者说了需求作者不做,你该怎么办?是的,如果对你很重要,你就自己做一个,这个是完全正确的。下一步,最好的做法——把你的代码PR给上游!如果你很懒,如果你不会(学经济的嘛),你就把它开源到你的GH上,让作者自己来merge!可是这位经济老兄,不但不开源(GPL violation),还要“市场竞争”,要“逼迫”作者更新……简直亮瞎了朕的狗眼,你说腾讯用了ffmpeg然后违反协议被挂在官网,那是因为怕竞对抄袭,您老这软件也不要钱,用您自己的话说,学了一个周csharp,我感觉写出的代码也就那样,有什么值得背负千古骂名闭源的?最大的可能就是,作者根本不懂开源、git、github这一套,就是小孩子心理自己做了一个方案然后挂出来炫耀而已了。(还有幸被某知名SB博客推荐了一下……于是才有了这一套事。)本噗的建议,外行想掺和开源这一套是好的,但是先把基础知识学好,不是随便写个代码发出来就是造福人类的,你只造福了用你软件的那点儿人,但是让上游作者很心痛。

2. 作者在文中说要切换到“比TCP更安全的协议”,在issue#28里说发现了ss协议的漏洞。虽然我没认真的看过ss协议,但是基本就是对IP层和TCP/UDP层的简单包装。作者可能不是科班出身,不知道现在国际上用的上网协议就这两种……TCP/UDP over IP……接下来,还是那句老话,发现了漏洞为什么不提出来呢?为什么非要在自己的闭源软件里实现呢?今天可以闭源发布客户端,明天就可以在里面加个病毒“造福”你的用户呀,这就是市场嘛。


更新:有人给我指出,四层还有个“SCTP”……只想说,grow up吧孩子……任何人只要乐意,都可以在四层自己发明一个协议,你甚至可以在三层发明个IP协议的替代品,然后自己搭个全球互联网……然而操作系统不支持有个卵用啊……