4
17
2017
22

局域网中通过 TUN 和软路由实现链路聚合

可怕,都两年没写东西了……

背景

前段时间奉老板命为实验室搭建 Linux 计算集群。之前实验室跑计算都是直接远程登录机房的 Windows 主机的,完全没有作业调度。听说要搞个 Linux 集群我还是蛮有兴趣的。(怎么又搞运维)

然而,实验室当初显然没有按照集群的配置来采购硬件。起步的其实只有三台计算用的服务器,没有配置存储服务器和网络设备。最初我是想至少添加一台登录+存储用的服务器吧,不然这个集群的拓扑实在有点坑。不过学长和老板觉得先用现有硬件搭建一个看看吧,所以我就拉了个旧主机将就着当登录节点了。既然如此,也没必要怂恿实验室加上万元添置 RDMA 模块了,搞个便宜的千兆交换机凑合着用就行了。

未名实验室的集群就基于这套不怎么专业的设备搭建起来了。为了充分榨干这一套设备的性能,后期我在文件系统、网络、软件配置等方面做了很多优化尝试。其中一个想法是:

集群中每台计算节点都装了四块千兆网卡,是否能够将所有网卡都利用起来,组成一个“四千兆”网卡,提高带宽?

警告:本文作者计算机网络课划水太多,文章充斥着大量非专业表述,请谨慎参考。

讨论

广义地讲,同时利用多个物理网卡发送/接收 packet,以提高网络带宽(突破单网卡带宽)和可用性的技术,都叫做链路聚合(Link aggregation)。

在网络协议栈中,不同层面都可以实现链路聚合:

  • 物理层(layer 1):Wifi 一根天线信号不好,装两根(胡诌的);
  • 数据链路层(layer 2):Linux 下的 Ethernet Bonding;
  • 网络层(layer 3):操作路由,以数据包、连接或者目的主机为单位将包分散在多个端口上发送/接收,如 ECMP 以及后面会讲的软路由方法。
  • ……

每种方法都有适合的应用场景,并行的粒度也不一样。比如说,作为一台网页服务器,要和世界各地大量的主机建立连接,改一改路由,让某些地区的连接走端口A上绑定的IP访问、另一些地区走端口B上绑定的IP访问,就能够均衡负载并且提高总带宽了,虽然单个连接还是不能突破单网卡带宽。

而我更在意的是局域网中两台机器之间的通信,希望单个连接也能够突破单网卡带宽。比如,集群两台机器之间要通过 NFS 或者通过 SSH 拷贝数据,我希望能够通过四块网卡的聚合达到 500MB/s 的传输速度。

此外网络拓扑也得明确一下:所有主机通过一台无网管千兆交换机相连。背板带宽足够大,不会成为瓶颈。

各种方法

先约定一下标记。假定我们有三台 Linux 主机(HostA、HostB、HostC),然后每台主机分别有两块网卡 eth0 和 eth1。三台主机的 eth0 上绑定的 IP 分别为 10.0.0.10/24、10.0.0.20/24、10.0.0.30/24;eth1 上绑定的 IP 分别为 10.0.0.11/24、10.0.0.21/24、10.0.0.31/24。

Ethernet Bonding

Ethernet Bonding 是 Linux 内核支持的一种将多块物理网卡组合成一块逻辑网卡的技术。IP 绑定在逻辑网卡上,链路聚合是在数据链路层进行的。

网上有很多资料,不再赘述了。比如:

对于几种以提高吞吐量为目的的 bonding 模式(比如 balance-rr),发送包是打散到每个物理端口上的,但接收包的负载均衡是通过不断发送 ARP 广播将 IP 绑定到不同端口实现的。由于 MAC 协议的限制,同一时刻一台主机上 MAC 表中某个 IP 只会对应到一个端口,发送到这个 IP 的包也只会涌向一个端口(虽然是从两个端口发送的)。因此,bonding 不能实现我需要的链路聚合。

ECMP 和 软路由

Equal-cost multi-path routing(ECMP),等价多路径路由,简单来讲就是为同一个目的地址配置“多个”“等价的”路由。

比如添加两个 ECMP 路由,使得到 10.0.0.0/24 可以走 eth0 和 eth1 两个端口出去:

ip route add 10.0.0.0/24 nexthop dev eth0 nexthop dev eth1

或者,要经过多个默认网关接入 Internet:

ip route add 0/0 nexthop via 网关1 dev eth0 nexthop via 网关2 dev eth1

Linux 内核根据报文源/目的 IP、源/目的端口(UDP/TCP)进行 hash 决定使用哪条 ECMP 路由发包(参考资料)。因此,至少对于一个 TCP/UDP 四元组,路由是固定的。另一个问题是,ECMP 只是决定发包的路由,不能做到接收包的负载均衡。如果要做收包的负载均衡,则需要发送方也配合、向两个端口发送。

由于我所有设备的所有端口是在一个局域网/交换机下,路由直接由 ARP 表决定了。同一时刻一个IP只能对应一个MAC,接收包只会从一个端口进来。所以只加入上面的 ECMP 路由、不做进一步配置的话,目前的效果是:

  • 发包能够突破单网卡带宽,但必须建立多个连接(使得 ECMP hash 不同)
  • 单 IP 收包还是只能从一个端口进来,不能突破单网卡带宽

所以,前面这样做 ECMP 还是没法实现我需要的链路聚合。

改进1:接收包负载均衡

其实,前面说的“同一时刻一个IP只能对应一个MAC”并不完全正确,其实每个网卡都有一个单独的 ARP 表。比如,可以通过 ip neigh show dev enp5s0 查询 enp5s0 上的 ARP 表。

这有什么意义呢?如果我们能让不同网卡拥有不同的 ARP 表记录:HostA 的 eth0 认为 10.0.0.20 在 HostB 的 eth0 上,HostA 的 eth1 认为 10.0.0.20 在 HostB 的 eth1 上…… 反之 HostB 看 HostA 亦然。这样,在做到发包的负载均衡的同时,也能够做到收包的负载均衡了。

怎么让不同网卡拥有不同的 ARP 表记录呢?最简单的方法是…… 多买几个路由器,把一组网卡(比如所有主机的 eth0)隔离在一个广播域中。不过,也可以用静态 ARP 表完成这件事:

arp -i eth0 -s 10.0.0.10 <MAC of HostA's eth0>
arp -i eth1 -s 10.0.0.10 <MAC of HostA's eth1>
arp -i eth0 -s 10.0.0.20 <MAC of HostB's eth0>
arp -i eth1 -s 10.0.0.20 <MAC of HostB's eth1>
arp -i eth0 -s 10.0.0.30 <MAC of HostC's eth0>
arp -i eth1 -s 10.0.0.30 <MAC of HostC's eth1>

虽然乍一看有点难以维护,但实际上如果端口数量完全一样,所有主机使用同一份 ARP 表就行了。

改进2:以包为单位进行负载均衡

ECMP 的负载均衡“粒度”不能满足我的需求。其实以包为单位的负载均衡非常容易做的:用 iptables 给发包随机或者依次打上 1、2、…… N(N 为网卡数)的标记;然后设定策略路由,根据标号选择路由就好了。

iptables -t mangle -A OUTPUT -d 10.0.0.0/24 -m statistic --mode nth --every 2 --packet 0 -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -d 10.0.0.0/24 -m statistic --mode nth --every 2 --packet 1 -j MARK --set-mark 2
ip rule add fwmark 1 table 10000
ip rule add fwmark 2 table 10001
ip route add 10.0.0.0/24 dev eth0 table 10000
ip route add 10.0.0.0/24 dev eth1 table 10001

不过还没完,Linux 内核有一个叫 Reverse Path Filtering 的保护机制。如果开启了“严格模式”(我的 Arch Linux 上默认如此),发送包的端口和上面绑定的 IP 不一致时会被内核过滤掉。可以通过内核参数 net.ipv4.conf.<interface>.rp_filter 控制这一行为(参考资料):

rp_filter - INTEGER
	0 - No source validation.
	1 - Strict mode as defined in RFC3704 Strict Reverse Path
	    Each incoming packet is tested against the FIB and if the interface
	    is not the best reverse path the packet check will fail.
	    By default failed packets are discarded.
	2 - Loose mode as defined in RFC3704 Loose Reverse Path
	    Each incoming packet's source address is also tested against the FIB
	    and if the source address is not reachable via any interface
	    the packet check will fail.

一般设置成 2,也就是“宽松模式”就好了,这样只要验证源 IP 属于本机就行了:

net.ipv4.conf.eth0.rp_filter=2
net.ipv4.conf.eth1.rp_filter=2

现在,接收和发送双方的负载均衡都实现了,并且是 per-packet 的。如果用 iperf 测试,应该可以看到单连接就能够塞满多块网卡带宽。

到了这里,和 ECMP 也没啥关系了,纯粹是 iptables 配策略路由的普通软路由方案。

利用 TUN/TAP 设备简化软路由管理

前面用不同网卡绑定不同的静态 ARP 表绕开 ARP 广播实现了更复杂的软路由。其实也可以加一层 TUN/TAP 设备(通俗地讲就是一种“虚拟网卡”)来做真正的软路由,不用手动写 ARP 表了。

首先在每台机器上都创建一个 TUN 设备,随便绑定一个 IP:

ip tuntap add mode tun tun0
ip addr add 10.99.255.10/32 dev tun0    # HostA
ip addr add 10.99.255.20/32 dev tun0    # HostB
ip addr add 10.99.255.30/32 dev tun0    # HostC

然后接下来就是要设置 10.99.255.[10,20,30] 这个“虚拟”网段内的路由。这完全是软件上做的,还是随机打标签+策略路由:

iptables -t mangle -A OUTPUT -d 10.0.0.0/24 -m statistic --mode nth --every 2 --packet 0 -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -d 10.0.0.0/24 -m statistic --mode nth --every 2 --packet 1 -j MARK --set-mark 2
ip rule add fwmark 1 table 10000
ip rule add fwmark 2 table 10001
ip route add 10.99.255.10 via 10.0.0.10 dev eth0 table 10000
ip route add 10.99.255.10 via 10.0.0.11 dev eth0 table 10001
ip route add 10.99.255.20 via 10.0.0.20 dev eth0 table 10000
ip route add 10.99.255.20 via 10.0.0.21 dev eth0 table 10001
ip route add 10.99.255.30 via 10.0.0.30 dev eth0 table 10000
ip route add 10.99.255.30 via 10.0.0.31 dev eth0 table 10001

和上个方法对比一下,其实加了个 TUN 的区别就在于把手写的静态 ARP 表换成了手写路由表(实质上 ARP 表也是种路由表)。不过自己设定的 IP 地址终究是比乱糟糟的 MAC 地址好看一些,并且该方法完全不影响原来物理网卡上绑定的 IP 及其路由。

 

到这里,我需要的链路聚合已经算比较优雅地实现了吧。为了更愉快地配合 Debian 的 ifupdown 使用,我写了个 if-up 脚本进行链路聚合(Gist)。放进 /etc/network/if-up.d 里,然后这么配置一下:

auto tun0
iface tun0 inet static
    address 10.99.255.10
    netmask 255.255.255.255
    mtu 9000
    fakenet 10.99.255.0/24
    table 10000 10001 10002 10003
    rspec 10.99.255.1:10.3.23.1:10.3.23.1:10.3.23.1 \
          10.99.255.10:10.99.0.10:10.99.1.10:10.99.2.10:10.3.23.10 \
          10.99.255.20:10.99.0.20:10.99.1.20:10.99.2.20:10.3.23.20 \
          10.99.255.30:10.99.0.30:10.99.1.30:10.99.2.30:10.3.23.30
    pre-up ip tuntap add mode tun tun0
    post-down ip tuntap del mode tun tun
Category: 计算机 | Tags: Linux 网络
1
29
2013
2

Archlinux on ThinkPad L430

甲、前言

出于特殊需求,花将近3000买了这个 ThinkPad L430。

一、配置

  • CPU:Intel Pentium B980 @ 2.40GHz  #Sandy Bridge 的,主频还可以
  • 显卡:HD 3000 核显 + Quadro NVS 5400M 独显  #奇葩的型号,好像是啥绘图卡,感觉和610M水准差不多
  • 内存:2GB  #跑Win7HB和Linux足矣
  • 硬盘:320GB HDD
  • 14吋屏幕、DVD刻录机、有摄像头、没指纹识别、预装Win7HB

二、吐槽

  • 指纹识别呢?我一直觉得 ThinkPad 这个很厉害,结果发现便宜货上没有……
  • 第一天就发现光驱是坏的,送回去修了,略郁闷。
  • Win7 预装了一坨联想的东西,还有啥QQ电脑管家,去死吧……

 

10
28
2012
3

NetworkManager 配合使用 chnroutes (至少适用于 Arch)

高三很忙,好久没写东西了。不过也快熬出头了。今天就写点儿啥吧。

 

VPN是个好东西,翻那个啥效果不错,比goagent之类的要稳定。但如果不配置路由的话,VPN就会成为默认网关,包办所有对外连接。这反而会导致访问国内网站速度变慢,而且也挺浪费流量的。我搜了一下,找到了chnroutes这个工具:

chnroutes
利用来自APNIC的数据生成路由命令脚本,让VPN客户端在连接时自动执行。通过这些路由脚本,可以让用户在使用VPN作为默认网关时,不使用VPN访问中国国内IP,从而减轻VPN负担,并提高访问国内网站的速度。

如果使用openvpn之类的命令连接VPN的话,按照其readme配置即可。但我还是偏好GUI,想用NetworkManager来管理连接。NetworkManager的VPN连接程序是自带的,并不使用命令行工具的配置文件。

Google到了这篇文章:《Ubuntu 9.10下使用Network-manager 配置openvpn 》

 

简要转述 chnroutes 使用方法:

  1. 克隆代码:
    git clone git://github.com/GutenYe/chnroutes.git
  2. 终端下切到代码目录,执行:python2 chnroutes.py
  3. 接下来会生成 vpn-up.sh、vpn-down.sh。vpn-up.sh 需要修改一下(原因参考上面提到的文章),把开头的 “OLDGW=$(...” 那一行删掉,改为:
    OLDGW=$(ip route show | grep '^[^d].*proto static' | grep -v 'dev\s*tun' | awk 'NR==1' | sed -e 's/.*via \([^ ]*\) .*/\1/')
  4. 把 vpn-up.sh 随便放到个合适的地方吧(我放到了 /etc/openvpn/ )

 

Arch 的 NetworkManager 没 Ubuntu 那个名为 01ifupdown 的 dispatcher 。简单研究一下,发现dispatcher也不是啥复杂的玩意儿。要点如下:

  1. 接入/断开连接时,会依次调用 /etc/NetworkManager/dispatcher.d/ 下的 shell 脚本
  2. NetworkManager 会给脚本传入(至少)两个参数,第一个是连接名称,第二个是动作
  3. 动作有(至少)四种:up—接入普通连接,down—断开普通连接,vpn-up、vpn-down—接入/断开VPN连接

照葫芦画瓢写了个(请保存到 /etc/NetworkManager/dispatcher.d/10chnroutes):

#!/bin/sh -e

case "$2" in
    vpn-up)
    exec /etc/openvpn/vpn-up.sh
    ;;
    vpn-down)
    exit 0
    ;;
esac

exit 0

额,弱爆了是吧……别的发行版应该也能用。

按说vpn-down时应该执行一下vpn-down.sh的,但我发现加上了反而会导致一个(无伤大雅的)错误,而且不执行也没啥影响,VPN断开后路由表确实自动恢复了。这方面我不太懂,反正事实就是这样。

到这里,NetworkManager 连接 VPN 时就能自动配置路由了。在VPN连接后,找个国内看IP的网站测试看看吧。

 

另外,对 Ubuntu 用户的附注。那篇参考文章提到的 01ifupdown,在最新的Ubuntu里变复杂了,要修改成下面这样:

    up|vpn-up)
        export MODE="start"
        export PHASE="post-up"
        /etc/openvpn/vpn-up.sh
        exec run-parts /etc/network/if-up.d
    ;;

 

Category: 计算机 | Tags: arch linux ubuntu vpn 网络
3
4
2012
0

【火狐三则】增强组件的PKGBUILD;不错的dial插件;同步profile到内存盘

没有什么关联的三则。

1. 火狐addon的PKGBUILD:

从CVS获取代码编译最新版插件的PKGBUILD,对喜欢用测试版Fx的用户可能有点用。

community里面有稳定版的adblock-plus、noscript,是下载XPI解压然后打包的。自己写的话,可以参考其中确定安装目录的部分。

adblock-plus

从hg获取的代码有个metadata,里面可以提取Fx版本支持信息,所以写成动态获取依赖版本了。

另外,第一次知道,用某些CVS的PKGBUILD中不用自己写clone代码的部分…… makepkg会自动完成。

pkgname=firefox-adblock-plus-hg
pkgver=3414
pkgrel=1
pkgdesc="plugin for firefox which disables script (mercurial developing version)"
arch=('any')
url="https://adblockplus.org/"
license=('GPL')
depends=("firefox")
conflicts=("firefox-adblock-plus")
provides=("firefox-adblock-plus")
makedepends=('unzip' 'python2-jinja' 'mercurial')

_hgroot="https://hg.adblockplus.org/"
_hgrepo="adblockplus"

build() {
    rm -rf "$srcdir/$_hgrepo-build"
    cp -rf "$srcdir/$_hgrepo" "$srcdir/$_hgrepo-build"
    cd "$srcdir/$_hgrepo-build"
  
    # determine supported firefox versions
    _fxver=($(sed -n 's/firefox=\(.*\)/\1/p' metadata | sed "s/\//\ /"))
    _abpver=$(sed -n 's/version=\(.*\)/\1/p' metadata)
    _emid=$(sed -n 's/id=\(.*\)/\1/p' metadata)
    depends=("firefox>=${_fxver[0]}" "firefox<=${_fxver[1]}")
    provides=("firefox-adblock-plus=$_abpver")

    python2 build.py build abp.xpi

    install -d "$pkgdir/usr/lib/firefox/extensions/$_emid"
    unzip -od "$pkgdir/usr/lib/firefox/extensions/$_emid" abp.xpi
    
    # unzip set filemode extracted from XPI file to 600
    # I don't know why :3
    chmod -R a+r "$pkgdir/usr/lib/firefox/extensions/$_emid"
}

https-everywhere

我sed功力太差,不会从XPI中提取版本信息(其实是土方法太繁琐),所以这个就不搞动态版本了……

pkgname=firefox-https-everywhere-git
pkgver=20120303
pkgrel=1
pkgdesc="an addon making firefox auto use HTTPS (git developing version)"
arch=('any')
url="https://www.eff.org/https-everywhere/"
license=('GPL2')
depends=("firefox>=3.0")
provides=("firefox-https-everywhere")
makedepends=('unzip' 'git')

_gitname="https-everywhere"
_gitroot="git://git.torproject.org/https-everywhere.git"

build() {
    cd $srcdir
    msg "Connecting to the GIT server...."
  
    if [ -d $_gitname ]; then
        cd $_gitname && git pull origin && cd ..
        msg "The local files are updated."
    else
        git clone $_gitroot $_gitname
    fi
    
    msg "GIT checkout done"
    
    rm -rf "$_gitname-build"
    cp -rf "$_gitname" "$_gitname-build"
    cd "$_gitname-build"
    sed -i '1 i#\!/usr/bin/python2' trivial-validate.py
    ./makexpi.sh
    
    install -d "$pkgdir/usr/lib/firefox/extensions/https-everywhere@eff.org"
    unzip -od "$pkgdir/usr/lib/firefox/extensions/https-everywhere@eff.org" pkg/*.xpi
}

 

2. FVD Speed Dial插件:

之前用Speed Dial,感觉界面很弱智……

今天发现了这个。自我感觉比Speed Dial强大多了,界面挺好看。

除了支持Speed Dial的分组之类的,Dial页还能显示最常访问、最近关闭等。

下载、截图自己看吧:https://addons.mozilla.org/en-US/firefox/addon/fvd-speed-dial/

 

3. profile-sync-daemon,同步浏览器配置到内存盘:

把用户profile(~/.mozilla)放到内存盘,可以提高Fx速度,并减少磁盘读写。考虑到这个比较麻烦,还要自己写脚本什么的,一直没搞过。

看Archwiki,发现了profile-sync-daemon这个daemon,挺很方便的。不仅支持Fx,还支持Chrome、Opera、Midori。graysky出品,必属精品。

从AUR安装,修改 /etc/psd.conf,在USERS部分填上自己的用户名,rc.d start psd 启动就行了。

2
19
2012
6

unzip 6.10b测试版,解决ZIP乱码问题

原来unzip有个-O参数,可以设定编码的。到了6.0版本不知为何移除了。后来ZIP乱码问题就一直困扰着群众。

今天翻了翻官网,发现测试版本6.10b重新添加了这个参数:

- Add -I and -O options for setting ISO and OEM character sets, respectively, used by UnZip when doing character set translations. This support is based on the unzip60-alt-iconv-utf8 patch suggested in an Info-ZIP forum thread and uses the iconv library which must be available. These options are enabled using the USE_ICONV_MAPPING compiler macro. Suggestions welcome on how to improve this limited character translation support.  

虽然这个版本2010年底就发布了,但能搜索到的信息几乎没有,真是奇怪。用官方新版本解决乱码不是很方便么……

于是写了个PKGBUILD,扔AUR了: unzip-beta

使用示例:

unzip 我是一个ZIP.zip -Ogbk

Category: 计算机 | Tags: arch ZIP 软件 linux
1
27
2012
11

最后还是堕落到宋体了

不得不说,点阵字体还是有很大好处的:看着清楚。所以又迎回了宋体。

矢量字体在我这里总有发虚、笔画杂揉的问题。估计是屏幕太小太旧,用网上给的配置感觉也不太好。

其他Windows字体没装,保持系统简洁。

 

参考: http://forum.ubuntu.org.cn/viewtopic.php?f=8&t=359236

(总算弄明白之前宋体为啥总也弄不好了,某个系统级别配置搞的鬼。我逐个移动/etc/fonts/conf.d下的文件,终于找到了元凶。)

 

以下是目前的fontconfig:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <!-- 基本设置,我的屏幕小,DPI设置为85。 -->
    <match target="font">
        <edit name="dpi" mode="assign">
            <double>85</double>
        </edit>
        <edit name="rgba" mode="assign">
            <const>rgb</const>
        </edit>
        <edit name="autohint" mode="assign">
            <bool>false</bool>
        </edit>
        <edit name="hinting" mode="assign">
            <bool>true</bool>
        </edit>
        <edit name="hintstyle" mode="assign">
            <const>hintfull</const>
        </edit>
        <edit name="antialias" mode="assign">
            <bool>true</bool>
        </edit>
        <edit name="embeddedbitmap" mode="assign">
            <bool>false</bool>
        </edit>
    </match>

    <!-- Windows中文字体替换 -->
    <match target="pattern">
        <test qual="any" name="family">
            <string>宋体</string>
            <string>新宋体</string>
            <string>NSimSun</string>
            <string>微软雅黑</string>
            <string>Microsoft YaHei</string>
            <string>AR PL ShanHeiSun Uni</string>
            <string>AR PL ShanHeiSun Uni MBE</string>
            <string>AR PL UMing CN</string>
            <string>AR PL UMing HK</string>
            <string>AR PL UMing TW</string>
            <string>AR PL UMing TW MBE</string>
        </test>
        <edit name="family" mode="assign" binding="same">
            <string>SimSun</string>
        </edit>
    </match>

    <!-- 不认识的字体当作sans-serif -->
    <match target="pattern">
        <test qual="all" name="family" compare="not_eq">
            <string>sans-serif</string>
        </test>
        <test qual="all" name="family" compare="not_eq">
            <string>serif</string>
        </test>
        <test qual="all" name="family" compare="not_eq">
            <string>monospace</string>
        </test>
        <edit name="family" mode="append_last" binding="weak">
            <string>sans-serif</string>
        </edit>
    </match>

    <!-- 小号宋体用点阵,关闭抗锯齿,不然看起来很浅 -->
    <match target="font">
        <test qual="any" name="family">
            <string>SimSun</string>
        </test>
        <test name="pixelsize" compare="more_eq">
            <double>8</double>
        </test>
        <test name="pixelsize" compare="less_eq">
            <double>18</double>
        </test>
        <edit name="antialias">
            <bool>false</bool>
        </edit>
        <edit name="embeddedbitmap" mode="assign">
            <bool>true</bool>
        </edit>
    </match>

    <!-- 斜体关闭点阵、开抗锯齿更清晰 -->
    <match target="font">
        <test name="slant" compare="not_eq">
            <const>roman</const>
        </test>
        <edit name="antialias">
            <bool>true</bool>
        </edit>
        <edit name="embeddedbitmap" mode="assign">
            <bool>false</bool>
        </edit>
    </match>

    <!-- 某些常见字体的alias -->
    <alias>
        <family>Times</family>
        <prefer>
            <family>Times New Roman</family>
        </prefer>
	<default>
	    <family>serif</family>
	</default>
    </alias>

    <alias>
        <family>Helvetica</family>
	<prefer>
	    <family>Arial</family>
	</prefer>
	<default>
            <family>sans</family>
        </default>
    </alias>

    <alias>
        <family>Courier</family>
        <prefer>
            <family>Courier New</family>
        </prefer>
	<default>
	    <family>monospace</family>
	</default>
    </alias>
    
    <alias binding="strong">
	<family>Ubuntu</family>
	<prefer>
	    <family>Ubuntu</family>
            <family>MYuppyGB-Medium</family>
            <family>文泉驿微米黑</family>
	</prefer>
    </alias>

    <!-- 基本的三个字体族:sans、serif、mono -->
    <alias binding="strong">
	<family>sans-serif</family>
	<prefer>
            <family>SimSun</family>
            <family>WenQuanYi Bitmap Song</family>
	</prefer>
    </alias>

    <alias binding="strong">
	<family>serif</family>
	<prefer>
            <family>SimSun</family>
            <family>WenQuanYi Bitmap Song</family>
	</prefer>
    </alias>
    
    <!-- 等宽就不用宋体了。编程不怎么用中文,英语矢量字体更好看 -->
    <alias binding="strong">
	<family>monospace</family>
	<prefer>
	    <family>Droid Sans Mono</family>
            <family>文泉驿等宽微米黑</family>
	</prefer>
    </alias>
</fontconfig>

另外,用font-manager禁用了几个字体。Nimbus那几个是X带的的基本字体,很难看。文鼎明体不禁用应该也没啥问题。剩下几个是效果差的:

<?xml version="1.0"?>
<fontconfig>
  <selectfont>
    <rejectfont>
      <pattern>
        <patelt name="family">
          <string>Nimbus Mono L</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>AR PL UMing TW MBE</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>Century Schoolbook L</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>URW Bookman L</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>AR PL UMing CN</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>Nimbus Roman No9 L</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>Nimbus Sans L</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>AR PL UMing HK</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>AR PL UMing TW</string>
        </patelt>
      </pattern>
      <pattern>
        <patelt name="family">
          <string>Ahem</string>
        </patelt>
      </pattern>
    </rejectfont>
  </selectfont>
</fontconfig>

 

Category: 计算机 | Tags: 字体 linux arch
1
17
2012
7

repo-elephant:Arch彩蛋?

无意中在最新的 pacman 4.0.1 里面发现了repo-elephant这么个玩意儿。

 

哦呵呵:

cuihao@cuihao-arch /tmp $ repo-elephant -q
    _    _
   / \__/ \_____
  /  /  \  \    `\
  )  \''/  (     |\
  `\__)/__/'_\  / `
     //_|_|~|_|_|
     ^""'"' ""'"'

 

啊哈:

cuihao@cuihao-arch /tmp $ repo-elephant -q
     __
    '. \
     '- \
      / /_         .---.
     / | \\,.\/--.//    )
     |  \//        )/  /
      \  ' ^ ^    /    )____.----..  6
       '.____.    .___/            \._)
          .\/.                      )
           '\                       /
           _/ \/    ).        )    (
          /#  .!    |        /\    /
          \  C// #  /'-----''/ #  /
       .   'C/ |    |    |   |    |mrf  ,
       \), .. .'OOO-'. ..'OOO'OOO-'. ..\(,

 

貌似是个正经玩意儿:

cuihao@cuihao-arch /tmp $ repo-elephant -h
repo-elephant (pacman) 4.0.1

  -q, --quiet       最小化输出信息
  -s, --sign        更新后使用 GnuPG 签名数据库
  -k, --key <密匙>   使用指定的密匙签名该数据库
  -v, --verify      更新前验证数据库签名

更多细节及可用选项的描述请参见 repo-elephant(8) 。

 

……好像又是坑爹:

cuihao@cuihao-arch /tmp $ man repo-elephant
没有 repo-elephant 的手册页条目

cuihao@cuihao-arch /tmp $ man 8 repo-elephant
在第 8 节中没有关于 repo-elephant 的手册页条目。

 

庐山真面目,原来是repo-add啊:

cuihao@cuihao-arch /tmp $ ls -al `which repo-elephant`
lrwxrwxrwx 1 root root 8  1月 13 12:45 /usr/bin/repo-elephant -> repo-add*

 

打开repo-add,发现这么一些代码:

elephant() {
	case $(( RANDOM % 2 )) in
		0) printf '%s\n' "H4sIAL3qBE4CAyWLwQ3AMAgD/0xh5UPzYiFUMgjq7LUJsk7yIQNAQTAikFUDnqkr" \
		                 "OQFOUm0Wd9pHCi13ONjBpVdqcWx+EdXVX4vXvGv5cgztB9+fJxZ7AAAA"
		;;

		1) printf '%s\n' "H4sIAJVWBU4CA21RMQ7DIBDbeYWrDgQJ7rZ+IA/IB05l69alcx5fc0ASVXUk4jOO" \
		                 "7yAAUWtorygwJ4hlMii0YkJKKRKGvsMsiykl1SalvrMD1gUXyXRkGZPx5OPft81K" \
		                 "tNAiAjyGjYO47h1JjizPkJrCWbK/4C+uLkT7bzpGc7CT9bmOzNSW5WLSO5vexjmH" \
		                 "ZL9JFFZeAa0a2+lKjL2anpYfV+0Zx9LJ+/MC8nRayuDlSNy2rfAPibOzsiWHL0jL" \
		                 "SsjFAQAA"
		;;
	esac | openssl base64 -d | gzip -d
}
# figure out what program we are
cmd=${0##*/}
if [[ $cmd == "repo-elephant" ]]; then
	elephant
	exit 0
fi

 

Arch开发人员真有聊

1
10
2012
8

清理字体

以前觉得字体多了好,这样访问不同网页就能看到不同的效果了。

后来发现不少字体Linux下的效果就是一坨儿…… 比如宋体吧,Windows下看着好好的,在Linux下用看着虚得很。虽然经过复杂地配置能搞定,但一个一个字体都这么弄,还是太费事了。

于是我想,把字体清理一下,只留下那些看着效果好的字体和必须的字体。

  1. Liberation字体删除了,因为英语“R”右下角一捺显示太虚。
  2. Nimbus无衬线和等宽字体禁用了,无衬线字体原因同上,等宽字体太烂了。
  3. Windows字体大多被删除,除了雅黑看着不错,其他无论中英文效果都很糟糕。
  4. 多余的韩文、日文CJK字体删除了。
  5. 基本用不着的小语种字体删除了。

目前留下的字体:

CJK:

  1. 文鼎的宋体、楷体,显示文档也许有用
  2. 文泉驿正黑、微米黑
  3. hannom,衬线字体,支持的汉字比较多
  4. 花园明朝,无衬线字体,支持的汉字比较多
  5. 雅黑宋体(修改版M$雅黑)
  6. 几个装点门面的艺术字体。

英语:

  1. Bitstream Vera
  2. Dejavu
  3. 谷歌的Droid字体
  4. Ubuntu字体,装点门面

其他:

  1. mph-2b-damase 支持些额外的字符。

目前感觉好极了…… 至少不用为了乱七八杂的字体纠结了。

 

Category: 计算机 | Tags: 字体 美化 linux
1
8
2012
0

一些Arch PKGBUILD的知识

总结一些以前疑惑的关于PKGBUILD的问题。

1. 就算需要,base-devel组中的软件包也不会写入编译时依赖列表(makedepends):

base-devel软件包组包含编译软件所需的基本工具(软件包列表:i686x86_64),包括gcc编译器、make之类的。一般编译软件包都需要这些包,所以干脆就规定makedepends中不需要指定它们。

如果你发现怎么makepkg都编译不了,先看看是不是忘记装base-devel了(pacman -S base-devel)。

2. 从git、svn、cvs、hg等版本控制系统获取代码的软件包,版本号会自动更新:

从版本控制系统获取代码的话,只要PKGBUILD是标准格式,版本号会自动更新,以反映最新的代码变化。

比如,从AUR上下载的ibus-git的PKGBUILD,本来的版本号是20110501,可makepkg之后得到的版本号就变成当天日期YYYYMMDD了。

svn、hg版本号会更新为最新修订号,git、cvs用当天的日期了。

3. install文件之作用:

某些软件包除了PKGBUILD,还会附带一个XXX.install文件。这个文件定义了安装、升级、删除软件包前后要执行的操作。

这些操作放到PKGBUILD是不行的,因为最终要安装的是软件包,而非PKGBUILD。

比如,字体软件包安装或卸载后需要刷新字体缓存,这些操作就必须放在install文件中。

4. arch=('x86_64' 'i686')arch=('any') 的区别:

arch=('x86_64' 'i686')表示:该PKGBUILD可以为x86_64和i686平台生成软件包,但生成的软件包并不能跨平台。

arch=('any')表示:该PKGBUILD生成的软件包在x86_64和i686平台都可以安装。

5. package()build() 函数的区别:

package()是在fakeroot环境执行的,所以能使用某些特殊命令。

其实,通常情况下,把编译过程放在package()、或是把所有操作都放在build()都是可以的。makepkg只保证package()build()(以及不常见的check())之后执行。

6. “xxx || return 1”中“return 1”的作用:

xxx || return 1”的意思是:如果 xxx 命令出错退出了,就退出当前函数并返回错误代码1。这是为了保证重要过程出错时makepkg及时停止。

估计是历史遗留,现在用处不大,因为makepkg本来就会自动出错停止。

7. makepkg不会自动删除旧的src目录,可能导致第二次编译错误:

在执行过一次makepkg的目录再次执行makepkg,src目录不会自动被删除。如果有patch之类的操作,可能因为上次patch过而导致错误。需要手动删除src目录。

Category: 计算机 | Tags: arch cvs Git linux shell svn 软件
1
2
2012
10

供同学们膜拜的 Linux

随便截图若干。

 

常规操作

1. 用强大的Vim写代码

屏幕截图 - 2012年01月02日 - 08时30分00秒.png

2. IBus输入法,以及记事本:

屏幕截图 - 2012年01月02日 - 08时32分47秒.png

3. 支持HTML5的Firefox:

屏幕截图 - 2012年01月02日 - 11时21分00秒.png

 

中国特色

4. 用python-webqq登陆扣扣:

屏幕截图 - 2012年01月02日 - 11时41分26秒.png

5. WebQQ弱爆了?来个TM2009,还带迅雷:

屏幕截图 - 2012年01月02日 - 08时38分46秒.png

6. 哪里的网络最自由?:

屏幕截图 - 2012年01月02日 - 12时05分57秒.png

 

娱乐

7. 听歌+歌词插件:

屏幕截图 - 2012年01月02日 - 11时18分34秒.png

 

8. 黑白的命令行放彩色电影:

9. Linux下打星际:

10. Linux下打使命召唤6

  

 

 

面子工程

11. Stellarium观天象:

屏幕截图 - 2012年01月02日 - 11时56分29秒.png

12. 十年前的Geforce2都能带动的特效:

13 & 14. 最新G3科技

 

| Theme: Aeros 2.0 by TheBuckmaker.com