Arch Linux 星球

July 02, 2016

Felix Yan

不双清给一加氢 OS 刷上 Google Apps

最近入爪一台一加 3,解锁刷 root 后几乎配置完了所有东西,然后才发现忘记了 gapps。网上看到许多人在这种情况下刷 gapps 遇到了各种各样的问题,一般都被建议双清解决。我查找了一些资料后,决定试试不双清自己修复权限问题。

安装 OpenGApps

这里的假设是已经刷过第三方 Recovery,我这里是 TWRP。从 OpenGApps 网站下载对应的包(我这里对应的是 ARM64、6.0),我选择了 nano 包。

重启进入 Recovery 刷入此包。然后不要急着重启,因为大量网友反应此时重启后会不断 fc。我在一加论坛找到了这样的方法,经实测有效(针对 TWRP,其他 Recovery 请自行调整):此时应回到 Recovery 首页,进入 Mount 页面勾上 System,然后回到首页依次选择 Advanced -> File Manager -> system -> priv-app -> SetupWizard,然后点击右下的选择气泡,最后点击 Delete 删除这个文件夹。

重启正常进入系统后,点击 Google Play 或直接添加 Google 帐号即可。

遇到的问题

一、Google Play 无法正常下载应用

Google Play 下载或更新任何应用时,提示 DF-DLA-15 错误。我找到的方法是进入应用管理清空 Google Play 及 Google Play Services 的数据后重试。

二、Google 联系人同步选项消失

帐户管理中的 Google 帐号内只剩下健身、人脉、应用数据,联系人同步不见踪影。Reddit 上有人指出授权 sync adapter 读写联系人即可,但 H2OS 的应用管理界面中似乎没有办法直接操作,因此我用 adb 手动进行了授权:

$ adb shell
$ pm grant com.google.android.syncadapters.contacts android.permission.READ_CONTACTS
$ pm grant com.google.android.syncadapters.contacts android.permission.WRITE_CONTACTS

执行后,重启手机即可,不需要如原文所说删除、重新添加 Google 帐号。

by Felix Yan at July 02, 2016 08:18 AM

June 26, 2016

中文社区新闻

screen-4.4.0-1 将无法连接(attach)旧的会话

如果升级到 screen-4.4.0-1 你将无法再次连接上(reattach)用旧版本 screen 开启的会话。所以请确保升级前已经关闭了所有旧的会话。

by farseerfc at June 26, 2016 06:49 PM

June 25, 2016

quininer kel

青龙会起源猜测

青龙会起源猜测

Fri Jun 24 20:03:11 2016

老伯脸色渐渐和缓,道“这桌子里有三百七十六份卷宗,每一份卷宗,都代表一宗财富,管理它的人。本来只有我一个人能指挥,因为他们也只接受我一个人的命令。”
律香川在听着!
老伯道“但无论谁,只要有了我的秘令和信物,都可以直接命令他们,现在我也全都交给你”
他又补充道“我对这三百七十六人的秘令和信物都不同,若是万一弄错,去的人立刻就有杀身之祸。”
律香川一直在静静地听着。
他本来就觉得老伯是个了不起的人,现在这种观念更加深直到现在,他才知道老伯的财产竟是如此庞大,如此惊人,就算用“富可敌国”四个字来形容,也不过分。要取这些财产,已不容易,要保持更不容易。
除了老伯外,他简直想不出还有第二个保持得这么久、这么好的秘密。
—— 《流星·蝴蝶·剑》

《流星蝴蝶剑》看到这一段的时候,第一个想起的是青龙会。

如此庞大的组织不禁引人深思,而《七种武器》里说:

“正月初三。”门外的人也重复说了两遍:“正月初三。”
这是日期,不是人的名字。也许不是日期,而是一个约好了的暗号。
但是现在这个暗号却代表一个人,属于一个极庞大秘密组织的人。
四百年来,江湖中从来未有过比“青龙会”更庞大严密的组织。
它的属下有三百六十五个分舵,分布天下,以太阴历为代表,“正月初三”,就代表它属下的一个分舵的舵主。
—— 《七种武器 之 离别钩》

四百年里从未有过比青龙会更庞大严密的组织。 而照《流星蝴蝶剑》的说法,孙玉伯的势力却似乎更大。

由此本人开了个脑洞 —— 青龙会的起源就是孙玉伯!

“我杀他,只因为我有个朋友不想再让他活下去。”
“你也有朋友?”思思笑了,“我从来不知道你也有朋友。”
她想了想之后又问:“你那个朋友随便要你做什么事你都答应?”
狄青麟居然点了点头。
“只有他才能让我这么做,因为我欠他的情。”狄小侯接着说:“他是现存江湖中最庞大的一个秘密组织首脑,曾经帮过我一次很大的忙,唯一的条件是需要我为他做事的时候,我也不能拒绝。”
他又说:“这个组织叫青龙会,有三百六十五个分舵,每一州每府每一县每一个地方都有他们的人,势力之大,绝不是你能想得到的。”
—— 《七种武器 之 离别钩》

  • 使用不为人知的秘密来控制权势者,典型的青龙会风格。
  • 称呼对方为“朋友”,典型的老伯风格。

律香川垂下头,黯然道“不必留给我…。”
老伯沉下了股,厉声道“你难道想死”
律香川头垂得更低。
老伯道“你绝不能死,因为你还要等机会不但要等机会替我报仇,还要等机会将我这番事业复兴,我没有儿子你就是我的儿。”
律香川道“是”
老伯展颜道“所以我大部分财产你都可自由支配,其中只有我特别注明的几份是例外。”
他神情忽然变得很奇特,缓缓接着道“那几份财产我是留给小蝶的。”
—— 《流星·蝴蝶·剑》

  • 老伯将卷宗分出了一部分留给女儿孙蝶,解释了为什么青龙会是三百六十五个分舵,而不是三百七十六。

高老大笑道“但你并不是没有来历的人,我已替你安排了个来历。”
孟星魂道“什么来历?”
高老大道“你姓秦叫秦中亭,是鲁东秦家的人,秦护花秦二爷的远房侄子,因为从小就跟着秦二爷手下的海客出海去做生意了,似从未在中原露过面,所以也就没有人认得你。”
—— 《流星·蝴蝶·剑》

龙五道:“你知道他是谁?”
柳长街道:“我不能确定。”
龙五道:“不妨说说看。”
柳长街道:“昔年有个了不起的少年英雄,九岁杀人,十七岁已名动武林,二十刚出头,就已身为七大剑派中崆峒一派的掌门,刀法之高,当世无双,人称天下第一刀。”
龙五道:“你没有看错,他就是秦护花。”
—— 《七杀手》

  • 《流星蝴蝶剑》和《七杀手》在同一时代,而《七杀手》在《七种武器系列》之前(又说七种武器之七)。 因此老伯或者某人使用老伯的资源创建了青龙会是可能的。

其他方向的例证,因为这里引用了丁情的小说,所以年表实际上是错的。 例如

小香摇摇头:“不会,李探花虽然把他的飞刀绝技传给了我祖父,却被我曾祖父知道了,当时就挑断了我祖父双手的筋络,使他终生不能发挥那些技艺。”
“这是为什么呢?难道你家跟李探花有什么过不去?”
小香只说了一句话:“我姓龙,我本名叫龙天香。”
谢先生偏又多问了一句:“你高曾祖父一定叫龙啸云。”
—— 《圆月弯刀》

《三少爷的剑》后续《圆月弯刀》里出现了龙啸云的后人,李寻欢到丁鹏之间差了近百年的时间。 所以《三少爷的剑》时间上应该在《边城浪子》之后,《飞刀,又见飞刀》之前。

不过这是题外话。《流星蝴蝶剑》时间上在《七种武器系列》之前应该是共识。

老伯没有回答只是接着道:“你只要一走进那镖局,就会看到一个又矮又脏的跛老人。他一定会问你是谁,你千万不能回答,连一个字都不能回答,要等他问你七次之后,你才能说‘潜龙升天’,只说这四个字,他就明白是我要你去的了。”
—— 《流星·蝴蝶·剑》

他微笑着道:“现在你该完全明白了吧?”
孟星魂摇摇头。他的确不能完全明白,因为他太激动,太欢喜。几乎已完全无法思索。
易潜龙很理解所以接着道:“我非但没有出卖老伯,也没有溜走。我从来就没有溜走过。”
孟星魂忽然理解,所以就替他说了下去,“别人以为你溜走的时候,其实你正在暗中为老伯训练那一批新血。”
易潜龙道:“不错,无论任何组织都和人一样,时时刻刻都需要新的血液补充,否则他不但会衰老腐败,而且随时都可能崩溃。”
孟星魂目中忍不住流露祟敬之色,因为他觉得在面对着的,是个伟大的朋友。
易潜龙也看得懂,微笑着道,“其实那也算不了什么,那些年轻人非但充满了热情,而且全都很忠实,要训练他们并不是件困难的事。”
—— 《流星·蝴蝶·剑》

  • 老伯有一个朋友叫易潜龙,也许是青龙会名字的来源? 比如老伯将卷宗传给给了易潜龙,易潜龙借此创立了青龙会。

不过以上都是毫无证据的牵强猜测。 只怪青龙会太过神秘,而七种武器尚未补全,也不可能补全了。

by quininer kel at June 25, 2016 12:22 AM

LastAvengers

编写便于打包的 Makefile

网络上关于 Makefile 的教程不少,但似乎都止于「如何用 Makefile 自动编译程序」, 而关于如何用 Makefile 安装程序的文章却寥寥无几。(也可能是我关键词不对,反正我搜了好久都没搜到) 最近在做 Srain 的时候,算是琢磨出了对于 make install 的比较正确的写法,

首先,对于生成的项目是单可执行文件的情况下,直接 install -755 xxx /usr/bin/xxx 就好了。 但是并非所有项目都只要单个可执行文件,程序可能还包含了 man 文档,icons,图片,配置文件等,这里只考虑项目需要已。

假设项目结构如下,代码文件里写了什么不重要~

.
├── build
├── data
│   └── pixmaps
│       └── srain-avatar.png
├── Makefile
└── srain.c

题外话:关于图标

对于图标,[1] 规定了图标在文件系统上的位置,程序只需要根据图标的名称就可已获得图标(当然要借助各种库函数,比如 gtk 的 gtk_image_new_from_icon_name), 根据 spec 看,程序应该依次检查 $HOME/.icons$XDG_DATA_DIRS/icons/usr/share/pixmaps

$XDG_DATA_DIRS 为空时,$XDG_DATA_DIRS 会默认为 /usr/local/share/:/usr/share/ [2](感谢 csslayer 指出)。

因此把图标安装在 /usr/share/pixmaps/usr/local/share/icons/usr/share/icons 下都是可行的,Arch Linux 偏向于安装在最后一个目录。 于是可以像这样安装 16x16 的图标:

cd data/icons/16x16; \
for png in *.png; do \
            install -Dm644 "$$png" \
                "$(DESTDIR)/usr/share/icons/hicolor/16x16/apps/$$png"; \
        done

PREFIX

除了图标之外,其他的数据文件应该如何组织? 对此 GNU 给出了他的规范 [3]:

GNU make 提供了 prefix 等变量确定各种文件安装的位置:

  • prefix 是下述变量的前缀,默认的 prefix 值应该是 /usr/loacl
    • exec_prefix 是下述变量的前缀,通常和 prefix 相等
      • bindir 安装可执行文件的位置,其值应为 $(exec_prefix)/bin
      • ...
    • datarootdir 用来安装只读的,架构无关的数据文件,其值应为 $(prefix)/share
    • sysconfdir 用来安装只读的配置文件,其值应为 $(predix)/etc
    • ...

[3] 中列出了各种用途的目录,但事实上我们不需要把数据文件分成那么细的粒度。对于简单的项目,只有 prefix 是必要的,其他路径都可以 hardcode。

make install 可以这么写(为了命名统一,prefix 用大写):

PREFIX = /usr/local

install:
    install -Dm755 "build/srain" "$(PREFIX)/bin/srain"
    cd data/pixmaps; \
        for png in *.png; do \
            install -Dm644 "$$png" \
                "$(PREFIX)/share/srain/pixmaps/$$png"; \
        done

放置各种文件的规范有了,但程序应该如何找到他的数据文件呢? 用 gcc 的 -D 参数声明一个宏,在编译的时候告诉程序的 prefix:

CC = gcc
CFLAGS = -O2 -Wall 
DEFS = -DPACKAGE_DATA_DIR=\"$(PREFIX)\"

TARGET = build/srain

$(TARGET): srain.c
    $(CC) $(CFLAGS) $(DEFS) $^ -o $@

在程序中你就可以根据这个宏在获得你的数据文件:

#ifndef PACKAGE_DATA_DIR
#define PACKAGE_DATA_DIR "/usr/local"
#endif

gchar *get_pixmap_path(const gchar *filename){
    gchar *path;

    path = g_build_filename(PACKAGE_DATA_DIR, "share",
            "srain", "pixmaps", filename, NULL);

    if (g_file_test(path, G_FILE_TEST_EXISTS)){
        return path;
    }

    g_free(path);
    return NULL;
}

注意上面的代码使用了 glib 函数库,当指定 prefix 为 /usr,程序便会从 /usr/share/srain/pixmaps 里寻找图片。

自行编译安装的程序通常被安装在 /usr/local, 这也是 GNU 推荐的 prefix
Arch Linux 的包的 prefix 通常是 /usr

如上一番设定后,程序经过编译和安装后便可以运行指定的任意目录上了,你也可以指定为 $(PWD)/build 方便调试。

make PREFIX=/usr; make PREXI=/usr install 后,产生的文件如下:

/usr/bin/srain
/usr/share/srain/pixmaps/srain-avatar.png

DESTDIR

上面的 make install 直接将各种文件安装在了目的文件系统上,如果 Makefile 写错的话,可能对系统造成破坏, 直接安装也不利于打包,正确的做法是,由 make install 得到程序所有文件的列表和路径, 再由包管理器把这些文件和路径存为软件包, 安装的时候根据路径把文件放到应该放的位置(这大概就是 Staged Install?)。 (这里感谢青蛙老师 hexchain 的指导)

变量 DESTDIR 就是用来实现 Staged Install 的,把之前的 make install 改成这样:

PREFIX = /usr/local
install:
    install -Dm755 "build/srain" "$(DESTDIR)$(PREFIX)/bin/srain"
    cd data/pixmaps; \
        for png in *.png; do \
            install -Dm644 "$$png" \
                "$(DESTDIR)$(PREFIX)/share/srain/pixmaps/$$png"; \
        done

注意 DESTDIR 变量只应该作用在 install 阶段,make PREFIX=/usr; make PREFIX=/usr DESTDIR=/tmp/ 会把所有文件都安装在 /tmp 下, 所有的影响都被限制在该目录内。这次生成的文件应该是:

/tmp/usr/bin/srain
/tmp/usr/share/srain/pixmaps/srain-avatar.png

之后再由包管理器把这些文件打成包,安装到系统中。

Configure

上面的 Makefile 有处不优雅的地方是,makemake install 的时候必须指定相同的 PREFIX,不然安装后的程序肯定是运行不了的,而 make 本身并不能 解决这个问题,因为 make 是「无状态」的。

[5] 提供了一个脚本来让解决这个问题,将 Makefile 改名为 Makefile.in,运行 ./configure --prefix=xxx 来获得一个拥有指定 prefix 的 Makefile,这样就可以不用每次敲 make 都输入 PREFIX=xxx 了。

于是大家都去用 autotool 了

#!/bin/sh

prefix=/usr/local

for arg in "$@"; do
    case "$arg" in
    --prefix=*)
        prefix=`echo $arg | sed 's/--prefix=//'`
        ;;

    --help)
        echo 'usage: ./configure [options]'
        echo 'options:'
        echo '  --prefix=<path>: installation prefix'
        echo 'all invalid options are silently ignored'
        exit 0
        ;;
    esac
done

echo 'generating makefile ...'
echo "PREFIX = $prefix" >Makefile
cat Makefile.in >>Makefile
echo 'configuration complete, type make to build.'

PKGBUILD

这样的一个项目打包起来是很愉快的 :)

pkgname=srain

...
build() {
    cd ${pkgname}
    mkdir build || true
    ./configure --prefix=/usr
    make
}

package() {
    cd ${pkgname}
    make DESTDIR=$pkgdir install
}

参考

  1. Icon Theme Specification
  2. XDG Base Directory Specification#Environment variables
  3. GNU Coding Standards#Variables for Installation Directories
  4. GNU Coding Standards#DESTDIR: Support for Staged Installs
  5. Practical Makefiles, by example

June 25, 2016 12:00 AM

June 17, 2016

百合仙子

Linux 作业控制实践

本文来自依云's Blog,转载请注明。

事情的起因是这样子的。

有一个非常常用的调试工具叫 strace。输出的信息是纯文本,一大片看起来累。在 Vim 里可以给它高亮一下,就好看多了。再加上各种搜索、清理,以及非常赞的 mark.vim 插件,用起来就舒服多了!

然而我并不想每次都让 strace 写到文件里然后再拿 Vim 去读,因为还得记着清理那些文件。如果数据量不大的话,直接通过管道传给 Vim 多好。

于是有了如下 zsh 函数:

(( $+commands[strace] )) && strace () { (command strace "$@" 3>&1 1>&2 2>&3) | vim -R - }

效果是达到了,但是这样子要中断 strace 的话,得去另一个终端里去 kill。按 Ctrl-C 的话,SIGINT 也会被发给 Vim,导致 Vim 显示空白。

所以嘛,得把 Vim 放到一个单独的进程组里,这样就不会在 Ctrl-C 的时候收到 SIGINT 了。但是,Vim 还得用终端啊。

一开始,我用自制的 expect.py 模块,给 Vim 分配了一个新的终端。这样子 Ctrl-C 好用了。然后我发现 Ctrl-Z 不好用了……

Ctrl-Z 还是挺方便的功能,临时需要执行个命令,不用开新的 shell(以及 ssh),直接按一下 Ctrl-Z,完事之后再回来,多好啊!就跟 zsh 的 Alt-q 一样方便好用呢。

于是就想还是不开 pty 了。直接子进程放新组里跑。这样 Vim 在尝试向终端输出时会收到 SIGTTOU 信号,因为它不是前台进程组。找了一下,用 tcsetpgrp 就可以把指定进程组放到前台了。然后发个 SIGCONT 让可能已经停下来了的 Vim 继续。

然后,当 Vim 收到 SIGTSTP 而停止的时候,我的程序该怎么知道呢?搜了一下,原来这种情况下也会收到 SIGCHLD 的!我以前一直以为只有子进程退出才会收到 SIGCHLD 啊……然后是一个关于 SIGCHLD 的坑,之前在 pssh 里看到过的,这次没有及时想到:不给 SIGCHLD 注册信号处理器时是收不到 SIGCHLD 的!不过诡异的是,我的这个程序有时却能够收到——在我使用 strace 跟踪它的时候……

于是,当 Vim 收到 SIGTSTP 时,把我们自己设置成前台进程组,然后给自己发一个 SIGTSTP 也停下来好了。令人意外的是,后台进程在调用 tcsetpgrp 时竟然也会收到 SIGTTOU。不过没关系,忽略掉就好了。

当用户 fg 时,就再把 Vim 设置成前台进程,并给它一个 SIGCONT 让它继续就好了。

最终的成品 vimtrace 在这里我的 zsh 配置是这样子的:

if (( $+commands[vimtrace] )); then
  (( $+commands[strace] )) && alias strace='vimtrace strace'
  (( $+commands[ltrace] )) && alias ltrace='vimtrace ltrace'
else
  (( $+commands[strace] )) && strace () { (command strace "$@" 3>&1 1>&2 2>&3) | vim -R - }
  (( $+commands[ltrace] )) && ltrace () { (command ltrace "$@" 3>&1 1>&2 2>&3) | vim -R - }
fi

后记:

strace 有时候还是会改变进程的行为的。这种时候更适合用 sysdig。Arch 刚刚更新的 sysdig 版本已经修正了崩溃的问题了~不过 Vim 对 sysdig 的输出就不像 strace 那样有好看的语法着色了。

其实我当时用 systemtap 来看信号发送情况更方便一些。不过那个需要内核调试符号,几百M的东西,装起来累啊……

by 依云 at June 17, 2016 08:21 AM

June 12, 2016

ヨイツの賢狼ホロ

在 Windows 中写 C 程序

说着说着一个学年就要过去了啦~

要说这半年(现在不是六月了么)印象最深刻的是啥,就是帮忙解决了身边不少同学的相同的问题……

--farseerfc 果然是先知啊(雾

ヨイツの賢狼ホロ 😋, [11.06.16 20:43] 😂😂

ヨイツの賢狼ホロ 😋, [11.06.16 20:43] /me 刚刚解决了些问题👍

ヨイツの賢狼ホロ 😋, [11.06.16 20:44] 解决了些社团同学的问题😂

farseerfc 😂, [11.06.16 20:44] [In reply to ヨイツの賢狼ホロ 😋] 感覺牙縫裡還夾著頭髮(

ヨイツの賢狼ホロ 😋, [11.06.16 20:44] [In reply to farseerfc 😂] 😂啥

莉莉艾塔·K·A (Лилы-Айта К.А.) , [11.06.16 20:44] [In reply to farseerfc 😂] ?!

farseerfc 😂, [11.06.16 20:44] [In reply to ヨイツの賢狼ホロ 😋] 一些骨頭在萌狼肚子裡(解決

ヨイツの賢狼ホロ 😋, [11.06.16 20:45] 😂

Felix Yan, [11.06.16 20:45] 太可怕了

Felix Yan, [11.06.16 20:45] 狼最近食欲很好啊

好了玩笑开完了(再纠结这个的话要不要亲自体验一下?😋)。其实就是因为这学期的 C 语言课,然后就栽在用啥写程序这个问题上了……

然而那些搞得咱想 **(😋) 的老师竟然还在用 VC6?? 对,就是那个老掉牙的而且在 Windows 7 以后的系统不好装的 Visual C++ 6 (╯^﹏^)╯ ┻━┻

所以在 问的不耐烦(实在吃不下) 之后,咱决定写点啥了……

最简单的方法:换 Linux 啦~

此处 Linux = 基于 Linux 内核的操作系统 😂

确实 Linux 上写 C 程序更方便些啦~

  • 大多数的 Linux 发行版上都带有 GCC (啥?汝不会连 GCC 都不知道是啥吧 , 赶紧补习一下吧~
  • 可能还会有手册页,包括标准库的大多数内容.
  • 另外,如果想继续深入学习的话,Linux 应该也算一门技能吧......

然而:

  • Linux 是个操作系统,这就注定了汝可能要花好长的时间先去学习如何使用这个操作系统😂
  • ......

所以咧?

如果汝有心情在这一领域深入下去 (而不是为了通过考试) ,可以尝试一下~ 😋

或者在 Windows 上搭建一个类 Unix 子系统?

最适合觉得装在真机或者虚拟机上太麻烦的人啦~

类 Unix 子系统其实就是运行在 Windows 上的一个程序啦~ 它用来提供POSIX系统调用的API, 这样在 Linux 等类 Unix 系统上写成的程序就可以通过重新编译来在 Windows 下运行啦~

目前名气最大的类 Unix 子系统有两个,分别是 CygwinMSYS2 , 如果非要咱钦定一个的话......那一定是 MSYS2 啦,因为有咱喜欢的 pacman 😋

考虑到长度的关系具体怎么安装咱下次再说吧 (挖坑的节奏......)

挑一个合适的集成开发环境?

集成开发环境(Integrated Development Environment,简称IDE)是一种辅助程式开发人员开发软体的应用软体, 在开发工具内部就可以辅助编写原始码文本、并编译打包成为可用的程序,有些甚至可以设计图形介面。

IDE通常包括程式语言编辑器、自动构建工具、通常还包括除错器。有些IDE包含编译器/直译器, 如微软的Microsoft Visual Studio,有些则不包含,如Eclipse、SharpDevelop等, 这些IDE是通过调用第三方编译器来实现代码的编译工作的。有时IDE还会包含版本控制系统和一些可以设计图形用户界面的工具。 许多支援物件导向的现代化IDE还包括了类别浏览器、物件检视器、物件结构图。 虽然目前有一些IDE支援多种程式语言(例如Eclipse、NetBeans、Microsoft Visual Studio),但是一般而言 ,IDE主要还是针对特定的程式语言而量身打造(例如Visual Basic)。

---- Wikipedia:集成开发环境

所以已经有先人想到了这个问题制作了很多(?)的集成开发环境啦~ 然而咱并没用过 (咱都是直接用 Arch Linux 的😏) ,这里列出几个咱见过的集成开发环境.

  • C-Free 好像是中国人开发的 IDE,好想要付费的样子 🤔
  • Code::Blocks 跨平台的自由软件。
  • Dev-Cpp 也是跨平台的自由软件. (话说学校的电脑里明明装着 Dev-Cpp 为啥还用 VC6 (╯ ̄﹏ ̄)╯ ┻━┻ )
  • Visual Studio ,这其实是个大型 IDE,对初学者来讲太重了些。不过最近更新的 Visual Studio 2015 Update 1 加入了 clang 作为编译器的功能,也可以拿来做 C 编译器啦~

GCC+文字编辑器?

其实上面提到的 IDE 里面一定是有编译器的,多半是GCC😂

其实 GCC 是有向 Windows 移植的,就是 MinGW 啦:

MinGW(Minimalist GNU for Windows),又称mingw32,是将GCC编译器和GNU Binutils移植到Win32平台下的产物,包括一系列头文件(Win32API)、库和可执行文件。

另有可用于产生32位及64位Windows可执行文件的MinGW-w64项目,是从原本MinGW产生的分支。如今已经独立发展.

---- Wikipedia:MinGW

实际应用上咧,多半会有已经打包好的 MinGW,可以帮助汝快速的准备工作啦~,例如 tdm-gcc

然后就是找个合适的文字编辑器啦~ 无论是 Atom , Visual Studio Code , 或者 Notepad++ 等等,挑一个自己顺手的就行啦~


好吧咱又算 抛砖引玉(挖坑) 了一次 😂😂😂

by ホロ at June 12, 2016 04:00 PM

百合仙子

SIGHUP, nohup, disown 以及 expect + sudo + bash + ssh

本文来自依云's Blog,转载请注明。

这些东西都和终端消失的时候(比如 ssh 连接中断)有关,但是细节上又各有不同。

nohup,去 coreutils 看源码就知道,是忽略 SIGHUP 然后 exec 相应的命令。信号处理器如果被设置成忽略,那么在 exec 之后依旧是忽略(与设置成用户自定义函数的情况不一样)。man 7 signal 可以看到说明。

disown 这个,我去看 zsh 的源码了。然而只看到 zsh 把进程从它的任务列表里删掉了,根本没提 SIGHUP 的事情。后来看到这个答案才知道原来 shell 也会发 SIGHUP 信号。

当然内核也会发 SIGHUP。查阅 drivers/tty/tty_io.c 可知,内核会给 session leader 及其组发 SIGHUP 和 SIGCONT,也会给前台进程组发,但是不会给后台进程组发 SIGHUP。那个是 shell 发的,所以 disown 之后后台进程就不会被 SIGHUP 干掉了。

所以,前台进程组如果没有被信号杀掉的话,会收到两次 SIGHUP 信号,一次 SIGCONT 信号。而后台进程组只会收到一次 SIGHUP。disown 过的不会收到任何信号。当然那些没死的进程,如果去读写终端,还是会得到 EIO 错误,写的时候还会收到 SIGPIPE 信号。

strace 可以观察到这些过程。

最后一个,出了问题。通过 expect 调用 sudo,然后登录服务器。终端断开时,expect 被 SIGHUP 杀死。sudo 会把用户发的信号传给它的子进程,但是内核发的不传。而 zsh 给 sudo 发信号时会因为权限原因而发送失败。于是后边的 bash 和 ssh 都会收不到 SIGHUP 信号。但是终端消失它们是能感知到的,所以这个出问题的进程树才这么深嘛。ssh 发现终端消失了,它干了什么呢?当然是通知对端终端没啦,然后等回复。对端 sshd 收到消息之后说,「哦哦,我去把 /dev/ptmx 给关掉。」于是 sshd 关掉了三个 /dev/ptmx 中的其中一个。所以这个 sshd 下的 bash 进程并不会得到 EIO 错误,还继续跑着。于是 sshd 还继续等着它跑完。于是这边的 ssh 还在等对端的 sshd 回复。于是这棵进程树就 hang 在这里了……

结论:还是 systemd 好啊,会话关闭时直接干掉这个会话启动的所有进程。需要在会话结束之后依旧运行的,自己用 systemd-run --user --scope xxx 启动就好。留下这些 sudo、ssh、bash 的还好,占用的资源不多。supervisorctl 这种的就囧了,死循环地读 stdin 又读不到东西,浪费一颗 CPU。

by 依云 at June 12, 2016 10:24 AM

June 05, 2016

Issac Ge (Tech)

只有 Python 高手知道的 tuple

熟悉 Python 的人都知道,它从语法上支持的内置数据结构一共四种,即 tuple, list, dict, set 等, sequence comprehension 一共有三个,唯独没有 tuple comprehension, 其形式被解析为生成器表达式,而且表示单元素的 tuple 也很不一样,需要额外添加一个在新手看来十分碍眼的逗号(1,).

但其实我们只简单地把 tuple 理解为一个 immutable 版 list 了,并没有深刻理解到它的本质。推上有人如此一针见血地指出:

我终于发现了,tuple 既可以当数据结构,又可以当模式来匹配变量。所以 tuple 说穿了是一个「不规则又不可变的数据结构或模式」,自然没有「推导规律」介入的余地,也难怪没有所谓的 tuple comprehension 了。

一旦洞察 tuple 的本质后,您就发现,tuple 原来大有文章:

其一,事实上,返回多个值的函数实则是在返回一个 tuple, 只不过可以省略括号而已。一旦理解透这个,就不会再写出 tp, label_tp = [], [] if len(result) == 0 else zip(*result) 这大坑了。

其二,只有一个变量的 tuple 在模式里可谓等价于变量本身,于是不是说 (1,) 里的逗号多余,而是它本身的括号就多余,毕竟没人爱写 (a,) = (b,); 其实 () 才是唯一真正特殊的 tuple; 于是纯括号就可以被名正言顺地赋予数学上的意义了,即 (a) 等于 a, 而且其实这还带来了方便 wrap line 的额外好处:

1
2
3
hfm_dir_str = (
'/home/acgtyrant/Projects/HamsterForMTK/'
'Hamster_Android_SDK/src/com/mapbar/hamster')

其三,虽说没多少人喜欢 (1,) 这写法,但我们可以分拆 sequence 值成多行,且每行后更有一个逗号!这对强迫症患者真是终极福音:

1
2
3
4
5
6
7
8
9
10
11
12
phodopus_evaluate_command = (
command_pathname,
'-v', video_pathname,
'--proto', proto_pathname,
'--model', model_pathname,
'--mean', mean_pathname,
'-c', cascade_model_pathname,
'--lf_proto', lf_proto_pathname,
'--lf_model', lf_model_pathname,
'--lf_mean', lf_mean_pathname,
'--noshow',
)

于是我习惯分拆函数的超长形参列表多行了,且最后一行以右括号结尾;多行的 sequence 值则倒数第二行以逗号结尾,倒数一行以右括号结尾且不缩进。

其四,tuple 不光可当安全的 immutable 数据结构,而且效率公认比 list 好

此外,tuple 在模式匹配上也威力十足:

其一,方便交换变量:a, b = b, a, 毕竟等价于 (a, b) = (b, a) 模式匹配嘛。

其二,我在 坑坑重重的 Extended Iterable Unpacking 已提到过 PEP 3132 – Extended Iterable UnpackingPEP 448 – Additional Unpacking Generalizations, 您会发现原来它们也不过是模式匹配嘛。此外,我们倒不能直接用星号 unpack generator, 但照样可以模式匹配 a, *_ = range(10), 毕竟只要后者能迭代就行了。现在看来,由于我已经洞察了 tuple 的本质,对它原本的坏印象也没有了。

其三,如果您想要可读性更好的模式匹配,可以试试 collections.namedtuple 库。

最后谢谢 @lilydjwg 和 @catsinrain 对我原推的启发,详见此推文的 timeline:

Written with StackEdit.

熟悉 Python 的人都知道,它从语法上支持的内置数据结构一共四种,即 tuple, list, dict, set 等, sequence comprehension 一共有三个,唯独没有 tuple comprehension, 其形式被解析为生成器表达式,而且表示单

June 05, 2016 09:13 AM

June 02, 2016

Issac Ge (Tech)

坑坑重重的 Extended Iterable Unpacking

学 Python 久了,就渐渐地发现了它的一些瑕疵,比如园括号不像方括号和花括号一样,即表示包含一个元素的 tuple 时要加碍眼的逗号 (1,), 贯彻推导语法时返回的是生成器而不是 tuple; 缩进不与作用域等价;现在我又发现,Extended Iterable Unpacking 也算是个坑。

$ ipython
Python 3.5.1 (default, Mar  3 2016, 09:29:07) 
Type "copyright", "credits" or "license" for more information.

IPython 4.2.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

 In [1]  a = ''.split()

 In [2]  a
 Out[2]  []

 In [3]  a = 'a'.split()

 In [4]  a
 Out[4]  ['a']

 In [5]  a, b = 'a'.split()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-703eacb578ed> in <module>()
----> 1 a, b = 'a'.split()

ValueError: not enough values to unpack (expected 2, got 1)

 In [6]  a, b = 'a b'.split()

 In [7]  a, b
 Out[7]  ('a', 'b')

 In [8]  a
 Out[8]  'a'

 In [9]  b
 Out[9]  'b'

 In [10]  a = *['a']
  File "<ipython-input-10-78ebc69aca60>", line 1
    a = *['a']
       ^
SyntaxError: can't use starred expression here


 In [11]  a = ['a'][0]

 In [12]  a
 Out[12]  'a'

您看出来了吗?左边的变量有一个时,不 unpack, 直接 binding 整个 sequence, 而不是 sequence 里的第一个 元素;若要 biding sequence 里的第一个元素,只能通过索引引用,没有 unpack 的余地;当所要 biding 的变量有两个以上时,就 unpack sequence 并各自绑定各自的了,但数量要对得上!除非用星号匹配。于是这语法就和括号一样反直觉了。

此外 Python 3.5 实现了 PEP 448 – Additional Unpacking Generalizations, 用起来倒是舒服。

最后出题考读者:

tp, label_tp = [], [] if len(result) == 0 else zip(*result) 有什么惊天大坑?在 Disqus 回复即可,答得好的同学奖一个 featured comment 和 vote.

Written with StackEdit.

学 Python 久了,就渐渐地发现了它的一些瑕疵,比如园括号不像方括号和花括号一样,即表示包含一个元素的 tuple 时要加碍眼的逗号 (1,), 贯彻推导语法时返回的是生成器而不是 tuple;

June 02, 2016 02:13 AM

May 30, 2016

Issac Ge (Tech)

要先判断 zip 接收的是不是空集

1
2
3
4
5
tp, label_tp = zip(*[
(log_rect, label_rect)
for log_rect in log_rects
for label_rect in label_rects
if _is_same_target(log_rect, label_rect, overlap_rate)])

您看出来这有什么陷阱了吗?当列表为空时,zip 函数的返回值就只有一个,即 label_tp 没有可以被 biding 的对象。

除了主动事先判断返回值的长度,似乎没有更好的办法了。

Written with StackEdit.

1
2

May 30, 2016 03:01 AM

不存在所谓的 with 作用域

自从开始用 with 管理资源后,我产生了一种致命的错觉:缩进等价于作用域,尤其是 with 语句会构成一种作用域。于是我对以下代码大吃一惊:

1
2
3
with open('.zshenv') as file_:
a = file_.read()
print(a)

a 居然可以在其所定义的上一层代码块访问到!当然,file_ 也可以访问,虽然已经被关闭了。于是说穿了,不存在所谓的块即作用域,函数才是元作用域单元。话说回来,这反常算是 Python 缩进语法的美中不足吧。

于是我就只在 with 语句处理和资源有关的部分了,其他语句挪到和 with 同等缩进的代码块里,有必要时就提前定义变量

Written with StackEdit.

自从开始用 with 管理资源后,我产生了一种致命的错觉:缩进等价于作用域,尤其是 with 语句会构成一种作用域。于是我对以下

May 30, 2016 02:54 AM

May 29, 2016

ヨイツの賢狼ホロ

MediaWiki 网站搬家记

如何把 MediaWiki 网站搬到另外一个服务器上?

这篇纯粹是来凑数的2333~

第一步:备份数据库 ......

说实话咱只用过 MySQL/MariaDB 😂,所以 mysqldump 解决 😂

# 这里用了一个重定向标准输出到某个文件
# mysqldump [连接数据库的各种选项,例如用户名啥的] [数据库名称] > somefile.sql
$ mysqldump -u wikiuser -p somedb > somefile.sql

然后输入密码,稍等片刻就会发现汝的当前目录下多了个文件 (例如 somefile.sql ),这就是导出的数据库啦~

第二步:传输文件

假设汝的 MediaWiki 安装在 /path/to/mediawiki 😂

如果汝能物理访问汝的两台服务器, 那就直接把 /path/to/mediawiki 和上一步备份的 SQL 转储复制过去不就好啦~ (╯・ω・)╯ ┻━┻

或者如果汝能用 SSH 连接两台服务器的话,可以试试这个:

tar czf - /path/to/mediawiki | ssh username@server tar xzf - -C /path/to/mediawiki

这一行命令做了这些:

  • 把 /path/to/mediawiki 打包成归档文件,不过输出到标准输出.

    (千万别说汝不知道啥叫管道以及管道怎么用) 😂

  • 通过 ssh 连接到目标服务器.后面是连接到服务器上以后执行的命令.

  • 后面的 tar 命令解开一个归档文件,中间孤独的 hyphen ("-") 表示要解开的文件来自标准输入. -C 参数用于改变解开到的目录.

别忘了把转储的数据库文件也 copy 过去😂

然后输入密码,稍等片刻 again ......

如果不行的话,那就传统的 FTP Copy 过去,就是可能慢点 😂

第三步: 还原数据库备份

mysql (MariaDB 也是这个命令):

# 这里用了一个重定向某个文件到标准输入
# mysql -u [用户名] -p [数据库名] < somefile.sql
$ mysql -u wikiuser -p somedb < somefile.sql

一些收尾工作

  • 数据库连接信息变了就去 LocalSettings.php 里改😏
  • 连外网的就去改 DNS 😂

好了大概就是这个 样子😂😂

by ホロ at May 29, 2016 04:00 PM

百合仙子

配置 Postfix 通过外部 SMTP 服务器发邮件

本文来自依云's Blog,转载请注明。

程序要发邮件。

我不想自己去连外部 SMTP 服务器,因为我懒得自己去处理各种错误。我们服务器上很多程序用的是 heirloom mailx 软件的 mail 命令。结果是有些服务器上有好几个甚至几十个 mail 进程卡在那里了。还有不知道通过什么东西发邮件的,偶尔会有邮件没发出来,发出来了的还因为在一个字符的多个字节之间换行再编码导致 mutt 和 Android 的 GMail 程序显示为乱码的。

所以我要用 Postfix,让它来处理这些杂事。之前只把 Postfix 用作普通的 SMTP 服务器过。然而现在目标邮寄地址是腾讯企业邮箱,对由子域名发出的邮件很不友好,老是扔垃圾箱里,连加白名单都没用……于是搜了一下,Postfix 是可以作为客户端登录到 SMTP 服务器来发信的。不过资料比较少,好不容易配置好了,自然要记录一下。

要登录腾讯企业邮箱发信,main.cf 里写上:

relayhost = [smtp.exmail.qq.com]:587

smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_use_tls = yes
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_sender_dependent_authentication = yes
smtp_generic_maps = hash:/etc/postfix/generic

/etc/postfix/sasl_passwd 里边写用户名和密码,比如 user@example.com 用户的密码是「password」,就这么写:

[smtp.exmail.qq.com]:587 user@example.com:password

/etc/postfix/generic 里配置信封上的发件人(MAIL FROM 命令)的地址重写,不然腾讯不收:

@hostname user@example.com

hostname 就是 Postfix 里那个 myhostname,默认是机器的主机名。这句配置的意思是,本来发件人地址是这个主机名的,全部改写成 user@example.com 这个。

然后生存 hash 数据库,并更改权限(更好的做法当然是创建的时候就弄好权限):

postmap /etc/postfix/sasl_passwd
postmap /etc/postfix/generic
chmod 600 /etc/postfix/sasl_passwd*

就绪,启动或者重新加载 Postfix 就可以了:

systemctl reload postfix

by 依云 at May 29, 2016 07:57 AM

May 28, 2016

Felix Yan

Pacman Hooks 简介

Pacman 5.0 带来了 Hooks 支持,但在大规模应用前,我们留出了一个多月的时间来让用户先升级到 Pacman 5.0(因为同时升级 pacman 和有定义 hooks 的包会导致无法正常执行这些 hooks)。现在距离 Hooks 正式投入使用已经过去了一个月,我觉得是时候介绍一下 Hooks 和如何使用它了。

先来看一个简单的 Hook:

[Trigger]
Type = File
Operation = Install
Operation = Upgrade
Target = usr/lib/tmpfiles.d/*.conf

[Action]
Description = Creating temporary files...
When = PostTransaction
Exec = /bin/sh -c 'while read -r f; do /usr/bin/systemd-tmpfiles --create "/$f"; done'
NeedsTargets

这个 Hook 的作用是:当检测到安装或更新的包文件中存在 usr/lib/tmpfiles.d/*.conf 时,在更新后对每个文件调用 systemd-tmpfiles --create 方法。前面的检测部分定义在 [Trigger] 部分,后面执行的操作定义在 [Action] 部分。下面我们分别了解一下这两部分。

一、[Trigger] 部分

首先需要了解的是可以用于触发的条件类别(Type)。上面的例子里使用了文件(File),即当操作中的包中存在对应文件时触发。另一个可选的 Type 是软件包名(Package),即直接匹配操作中的包名。

接下来,操作(Operation)选项限制了对软件包的操作类别。可以选择的操作有安装(Install)、更新(Upgrade)和删除(Remove)。一个 Hook 需要在多种操作执行时,如例子中那样写成多行即可。常用的组合有三种全部写上(更新缓存、数据库等)、写 Install+Upgrade(执行安装时的一次性操作)及与之对应的 Upgrade+Remove(卸载时的一次性操作)。

最后,我们需要定义具体的目标(Target)。如果目标是文件,这里需要写其相对根目录的完整路径,但需要去掉开头的 / 字符。通配符(*、?)可以使用,具体匹配时会使用 fnmatch 方法。同样的,在一个 Hook 中可以定义多个目标,类似例子中的 Operation 那样写成多行即可。

二、[Action] 部分

先看看 Hooks 的执行时机:

2016-05-28-130821-7661a5

可以看到,有两类明显不同的 Hooks: Pre-transaction Hooks 和 Post-transaction Hooks。

Pre-transaction Hook 在具体操作发生前执行,此时待升级的软件包还未被升级,待删除的软件包还未被删除,还可以让它们来绽放最后的光芒。因此,这种 Hook 通常和上面 [Trigger] 部分的 Upgrade、Remove 操作搭配使用。如 gconf 包的 gconf-remove Hook,会在 gconf schema 被删除前调用 gconfpkg --uninstall 命令来卸载对应的 schema。

Post-transaction Hook 则与它相反,是在操作完成后执行。如上面的 tmpfiles Hook。

这两种不同的类型被定义在 When 选项中,分别写作 PreTransaction 和 PostTransaction

Description 选项仅包含一个供人类阅读的描述信息。目前的通用做法是用动词进行时作为开头,英文省略号作为结束。显示在终端中会成为这样的效果:

(1/1) Creating temporary files...

Exec 选项定义了具体执行的命令。和上面 Target 选项不同,这里不但需要写出待执行命令的完整路径,还需要保留最前方的 / 字符。如果在命令中需要用到前面 Trigger 得到的具体结果(如上面例子),你还需要在 [Action] 部分写一行 NeedsTargets 来让被匹配到的目标成为 Exec 选项的 stdin 输入,一行一个。值得注意的是如果匹配到的目标是文件,我们在对它进行操作前也需要补上最前方的 / 字符,如上面例子中使用的 "/$f"

此外,[Action] 部分还有一些其他选项:

  • Depends 选项:定义 Hook 运行时需要的依赖。如果触发时对应依赖关系不满足,Hook 会拒绝运行。可以定义多次。
  • AbortOnFail 选项:当 Hook 执行失败时终止整个操作。这个仅对 Pre-transaction Hook 有效,毕竟 Post-transaction 发生在操作之后,定义这个选项没有意义。这个选项和 NeedsTargets 选项一样不需要任何参数。

总结

姗姗来迟的 Hooks 功能替代了许多原本在 .install 文件中定义的操作,大幅减少了在每个包中重复写这些操作的困扰,也节省了大量重复执行操作浪费的时间。目前有很多常见操作已经采用了 Hooks,但还有很多仍然在完善中。如果你在用的 AUR 包还没有采用这些 Hooks,请不要犹豫,赶快改改拍在维护者脸上吧!

关于哪些通用操作已经采用了 Hooks,可以参考这个 Wiki 页面。此外,如果想找更多 Hooks 的例子来研究,可以打开本地的 /usr/share/libalpm/hooks/ 目录,你已经安装的 Hooks 都在这里。

参考资料:上文中的 Wiki 页面,以及 pacman 源码

by Felix Yan at May 28, 2016 06:05 AM

May 24, 2016

Issac Ge (Tech)

在 Python 里小试 Optional 手法

Python 天生不支持 Option 类型,typing 有个 Optional, 但也就只能用来当 type hints 而已。

当然,这并不妨碍我们自行贯彻 Optional 手法。今天我写的函数 parse 会把所有 *_pathname 都打开并解析其内容,它有四个可选参数,其中三个的默认值是 None.

1
2
3
4
5
6
7
def parse(
log_pathname,
label_pathname,
tp_pathname=None,
fp_pathname=None,
fn_pathname=None,
overlap_rate=kitti_rate):

也就是说用户可以直接调用 parse(log_pathname, label_pathname), 即不打算提供剩下的参数。这时 parse 可以自发构造临时文件并代替所要打开的文件,前者当然是空的,于是不怕照常被解析。

于是我们就需要判断对象是否为 None, 是则继续沿用原来的值,反之则用指定默认值的函数了,即类似于:

1
2
3
4
5
6
7
8
9
def a(b, c):
if b is None:
return c
else:
return b
d = None
a(d, 1)
e = 2
a(e, 1)

显然 a(d, 1) 为 1, a(e, 1) 为 2.

我看了支持 Optional 的编程语言,Haskell 用 fromMaybe(大概?),Rust 用 unwrap_or, C++17 用 std::optional::value_or(顺便独家爆料下,起这函数名的同行就在 C++ 众里,真是吾辈的福气)。

虽说 Python 没有这样的函数,但已经有足够简单好用的表达式了a = b or c.

言归正传,光判断 *_pathname 还不够,得用 tempfile.NameTemprorayFile 充当前者为 None 时所打开的文件才行。于是我仿照 Rust 的 unwrap_or, 封装了一个特化函数:

1
2
3
4
5
def _unwrap_or_tempfile(pathname, mode='r'):
if pathname is None:
return tempfile.NamedTemporaryFile(mode=mode, delete=False)
else:
return pathname.open(mode)

最后,其实 Python 标准库也有若干当对象为 None 时就返回指定 default 值的函数:next(iterable[, default]), dict.get(key[, default])dict.setdefault(key[, default]) 等等。于是我们可以在需要时,贯彻这样的 Optional 手法。

Written with StackEdit.

Python 天生不支持 Option 类型,typing 有个 Optional, 但也就只能用来当 type hints 而已。

当然,这并不妨碍我们自行贯彻 Optional 手法。今天我写的函数

May 24, 2016 09:23 AM

May 21, 2016

百合仙子

当 SSD 坏掉之后

本文来自依云's Blog,转载请注明。

某天,我注意到系统日志中有如下报错:

ata2.00: exception Emask 0x0 SAct 0x80 SErr 0x0 action 0x0
ata2.00: irq_stat 0x40000008
ata2.00: failed command: READ FPDMA QUEUED
ata2.00: cmd 60/18:38:64:ad:96/00:00:00:00:00/40 tag 7 ncq 12288 in
         res 41/40:00:64:ad:96/00:00:00:00:00/00 Emask 0x409 (media error) <F>
ata2.00: status: { DRDY ERR }
ata2.00: error: { UNC }
ata2.00: configured for UDMA/133
sd 1:0:0:0: [sdb] tag#7 UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x08
sd 1:0:0:0: [sdb] tag#7 Sense Key : 0x3 [current] [descriptor] 
sd 1:0:0:0: [sdb] tag#7 ASC=0x11 ASCQ=0x4 
sd 1:0:0:0: [sdb] tag#7 CDB: opcode=0x28 28 00 00 96 ad 64 00 00 18 00
blk_update_request: I/O error, dev sdb, sector 9874788
bcache: bch_count_io_errors() sdb1: IO error on reading dirty data from cache, recovering
ata2: EH complete

啊,看来我的 SSD 要坏掉了么?!拿 bcache-status 看了一下状态,已经500多个报错了,但是我并没有遇到什么问题。看了一下 SSD 的 SMART 信息,也是500多个报错。这种报错出现已经有几天了,但是似乎影响并不大?SMART 报告也说「状况正常」。那就等有时间再处理好了,先把 bcache 缓存策略从「writeback」改成「writethrough」好了。我当时是这么想的。

出事的 SSD 是笔记本自带的,16G,被我用作缓存了。使用的是 bcache,一年之前我写文章讲过的。没想到刚刚一年,就开始出问题了。

过了一两天之后。我正上班中,同步 MediaWiki 数据时发现自己的机器又连不上了。我起初以为是网络问题,因为我记得很清楚我的机器是开着的。但是过了一会儿它还是不能访问。我 ping 了一下,却发现是通的!登陆到我作为路由器的树莓派上却发现,网络是正常的。能 ping 通笔记本,但是从树莓派上也 ssh 不了,访问 nginx 也没回应。所以笔记本还在线,但是系统出问题了。奇怪的是,访问另一端口上我用 Tornado 写的 Web 程序时却是正常的。

终于等到了下班。回到家里之后就听见笔记本风扇呼呼地响着。赶紧打开查看。htop 显示 journald 正在使用 CPU。于是去看 journald 日志,心里顿时凉了半截:日志只记录到上午,但满是上边那样的 SSD 报错。进一步的检查发现,/ 分区已经被挂载为只读,syslog-ng 日志比 journald 日志记录了更多的报错。火狐已经不知道什么时候挂掉了,并且启动不了。sudo 还是好的,但是运行 zsh 时会段错误。运行 bash 的话,会报一点错,可以看到有些文件已经变成无意义的数据了。bash 能启动,但是很奇怪的是,输入不了字符 e……想起还装了 dash,于是用这个连最基本的补全都没有的 shell,配合还没有挂掉的连着 VPS 的 mosh 上的 IRC 上网友们的帮助,尝试禁用 SSD 缓存。

结果是失败了。关于 bcache 有些资料与我看到的情况并不一致。重启会报一些错,然后我进入了 initramfs 里的 shell,尝试禁用 SSD,依旧失败中,脏数据写不回去,所以禁用不了缓存……不过看到了缓存中脏数据只有几百K。当然单位是什么我就不知道了……

放弃。又一天,我改从救援系统进入。记得有个工具能把普通分区转成 bcache。手机上网找到了,blocks。但是它并不能把 bcache 转回来。好在是开源项目,我读了一下代码,结合别人的说法,结论是:把普通分区转为 bcache,只要把分区缩小,在起始处空出一点空间,然后写入 bcache 的超级块就可以了。于是反过来,只要跳过 bcache 的超级块来读,就可以读到原来的分区数据了。

但是,bcache 超级块有多大呢?不知道。不过之前看到过一个扫数据的脚本,用类似的办法找一下分区数据的位置好了:

for i in {1..20}; do dd if=/dev/sda2 skip=$i | file -; done

file 显示在第8块的地方发现了「LUKS encrypted file」。这就是我要找的文件系统了!

为保险起见,先读读看。使用 losetup 把 /dev/sda2 映射成只读的 loop 设备,但是跳过开头的 8192 字节(dd 的块是 512 字节一个)。然后用 cryptsetup 解密。解密成功了。只读挂载解密之后的 ext4 文件系统。挂载成功了。看了一下内核日志,没有报错,没有警告。chroot 进去,正常,没有段错误,配置文件没有变成无意义的乱码。一切进行得好顺利!损坏程序比我以为的要轻不少呢!

为了确认损坏情况,我进行了一次模拟备份,也就是 rsync 的「--dry-run」选项。这样与最近的一次备份作比较,看看差异。结果很乐观,rsync 只报了十来个 I/O 错误。不过这也说明文件系统还是有问题的。

又一天。开始恢复系统了。还是从救援系统进入。进入 gdisk,删除原来的 sda2 分区,新建一个小了 8192 字节的分区。经验表明这样子删掉再重建分区表是没有问题的。也确实没出什么问题。不带 bcache 的文件系统出来了。解密之,然后使用 fsck 修复。修复过程中,fsck 问了我一大堆是不是要修复的问题。修复完毕之后,更改内核选项以便适应新的分区表,重启。

一切正常。不过根据之前 rsync 和修复过程中提到的文件名,去看了一下那些文件。都是最近更新系统时的一些 Python 文件。有一些文件消失了,另一些文件的权限和类型变得很奇怪。删掉,重装安装对应的软件包。完事了~不过没有了 SSD 缓存,能够感觉到有些操作会慢不少。

这 SSD 也真容易坏啊。刚刚一年呢。而且坏的过程很快,预警期只有几天。现在 SMART 报告已经出现过1000多个错误了,但整体评估还是「磁盘状况正常」……

好在我用的都是自由软件,虽然可能找遍整个互联网都没有个说法,但是还有实现它们的源码可以阅读,可以自己去思考解决方案。当然啦,就算这个 bcache 完全坏掉了,我也不需要太惊慌,因为我有备份嘛,更麻烦,但最多只损失几天的数据,不会突然之间什么都没有了。

by 依云 at May 21, 2016 08:45 AM

May 17, 2016

Issac Ge (Tech)

御用 Path 规范

我曾经写过御用文件 IO 命名规范,那时给文件对象名起个 file 后缀,即 *_file, 且规定:凡格式贯彻 *_filename, *_pathname*_dir 的 identifier 都一定指向 str 对象,且当时只考虑 Linux 上的路径拼接,自然直接用 / 当 sep.

不过如今用 Python 处理路径多了,不免开始考虑模块化,对应的则有经典 os.path 库,但 JaHIY 推荐了 Python 3.4 新出的 pathlib, 我试了下,发现明显比前者好用多了,有很多有用的函数,比如 PurePath.suffix, PurePath.parent PurePath.name, PurePath.with_namePurePath.home 等等,此外直接用除法符号当拼接路径的操作符也令人眼睛一亮。于是我重新制定了基于路径上的新命名规范:

其一,所有 *_filename, *_pathname*_dir 的 identifier 都统统用 Path 类型,用没有 IO 副作用即不影响文件系统的子类型 PurePath 也可以。

1
home_dir = Path.home()

其二,pathname 一样用绝对路径,filename 用不包含任何目录分隔符的相对路径。不论是不是目录,都不再加额外的目录分隔符后缀,比如 /, 当然,文件名还是要加 suffix.

其三,拼接目录用 /, 必要时还可以用括号来 wrap line:

1
2
3
4
testset_dir = home_dir / 'BigDatas/daytime/testset'
cascade_model_dir = (
rp_dir
/ 'models/cascade_models/20x20-HAAR-14-0.99-0.5')

其四,虽说核心对类型是 Path 而不再是 os.path 所处理的 str, 好在互相转换也方便,只要在外围把 Path 类型对象传入接收 str 对象的函数时,再使用 str 函数转换即可,就和外围处理具体编码内部处理 Unicode 一样,甚至也可以用 map 来一气呵成地转换;反之亦然,即用 Path 函数转换,甚至可以无缝地直接套在原本的 format 函数上:

1
filename = Path('{}{}{}'.format('cascade', num_stage, '.xml'))

话说要是 Python 内置库自发支持 pathlib 就好了,这样不用在 open 里显式转换为 str 对象了,直接传路径来来去去,多爽!

其实 pathlib 还封装了 Path.open 函数,多谢 JaHIY 的提醒。

其五,为了照顾不熟悉 pathlib 的同行,可以用 type hints 来强调您所期望的 filename, pathnamedir 等类型为 Path.

其六,其实只要遵循以上编程规范,跨平台自然也就水到渠成了。

Written with StackEdit.

我曾经写过御用文件 IO 命名规范,那时给文件对象名起个 file 后缀,即 *_file, 且规定:凡格式贯彻

May 17, 2016 02:20 AM

May 16, 2016

Issac Ge (Tech)

大话类型之乱伦

性向来是人类文明的禁忌,那是因为一旦放开这禁忌,那么「乱伦」会由于成本小而变得泛滥成灾,对人类群体的利益往往弊大于利,比如大脑与身体都尚未成熟的儿童怎么保护好自己的性权利?尚未经济独立的早恋少女怎么分娩并抚养子女?婚生子女和私生子之间怎么划分财产?同性恋怎么繁殖后代?性反转人士怎么上厕所?更别说近亲繁殖的子女往往具有基因缺陷了。

同理,在编程语言中,类型的乱伦行为也是大忌。一个类型家族的对象与另一个类型家族的对象发生关系,繁殖出新对象,如果父母彼此没有血缘(继承)关系,那么跟谁姓(类型),继承什么财产(属性)也比较好办,只要有章(语法与源代码)可循就行了,比如 C++ 用 operator 函数来规定双亲的繁殖行为。反之呢,乱伦现象就产生了!

事实上,我不觉得 Python 是真正意义上的强类型语言,因为它的 bool 是 int 的子类,且彼此可以发生关系。原则上不同类型的对象不等值,但 Python 里 1 == True 返回 True, 而且 bool 与 int 类型可以进行四则运算,如果 True/False 真单纯被转换 int 类型且运算结果是 int 好了,但事实上 1 + False == True 依然返回 True! 和直觉很不符,也就是说您很难说清 bool 与 int 的私生子到底跟谁姓,其值到底是什么,所以我才说这叫乱伦嘛,弊大于利,所以我就一直避免这种运算。

同理,对一切类似的乱伦行为保持警惕。比如 C++ 的多重继承语法可能不好用,因为既然父母彼此生殖隔离,那就很难明确子女到底继承了什么样的基因(属性),说难听点就是个怪胎;还有,虽说 Python 支持在 if 语句里调用对象的 __bool__(), 但您凭什么认为一切人都是男的?不光有天生的女性,也有爱女装的伪娘,您又是否有主宰后者上哪厕所的权利?所以说到底不要指望一切类型都显式支持 __bool__, 可读性也不好,所以我便习惯在 if 语句里只用纯粹的 bool 类型对象。

Written with StackEdit.

性向来是人类文明的禁忌,那是因为一旦放开这禁忌,那么「乱伦」会由于成本小而变得泛滥成灾,对人类群体的利益往往弊大于利,比如大脑与身体都尚未成熟的儿童怎么保护好自己的性权利?尚未经济独立的早恋少女怎么分娩并抚养子女?婚生子女和私生子之间怎么划分财产?同性恋怎么繁殖后代?性反转

May 16, 2016 04:55 AM

御用文件 IO 命名规范

Update: 御用 Path 规范 有 break 本规范。

我琢磨了一会该怎么命名文件 IO 上相关的对象,想好后,御用文件 IO 命名规范如下:

  • file 指被任意现代常规文件 IO 函数(比如C的 fopen(), C++ 的 ifstream() 和 Python 的 open()等)打开的文件对象名,被打开的文件可以是文本文件或二进制文件。
  • 用非常规文件 IO 函数打开文件时,一般用返回值的类型名来命名。比如:fd 指被 POSIX 底层文件 IO(比如C的 open() 和 Python 的 os.open()等)打开的文件描述符对象名;举一反三,可以用 image 命名 OpenCV 的 cv::imread() 打开的 cv::Mat 对象,可以用 dir 命名 POSIX 的 opendir 打开的 DIR * 变量,可以用 socket_fd 命名 POSIX 的 socket() 打开的 socket 描述符等。尽量别用缩写
  • filename只包含文件名、不含任何路径(包括相对路径)的字符串对象名。
  • pathname 指包含绝对路径的文件名的字符串对象名。
  • file, fd, img, dir, socket_fd, filename, 和 pathname均加前缀,以进一步区分,比如 image_filename, samples_pathname 等;不过,若只是个在函数内用的临时变量,也可以不用加,方便;也可以再加 s 后缀,以表明它在 Python 中可能是对应的 list, 在 C++ 中则可能是对应的 std::vector 容器等。
  • 不论字符串对象是 filename 还是 pathname ,如果字符串值中的文件是目录,一定要加 / 后缀;否则,就加文件格式后缀。
  • 在项目用文件 IO 函数时,如果要处理的文件和项目源代码无关,则必传 pathname 字符串对象;反之,可以用 filename 字符串对象,必要时再追加表示相对路径或绝对路径的字符串对象。

Written with StackEdit.

Update: 御用 Path 规范 有 break 本规范。

我琢磨了一会该怎么命名文件 IO 上相关的对象,想好后,御用文件 IO 命名规范如下:

May 16, 2016 04:01 AM

Python 作用域解析之补遗

有人把 Python 作用域解析规则总结为 LEGB, 确实够精炼简要。但我还要继续补遗:

其一,所谓 global 命名空间,都是隶属某模块名的。于是当解释执行(注意没有加 -m 参数)某 Python 源代码文件,或在交互式环境里,这个文件或交互式环境本身所谓的 global 命名空间,其实同样隶属一个模块,它的名字就叫 __main__. 如果您在被解释执行的文件或交互式环境定义一个函数对象 a, 那么 print(a.__module__) 会返回一个 str 对象,其值为 __main__. 说来好笑,我曾经纳闷有什么办法能访问到这模块,后来想想,其实我本来不就在文件和交互式环境本身里面啊,当然能随便直接访问了。

其二,import a, print(a.b) 很好理解,会先在 __main__ 模块解析到 a 这模块的名字,接着就在后者的 global 命名空间继续解析到 b.

其三,print(sum.__module__), def sum(): pass, print(sum.__module__) 会先后输出 __builtins____main__, 但这不是因为 rebinding 了 builtins 命名空间的 sum ,而是在 __main__ 模块的 global 命名空间定义了 sum 对象且后者被先解析到而已。此外您也可以__builtins__ 当成模块对象(注意不是 str 对象)来访问它 global 命名空间的值,比如 print(__builtins__.__dict__) 就返回一个字典对象,后者把 str 对象映射为您可以访问的内置对象。说起来其实这里很微妙,因为 __builtins__ 本身应该被解析为 __main__ 模块 global 命名空间的某对象了,但您并没有 import 它,也就是说它从一开始就默认存在,但偏偏又不隶属「如同字面意义上所真正内置」的 __builtins__ 模块的 global 命名空间!事实上您还可以显式 import builtins, 再继续访问它的属性……比如 print(builtins.__dict__) 就返回和 print(__builtins__.__dict__) 一样的值。

其四,del 可以在 __main__ 的命名空间删掉对库的引用,比如 import sys 后再 del sys, 您会发现 sys 库又访问不到了,可谓变相的 unimport. 那么 del __builtins__ 会发生什么?您在 __main__ 模块的 global 命名空间删掉了对 __builtins__ 的引用**,您自然没法用 int, str 之类的内置对象了,而且连 import builtins as __builtins__ 之类的补救方案都执行不了,因为连 __import__ 都找不到了。何等丧心病狂的 hack!

其五,from a import * 应该会直接把 a 模块所有 global 变量归属到 __main__ 模块的 global 命名空间,但是您如果试试输出模块 m 里的 b 函数所属的模块名的话,即 print(b.__module__), 它返回 m 而不是 __main__; 此外,如果 mn 各有函数 b, 那先后 from m import * from n import * 的话,那 print(b.__module__) 返回 n. 我把这灾难叫做作用域偏移

最后总结编程规范:

  1. 禁止一切 from * import * 形式的语句
  2. 不要乱动一切以下划线开头的东西,自然包括 __builtins__.
  3. 通过 del 来 umimport 库。
  4. 不要在 local 或 global 空间命名和 builtin 空间某对象重复的 identifier, 可以在名字后面加一个下划线以区分,比如 str_.

Written with StackEdit.

有人把 Python 作用域解析规则总结为 LEGB, 确实够精炼简要。但我还要继续补遗:

May 16, 2016 02:19 AM

May 15, 2016

Issac Ge (Tech)

什么情况下 map 比 list comprehension 好?

事实上,list comprehension 公认效率比 map 好所以当 map 比 list comprehension 可读性好且不在乎性能时,可以优先用前者。

那问题又来了:什么时候 map 的可读性比较好?当且只当低阶函数是您所熟悉的 Python 函数,便利的 sequence 对象也够一目了然时。比如我就经常用它转换命令列表,够一气呵成:

1
2
3
4
5
6
7
8
traincascade_command = [
command_pathname,
'-w', weight,
'-h', height,
'vec', vec_pathname,
]
traincascade_command = map(str, traincascade_command)
subprocess.call(traincascade_command)

妈妈再也不用担心我不小心传 int, pathlib.Path 进命令列表了,写的 list comprehension 又长又臭得超出 79 个字符了。同理,rects = map(int, rect_strs) , positives = map(abs, integers) 之类的精炼表达式也可以。

因为您很清楚 str, intabs 等是一元函数,作用是什么;反之,即用您所不熟悉的 Python 函数,比如 a = map(b, c), 这时您往往会产生四重疑惑:

其一,b 是一个 callable 对象吗?
其二,b 可以只接受一个形参吗,即它到底是不是一元函数?
其三,c 是否为 sequence 对象?
其四,c 的 iterable 元素又是什么鬼?

更别说用雪上加霜的 lambda 了。

但换用 list comprehension 就没这问题:a = [b(d) for d in c], 显然 b(d) 表达了 b 彻彻底底是个一元函数,且 c 作为 sequence 对象时 iterable 元素是 d, 最终 a 会被 bind 到一个 list 对象。可读性更胜一筹。

举一反三,您可以琢磨什么情况下 filter, funtools.reduce 等也能如法炮制。

事实上,list comprehension 公认效率比 map 好所以当 ma

May 15, 2016 10:41 PM

May 12, 2016

ヨイツの賢狼ホロ

入手 Surface Book

这可不是oo什么的...... 😂😂

简单说就是咱搞了台 Surface Book 回来 (不是顶配所以不要说咱土豪啦😂😂

搞 Windows _(:з」∠)_

  • 升级到了最新的预览版 ( 用 Microsoft 账户登录就好)
  • 装了 Office 2016 (汝会明白为啥的😏
  • 把 osu! 复制到了 Surface Book 上 (用 Surface Pen 玩 osu! 的感觉真是酸爽😏

当然作为 Arch Linux 用户怎么不会去装 Arch Linux 呐?

  • 于是和 上篇文章 一样,用 Windows 内置的磁盘管理收缩了一个空闲分区出来. <(ノ=﹁"﹁=)ノ┻━┻

  • 因为懒得用 hashtool 给内核签名,于是咱直接关了安全启动:

    开机时按住音量加键和电源键进入 Sueface UEFI,在 "Security" 一节里把 "Secure Boot" 设置成 "Disabled" 就好.

装 Arch Linux ~(>_<~)

因为咱原来有个装着 Arch Linux 的移动硬盘,所以咱就计划直接把移动硬盘上的 Arch Linux 复制到 Surface Book 上.

但是因为 Linux 里其实是有些虚拟文件系统 ( 例如 /dev , /proc 一类的 ), 所以只好先用另一个 Arch Linux 的 Live ISO 启动 (╯ ̄皿 ̄)╯ ┻━┻

截至咱写这篇文章的时候, Arch ISO 里的内核 ( 像是4.4? ) 没法驱动 Surface Book 的键盘底座,所以坠吼搞一个 USB 键盘 😂
  • 首先按照 ArchWiki 的 Beginning Guide ,把刚刚分配出来的空闲空间新建一个分区.
  • 然后把原来的 Arch Linux 分区和新的分区挂载到两个位置 (假设源分区是 /mnt ,目标分区是 /target )
  • 接下来用 rsync 来同步内容:
# rsync的 -a 参数表示 "归档" 选项.
# -A 是保留 :ruby:`ACL|访问控制列表`
# -X 是保留扩展属性

# rsync -aAX /mnt/ /target

最后上一张图 😂

最后上一张图

by ホロ at May 12, 2016 04:00 PM

May 10, 2016

Phoenix Nemo

使用 Unbound 搭建更好用的 DNS 服务器

用了好久的 DNSMasq 方案终于在大半年前彻底炸掉了。

原因不光是 DNSMasq 性能和安全性完全不足以撑起公网缓存/递归 DNS 的任务,也有想要做反污染和加速的时候确实太蛋疼的问题。

现在使用的方案是 Unbound+DNSCrypt,外带一份加速列表。这段时间看来,不管在我本机还是在公网服务的两台,效果和反馈都很不错。

准备工作

需要的程序:

  • unbound
  • dnscrypt-proxy
  • makefile
  • git

makefilegit 用于处理 dnsmasq-china-list

Unbound 配置

修改文件 /etc/unbound/unbound.conf。没有这个文件的话,一般需要找一下软件包里提供的配置 example 文件复制过去。这里列出的仅包含需要修改的部分,其他的按照默认配置一般没有问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
num-threads: 2 # 线程数可以修改为物理核心数
interface: 0.0.0.0 # 侦听所有 IPv4 地址
interface: ::0 # 侦听所有 IPv6 地址
# 如果只需要本机使用,则一个 interface: 127.0.0.1 即可
so-rcvbuf: 4m
so-sndbuf: 4m # 本机使用的话,这俩 buf 可以取消注释
so-reuseport: yes # 如果开了多线程,就写 yes
msg-cache-size: 64m # 本机可以设置 4m 或者更小
rrset-cache-size: 128m # 本机可以设置 4m 或者更小
cache-max-ttl: 3600 # 建议设置一个不太大的值...专治各种运营商 DNS 缓存不服
outgoing-num-tcp: 256 # 限制每个线程向上级查询的 TCP 并发数
incoming-num-tcp: 1024 # 限制每个线程接受查询的 TCP 并发数
# 下面这四个不需要解释了吧,不想用那个就写 no
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
tcp-upstream: no # 默认是 no,隧道状态比较稳的话也不需要写 yes。一些情况下强制使用 tcp 连上游的话写 yes
access-control: 0.0.0.0/0 allow # 本机用的话建议设置 127.0.0.0/8 allow,局域网用适当调整
root-hints: "/etc/unbound/root.hints" # 没有的话在 ftp://FTP.INTERNIC.NET/domain/named.cache 下载一份
hide-identity: yes # 不返回对 id.server 和 hostname.bind 的查询。
hide-version: yes # 不返回对 version.server 和 version.bind 的查询。
# 不过下面有 identity 和 version 的自定义选项,不隐藏这些的话,修改下选项还可以卖个萌(´・ω・`)
harden-glue: yes # 建议打开
module-config: "iterator" # 禁用 DNSSEC 检查,如果上游不支持 DNSSEC 就关掉。注意这个选项有可能在其他 include 的文件里
unwanted-reply-threshold: 10000000 # 针对各种网络不服,数值为建议值,具体可以自己修改看看效果
do-not-query-localhost: no # 一般是为了防止扯皮丢包开着,不过等下要用 DNSCrypt 所以关掉
prefetch: yes # 蛮好用的,开着吧
minimal-responses: yes # 省带宽,开着吧。本机用可以关掉
# 关键部分来了,把默认查询全部丢给 DNSCrypt。使用 [地址]@[端口] 指定查询地址和端口,默认端口 53。
# 然后把国内的地址丢给国内的缓存服务器。这两个选项的顺序不能错哟。
# 如果使用隧道查询,把这个地址改为隧道对端的地址,或者一个国外的 DNS 服务器都可以,例如 8.8.8.8。
# 具体看是在对端开 DNS 还是直接用国外的服务器。后者的话,前面 outgoing-interface 可以直接设置隧道本地端的地址,不过要配合 dnsmasq-china-list 的话,还是写路由表比较合适,否则不够灵活。
include: "/etc/unbound/accelerated-domains.china.unbound.conf"
forward-zone:
name: "."
forward-addr: 127.0.0.1@5353

DNSCrypt 配置

修改文件 /etc/default/dnscrypt-proxy

1
2
DNSCRYPT_PROXY_LOCAL_ADDRESS=127.0.0.1:5353 # 设置侦听在 127.0.0.1 端口 5353
DNSCRYPT_PROXY_RESOLVER_NAME=cisco # cisco 其实蛮快的,但是慢的话就去用个别的吧。d0wn 的那堆服务器真的不稳定,和名字一个样...

如果使用 systemd 的话这个文件就没用辣,看这里看这里

修改文件 /usr/lib/systemd/system/dnscrypt-proxy.socket

要修改的部分:

1
2
ListenStream=127.0.0.1:5353
ListenDatagram=127.0.0.1:5353

127.0.0.1:5353 就是上面 unbound 配置里 DNSCrypt 的监听地址。

dnsmasq-china-list 来加速

首先 clone 这个仓库到本地,然后在 Makefile 里修改 SERVER=114.114.114.114,改为你觉得最合适的国内缓存 DNS 服务器。114DNS 最不太近的一段时间里都挺残的所以不建议用。

执行 make unbound 来生成一份 unbound 配置,然后放在上面 unbound 配置里写的地址,也就是 /etc/unbound/accelerated-domains.china.unbound.conf

如果还需要一些特定的缓存上游设置,要放在 include: "/etc/unbound/accelerated-domains.china.unbound.conf" 这句前面。来举一只栗子。

举一只果子的栗子。

AppStore 的加载和下载速度一直在国内饱受一些极客们的诟病,然而同时饱受诟病的运营商 DNS 解析 AppStore 的下载地址反而是国内的 CDN 地址,速度会非常快。

需要使用 dig 工具,并且要在国内的网络环境下测试。Linux 发行版里都有包可以装,OS X 则自带。

第一条命令:dig +trace a100.phobos.apple.com.

递归追踪解析结果,这个记录被 CNAME 到了 a100.phobos-apple.com.akadns.net.

第二条命令:dig +trace a100.phobos-apple.com.akadns.net.,得到这条记录被 CNAME 到了 a1-a200.itunes-apple.com.akadns.net.

第三条命令:dig +trace a1-a200.itunes-apple.com.akadns.net.,看到了 CDN 的地址,a1-a200.phobos.apple.chinacache.net.

所以如果有国内的地址直接去跟踪解析 akadns.net 的 DNS 的话,一般是可以正确解析到国内 CDN 的。先找一个 akadns.net 的权威 NS 地址,比如 a1-128.akadns.net 对应的 IP 是 193.108.88.128。同时还得有国内的 CDN 地址也从国内地址去解析,那么配置里这样写:

1
2
3
4
5
6
forward-zone:
name: "akadns.net."
forward-addr: 193.108.88.128
forward-zone:
name: "chinacache.net."
forward-addr: 119.29.29.29 # DNSPod PublicDNS 的服务器地址

多次尝试之后,发现还有一个 CDN 地址 0gq2p7eckbs26f.mwcname.com,那么也把这个地址交给 unbound 通过国内网络解析。

1
2
3
forward-zone:
name: "mwcname.com."
forward-addr: 119.29.29.29

一并加到上面的配置里,然后来测试下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Phoenix-X1-Carbon :: ~ » dig @127.0.0.1 a100.phobos.apple.com

; <<>> DiG 9.10.3-P4 <<>> @127.0.0.1 a100.phobos.apple.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24454
;; flags: qr rd ra; QUERY: 1, ANSWER: 14, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;a100.phobos.apple.com. IN A

;; ANSWER SECTION:
a100.phobos.apple.com. 3596 IN CNAME a100.phobos-apple.com.akadns.net.
a100.phobos-apple.com.akadns.net. 117 IN CNAME a1-a200.itunes-apple.com.akadns.net.
a1-a200.itunes-apple.com.akadns.net. 297 IN CNAME a1-a200.phobos.apple.chinacache.net.
a1-a200.phobos.apple.chinacache.net. 1799 IN CNAME a1-a200.phobos.apple.cncssr.chinacache.net.
a1-a200.phobos.apple.cncssr.chinacache.net. 1799 IN CNAME cc00109.h.cncssr.chinacache.net.
cc00109.h.cncssr.chinacache.net. 120 IN A 223.99.228.87
cc00109.h.cncssr.chinacache.net. 120 IN A 113.207.33.15
cc00109.h.cncssr.chinacache.net. 120 IN A 113.207.33.12
cc00109.h.cncssr.chinacache.net. 120 IN A 202.110.80.14
cc00109.h.cncssr.chinacache.net. 120 IN A 61.179.105.154
cc00109.h.cncssr.chinacache.net. 120 IN A 61.179.105.7
cc00109.h.cncssr.chinacache.net. 120 IN A 119.188.138.172
cc00109.h.cncssr.chinacache.net. 120 IN A 120.192.248.195
cc00109.h.cncssr.chinacache.net. 120 IN A 221.181.39.76

;; Query time: 233 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Apr 28 00:34:02 CST 2016
;; MSG SIZE rcvd: 387

走国内 CDN 了吧~

重启相关服务,更改自己所用的 DNS 地址,完事儿收工(「・ω・)「

=== 2016-04-30 14:00 更新 ===

如果需要 edns-client-subnet 支持的话,需要手动编译源码安装。命令

1
2
3
4
# 克隆源码
svn co http://unbound.nlnetlabs.nl/svn/branches/edns-subnet/
# 编译安装
./configure --enable-subnet --with-libevent && make && sudo make install

配置文件的格式

1
2
# 默认向所有服务器发送 edns-client-subnet
send-client-subnet: 0.0.0.0/0

如果只对特定权威 DNS 发送 edns-client-subnet 请求,则按照此格式写多行 IP。

用了好久的 DNSMasq 方案终于在大半年前彻底炸掉了。

原因不光是 DNSMasq 性能和安全性完全不足以撑起公网缓存/递归 DNS 的任务,也有想要做反污染和加速的时候确实太蛋疼的问题。

现在使用的方案是 Unbound+DNSCrypt,

May 10, 2016 06:53 AM

May 08, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (7) - 双系统 Tips & Tricks

终于决定跳出虚拟机啦~

到底是啥原因让汝决定在自己的电脑上装 Linux 咧?

简单来说有下面两点:

  • 虚拟机的性能不足 (卡卡的很贴心)
  • 认为自己积累了一定的经验,希望再向前一步呗~

Act 1:该知道汝的电脑是 BIOS 还是 UEFI 启动了呗~

如果不知道的话,😋

  • 首先打开设置 ( Windows 8/8.1 叫做 "电脑设置"),然后通过 "更新和恢复" -> "恢复" -> "高级启动" 重启电脑.

如果是 UEFI 启动的话,大概是这个样子:

UEFI 系统启动之后大概像这样

没错就是有个 "使用设备" 的选项 😂

Act 2:在硬盘上准备一块空闲空间

不然要把 Linux 装到哪里去呐?

这里拿来演示的是 Windows 7 以后都自带的 “磁盘管理” 程序,应该能解决大多数问题 _(:з」∠)_

  • Windows 8 以后的系统可以通过按下 Windows + X 的菜单里找到 “磁盘管理”
磁盘管理在这~
  • 嗯,大概就是这样子的呗 (虽然具体的磁盘分区可能和咱的不一样)
大概长这样~
  • 汝哪个硬盘分区比较空闲? 右键点击它,有一个"压缩卷的选项"
”压缩卷“ 在这~
  • 输入压缩的大小 _(:з」∠)_
多少
  • 然后就多了一块未分配的空间 😂
多了一块未分配的空间

如果汝的硬盘分区有些刁钻而磁盘管理没法解决的话,AOMEI 家的分区助手不错, 这是官方网站 , 这是分区教程

Act 3:准备安装介质

其实基本上用的都是 U盘啦~

于是继续推荐编程随想的 如何用 ISO 镜像制作 U 盘安装盘(通用方法、无需 WinPE)

啥时候咱自己写一篇类似的...... 😂😂

Act 4:(UEFI 专属环节 (雾)) 关掉安全启动

啥是安全启动? 为啥要关掉咧?

安全启动是一个由电脑行业的成员开发的安全标准,它有助于确保仅使用受制造商信任的软件启动你的电脑。

当电脑启动时,固件会检查每个启动软件的数字签名,包括固件驱动器(选项 ROM)和操作系统。如果签名正常,则电脑启动,而且固件会将控制权交给操作系统。

然而默认情况下预装 Windows 的电脑中只会默认带有 Microsoft 的签名,而不是所有的 Linux 发行版都有能力获得签名的 Pia!<(=o ‵-′)ノ☆

所以就要关掉啦~ 😂😂

那么怎么关咧?

不过各种硬件实在是太多啦,咱实在是没法一一列举嘛~

  • Microsoft 提供的概述
  • 对于预装 Windows 的电脑,最好去看看生产商的支持网站.
  • 或者可以 Google 一下 ~(>_<~)

然后就是开始安装啦~如果遇到问题的话,先学习一下 提问的智慧 , 然后去汝安装的发行版的支持论坛问问呗~

by ホロ at May 08, 2016 04:00 PM

May 04, 2016

Issac Ge (Tech)

惰性求值可能会导致作用域偏移

在 with statement 的返回语句处理前者所打开的资源,会发生什么?好在 Python 的语法十分妥当,确保了 return 语句还在 with 作用域之内,即在资源被回收之前,就会该处理好的就处理好

但是,若返回涉及资源的生成器表达式时,那又会如何呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Python 3.5.1 (default, Mar  3 2016, 09:29:07) 
[GCC 5.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def a():
... with open('.zshenv') as file:
... return (line for line in file)
...
>>> a()
<generator object a.<locals>.<genexpr> at 0x7f900079c048>
>>> for b in a():
... print(b)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in <genexpr>
ValueError: I/O operation on closed file.
>>>

印象中,Python 向来是一门基于垃圾回收机制的动态语言,语法设计得十分精良:变量即指向对象的指针;LEGB 确保作用域互不侵犯;with statement 就牢牢地划定了工程师可以访问资源的地方,资源在作用域里一定存在,反之则反,大家写起来也安心。

但是惰性求值打破了这份美景。事实上,生成器表达式本身就意味着惰性求值,即迭代到哪,哪里才会被求值并赋值,除此之外的「值」要么还没被迭代到,要么在迭代过后被销毁。于是我们可以说在上例中,惰性求值偏移了这些迭代对象的作用域到 with statement 之外,再在访问这些资源时已经晚了。

此外,据我所知,lambda 也可能会导致惰性求值

whenever any of the returned functions are called, the value of i is looked up in the surrounding scope at the time it is called (and by then, the loop has completed, so i has already been assigned its final value of 4)

事实上,Python 本身还是一门 late binding 语言,也许不为人知的某角落会发生无谓的惰性求值,害得作用域被偏移了,只能小心为上。总之先制定新编程规范:其一,不要在 with statement 里返回涉及资源的生成器表达式;其二,如果生成器表达式里的 lambda 或函数被绑定错了实参,可以构造一个默认参数并再传实参。

最后分享一篇有趣的文章:蟒之惰性

Written with StackEdit.

在 with statement 的返回语句处理前者所打开的资源,会发生什么?好在 Python 的语法十分妥当,

May 04, 2016 02:42 AM

April 30, 2016

百合仙子

愛される花 愛されぬ花

本文来自依云's Blog,转载请注明。

很早就听过这首歌,但现在才知道这首歌讲的是什么。很喜欢这首歌的歌词,不过像《ひとり上手》一样,好悲伤啊。

找到正确的对照版歌词并不是那么容易的,因为大陆网站莫名其妙地对日文汉字进行了「简化」。标注读音的就更难得了,所以我专门制作了标注汉字读音的中日对照版歌词,有兴趣的朋友可以看看:愛される花 愛されぬ花.pdf。感谢 farseerfc 进行校对。

我没有在 YouTube 上找到中岛美雪演唱的版本,所以只好用网易云音乐这个歌词并不正确版本啦: http://music.163.com/song?id=624802

泱泱大国,连周边国家的文字都不能写对,我也是醉了……

by 依云 at April 30, 2016 10:09 AM

April 29, 2016

百合仙子

一个系统,两套网络

本文来自依云's Blog,转载请注明。

创建并配置一个新的网络命名空间

公司 VPN 用的网段是 192.168.1.0/24,而我家里的网络,就像大多数人的一样,也是 192.168.1.0/24。网段冲突了。当然啦,隔离得相当好的 lxc 可以解决这个问题。可是它隔离得太好了,我可不想再多维护一套环境。那么,就只隔离网络好了!

正好之前看到 iproute2 套件可以管理网络命名空间。那么,就用它啦。

首先,创建一个名为 vpn 的网络命名空间:

ip netns add vpn

现在如果进去看的话,会发现里边只有一个孤零零的 lo 网络接口,所以里边是一片与世隔绝的黑暗。我没有其它的网络接口给它用。桥接当然是可以尝试的,只是需要更改已有的网络配置。所以还是用另外的方案吧。弄根网线来,把里边和外边连接起来好了。

创建一对 veth 接口。这就是我们的「网线」~

ip link add vpn0 type veth peer name vpn1

一端留外边,另一端移到 vpn 里边去:

ip link set vpn1 netns vpn

接好网线的两端:

ip link set vpn0 up
ip netns exec vpn ip link set vpn1 up

好了,现在两个网络之间可以通信了~当然,只是链路层。为了使用 TCP/IP,我们得分配 IP 地址。在外边的这个就不需要 IP 地址了,因为我要把它接到一个网桥上,网桥自己有 IP 的。

brctl addif br0 vpn0

这里 br0 是我已有的网桥(给 lxc 用的那个)。如果你没有的话,就自己按以下方法弄一个。我用的是 bridge-utils 里的 brctl 命令。iproute2 也可以做的。

brctl addbr br0
ifconfig br0 192.168.57.1
iptables -t nat -A POSTROUTING -s 192.168.57.1/24 -j MASQUERADE

最后的 iptables 命令是做 NAT 啦。当然内核的 IPv4 转发功能还要开启的。

vpn0 这端弄好了,再给 vpn1 分配 IP,并设置相关路由表项:

ip netns exec vpn ip address add dev vpn1 192.168.57.101/24
ip netns exec vpn ip route add default via 192.168.57.1

现在就可以在里边连 VPN 啦~

ip netns exec vpn openvpn ...

当然也可以去里边开个 zsh 用

ip netns exec vpn zsh

不过要注意如果跑 GUI,或者连接 D-Bus 的话,需要手动把相关环境变量移进去。虽然是独立的网络命名空间,但是因为共享了文件系统,所以虽然看不到在监听的 UNIX 套接字,但是连起来还是没有问题的。X 和 D-Bus 都可以良好工作的。

export DISPLAY=:0 LANG=zh_CN.UTF-8 LANGUAGE=zh_CN:zh_TW
export GTK_IM_MODULE=fcitx QT_IM_MODULE=fcitx XMODIFIERS=@im=fcitx
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
# 如果在 tmux 里的话
export TMUX=1

再加上 mount 命名空间吧

我这里在里边得用 IP 地址,因为我的 DNS 是 127.0.0.1,在里边当然是用不了的。怎么办呢?我不想改 DNS 服务器地址,因为里外的文件系统是共享的。那就再加上 mount 命名空间吧,这样就可以 bind mount 一个修改过的文件到 /etc/resolv.conf 上了。

其实呢,ip netns 是通过把网络命名空间(/proc/<pid>/ns/net)bind mount 到文件来实现命名空间的持久化的(不然使用这个命名空间的进程都退出,该命名空间就销毁了)。其文件位于 /run/netns 下。对于 mount 命名空间我们可以手工这么做:

mkdir -p /var/run/ns
mount --bind /var/run/ns /var/run/ns
# 命名空间只能 bind mount 到 private 挂载的文件系统上
mount --make-private /var/run/ns
# 随意找个普通文件就行。一般是用空文件;我这样可以省一个文件~
cp /etc/resolv.conf /var/run/ns

然后用 unshare 建立新的 mount 命名空间,并进入之前的 vpn 网络命名空间(当然用 nsenter 进入也是可以的):

unshare --mount=/var/run/ns/resolv.conf ip netns exec vpn zsh

创建了之后就可以用 nsenter 进去玩儿了:

nsenter --mount=/var/run/ns/resolv.conf --net=/var/run/netns/vpn zsh

可以在里边各种 bind mount,不会影响外边的哦:

# 在新的命名空间里边
mount --bind /var/run/ns/resolv.conf /etc/resolv.conf
vim /etc/resolv.conf

组合更多的命名空间

当然也可以组合更多种的命名空间的。我还试过 pid 命名空间,不过 pid 命名空间比较特殊:它在 fork 后才生效,当 init 进程(pid=1 的进程)退出之后所有位于此 pid 命名空间的进程都会被杀死,并且再也进不去了。所以不是很好玩的啦。

创建与进入的命令如下:

unshare --mount-proc -f --pid=/var/run/ns/pid --mount=/var/run/ns/resolv.conf nsenter --net=/var/run/netns/vpn su - lilydjwg
# 进入时用 -t 选项,或者重新 bind mount 文件(不然新进程会在原 pid 命名空间)
nsenter -t 9416 --mount=/var/run/mountns/resolv.conf --net=/var/run/netns/vpn --pid su - lilydjwg

后记

除了可能偶尔连接公司 VPN 会用到这个技术之外,我又给其找到了一个更好的使用场合:Wine QQ!于是本地的 nginx 日志里终于不会再有 /srv/http/cgi/reccom 找不到的提示了,CGI 服务也不会被不必要地启动了。

2016年5月13日更新:自用的脚本放在 Gist 上了。

by 依云 at April 29, 2016 09:23 AM

April 27, 2016

ヨイツの賢狼ホロ

火狐娘兼职 RSS 阅读器~

火狐娘也可以兼职做 RSS 阅读器呐~

啥? 又来问啥是 RSS ??

如果连 RSS 是啥都不知道那这篇文章就不用看了 (╯>_<)╯ ┻━┻

「自知之明者,谓之贤也。」

让火狐娘兼职 RSS 阅读器的好处和问题是啥咧?

  • 好处:又可以少开一个应用啦~ ( 不过对于用 Owncloud News 的咱来说好像没啥区别😂😂
  • 问题:好像没有大多数 RSS 阅读器那样把所有的文章安排在一个流里的功能 _(:з」∠)_

咱们来开始呗~

首先打开汝的 Firefox 😂😂 , 在右边的长条菜单里找到那个孤零零 (?) 的 "定制" 选项.

定制在这~

在左边就可以看到"订阅"按钮啦,把它拉到工具栏或者菜单里呗~ (订阅:我在这快来拉我~)

订阅:我在这快来拉我~

然后打开一个博客 ( 例如 百合仙子 lilydjwghttps://blog.lilydjwg.me )

举一个栗子~

如果这个网站有 RSS 的话 , RSS 那个图标就会亮起来,就像上面那样~


那么这个具体是咋实现的呢? 原理就在于这段 HTML 代码上~

<link href="https://blog.lilydjwg.me/posts.rss" rel="alternate" title="Blog RSS" type="application/rss+xml" />

这段链接到了一个 MIME 类型是 application/rss+xml 的文件呐~ 所以火狐娘看到这个就知道这个网站有 RSS 可以看了呢~

除了 RSS 以外火狐娘还认得 Atom Syndication Format(Atom供稿格式) 的标准哟~ ( 虽然也是 RSS 阅读器们的必修课 ~(>_<~) ), 像这样:

<link href="/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="约伊兹的萌狼乡手札 Full Atom Feed" />

如果有时 RSS 源不止一个,就挑一个呗~ ( 比如第一个 )

有时 RSS 源不止一个......

然后汝就会打开一个这样的页面呗~ 其实还可以支持其它方式 ( 例如 Owncloud 新闻阅读器 ) 订阅收取点,不过这次咱就用火狐娘的固有技能 "实时书签" 呗~

FireFox 解析的 RSS 页面~
使用

实时书签大概像这样,如果汝订阅的网站更新了的话文件夹和每篇文章旁边的 RSS 图标会亮起来的啦~

实时书签长这样~

当然如果汝习惯 RSS 那种文章流,把 RSS 页面加为书签呗~

把 RSS 页面加为书签呗~

by ホロ at April 27, 2016 04:00 PM

April 25, 2016

ヨイツの賢狼ホロ

权限的边界-关于社区的一些无关思考

权限到底有没有边界?如果有的话,又在哪里?

为了避免oo和xx,先来个前提声明呗~

  • 咱绝对没有炮轰文中提到的人 (或非人) 的意思,虽然他/她/它们之间曾经 (或是现在正在) 有过节. 但是这和咱又有啥关系呐~
  • 建议汝先读读 政治常识扫盲:澄清“言论自由”的各种误区 这篇文章来扫除一下汝内心中可能存在的几个误区呗~
  • 由于各种原因这篇文章可能写的很长?
  • ......

从一件小事开始?

前几天 #archlinux-cnfarseerfc 在 Telegram 上创建了一个日语学习群,虽然一开始加的人挺多的,但是......

请原谅咱一字不落的贴出聊天记录 ( 至少是现在,如果将来有人要求删掉又是另一回事了

Star Brilliant , [27.04.16 04:50] 刚刚是谁踢我的

Star Brilliant , [27.04.16 04:50] 某卷?

teleboto, [27.04.16 04:50] [u] 同被踢

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:50] 😂

Star Brilliant , [27.04.16 04:50] 搞得好像那群是他家似的

Star Brilliant , [27.04.16 04:50] 我进到群里看到他在说话都没说什么

Star Brilliant , [27.04.16 04:50] 大不了不打理得了

Star Brilliant , [27.04.16 04:51] 私事公办很不对吧

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:51] 😂😂😂

Henry King, [27.04.16 04:51] @m13253 他的意思是你进群之后秀水平了

Star Brilliant , [27.04.16 04:51] [In reply to Henry King] 哦?

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:52] [In reply to jm33_m0] 😂😂

Star Brilliant , [27.04.16 04:52] 因为我“有一点基础所以不应该学习”

Star Brilliant , [27.04.16 04:52] 如果那个群他是管理员我就不管了

farseerfc 😂 0xC13D4796, [27.04.16 04:52] 他是管理員啊,我和他一起開的……

Star Brilliant , [27.04.16 04:52] 或者说如果那个群是他办的我就无所谓了

Star Brilliant , [27.04.16 04:52] [In reply to farseerfc 😂 0xC13D4796] 那我就不管了

Star Brilliant , [27.04.16 04:53] 总之我和他有仇

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:53] /me 默默的围观就好了😂

Star Brilliant , [27.04.16 04:53] 而我现在出现在 #archlinux-cn 的原因,正是因为这个群不是他自己加的

Star Brilliant , [27.04.16 04:53] 自己家的

teleboto, [27.04.16 04:53] [u] 我进去似乎不到一分钟……

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:53] (但是话说回来咱可没秀水平啊😂

Star Brilliant , [27.04.16 04:53] “开始踢人”,砰!消失了

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:54] [In reply to Star Brilliant ] 和 @acgtyrant 一样 😂

Star Brilliant , [27.04.16 04:54] [In reply to ヨイツの賢狼ホロ 😋(🍎*)] 我想你不知道5年前那个盖子/opensuse事件

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:55] [In reply to Star Brilliant ] /me 咱就是把Telegram放在后台一会儿😂

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:55] [In reply to Star Brilliant ] 前一阵子翻暴君的老Arch博客来着😂

wicast C, [27.04.16 04:56] 群关了!!?

wicast C, [27.04.16 04:56] 洗个碗就不见了🌚

Henry King, [27.04.16 04:56] [In reply to Star Brilliant ] 😅 五年前啊。那个时候我还没怎么用 G+。

逐光入暗 TJM ¦ PGP 9F6B2D7D, [27.04.16 04:56] [In reply to Star Brilliant ] 求科普

teleboto, [27.04.16 04:56] [LastAvengers] u: 日语群么?

Star Brilliant , [27.04.16 04:56] [In reply to 逐光入暗 TJM ¦ PGP 9F6B2D7D] 这里不方便说

paco tacitus, [27.04.16 04:57] [In reply to Star Brilliant ] 啥事件?

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 04:57] 五年前咱还是Debian用户😂

逐光入暗 TJM ¦ PGP 9F6B2D7D, [27.04.16 04:57] [In reply to Star Brilliant ] 口以私了

Star Brilliant , [27.04.16 04:57] [In reply to 逐光入暗 TJM ¦ PGP 9F6B2D7D] 我建议你问盖子本人

paco tacitus, [27.04.16 04:57] 我私聊不了

逐光入暗 TJM ¦ PGP 9F6B2D7D, [27.04.16 04:57] [In reply to Star Brilliant ] O.O

Star Brilliant , [27.04.16 04:57] 因为我不知道事情的(完整)前因,但是知道后果

paco tacitus, [27.04.16 04:57] [In reply to Star Brilliant ] 能google吗

高坂 きりの, [27.04.16 04:58] 五年前是2011吗

Star Brilliant , [27.04.16 04:58] [In reply to paco tacitus] ない,大部分文字记录被“逼迫要求删除”了

高坂 きりの, [27.04.16 04:58] 关键字搜不到啊

Star Brilliant , [27.04.16 04:59] 大部分情况下,我会选择少一点人际关系的问题

Star Brilliant , [27.04.16 04:59] 钻研技术就好

Felix Yan, [27.04.16 04:59] 🌚 五年前……那时候盖子还很小吧(捂脸

teleboto, [27.04.16 05:01] [u] LastAvengers: tg太伤人了😢😢

teleboto, [27.04.16 05:03] [phoenixlzx] 我已經不知道该说什么好了,一个认真的学习群一群人在里面开始瞎扯,被踢了就开始自己瞎猜然后翻我旧账,翻旧帐也就罢了这么多年了也没查证过到底是谁的问题

Star Brilliant , [27.04.16 05:04] “瞎扯”

paco tacitus, [27.04.16 05:06] 就搜到了关于yum作者去世的事。。比尔盖子?

Star Brilliant , [27.04.16 05:07] [In reply to paco tacitus] 都是徒劳,该毁灭的都毁灭了

Star Brilliant , [27.04.16 05:07] 我还留存一份然而可能找不到了

Star Brilliant , [27.04.16 05:07] 没必要翻旧账了

paco tacitus, [27.04.16 05:07] 奇怪

paco tacitus, [27.04.16 05:07] 好吧

Star Brilliant , [27.04.16 05:07] 因为我不想劝说任何人改变对任何人/事物的看法

teleboto, [27.04.16 05:07] [phoenixlzx] 然而刚才你就在这么做

Star Brilliant , [27.04.16 05:08] 我不希望你们因为听说了这些事情而对中国开源社区产生什么不好的印象

teleboto, [27.04.16 05:08] [phoenixlzx] 而且五年前你也在这么做

paco tacitus, [27.04.16 05:08] 🌚👍

teleboto, [27.04.16 05:10] [phoenixlzx] 再回来说这个日语群,本来也只是我自己想学而已,死皮赖脸去找fc前辈来带路,结果突然就来了一群人在聊东聊西,还有自以为比别人优秀就在秀的,这个群还怎么学习

teleboto, [27.04.16 05:11] [phoenixlzx] 一堆呆在日本几年的人拉进来帮忙的,都还没说话呢

Star Brilliant , [27.04.16 05:11] 简直

David Huang, [27.04.16 05:11] 🌚

teleboto, [27.04.16 05:12] [phoenixlzx] 不要太把自己当大爷了

paco tacitus, [27.04.16 05:12] 好吧。。我搜到那个事了🌚

paco tacitus, [27.04.16 05:12] 有点过分

ヨイツの賢狼ホロ 😋(🍎*), [27.04.16 05:12] [ 😂 (sticker) ]

Star Brilliant , [27.04.16 05:14] [In reply to teleboto] 我想告诉你的是,因为种种原因,我B了你,然而我在群里看到你存在的时候都“宽容”(暂且这么说)地忍了,你的做法真的合适么?

Star Brilliant , [27.04.16 05:14] “聊东聊西”得说出点证据

Star Brilliant , [27.04.16 05:14] 至于某旧账,我也不想多说

Star Brilliant , [27.04.16 05:15] 本来我是想点到为止,你自己一个人知道就好

Star Brilliant , [27.04.16 05:15] 毕竟群里其他人都不知道这个事情

Star Brilliant , [27.04.16 05:15] 有人问我这个事情到底怎么回事的时候我也没说

teleboto, [27.04.16 05:15] [phoenixlzx] 首先这个群是我和fc开的,我B你的时候你还没B我呢知道伐?本来我也可以看到你进来就直接踢掉你然而还是觉得既然来学习也就算了

teleboto, [27.04.16 05:16] [phoenixlzx] 结果呢

Star Brilliant , [27.04.16 05:16] 你应该知道我b人一般不会点击“b”

Star Brilliant , [27.04.16 05:16] 而是肉眼打码

Star Brilliant , [27.04.16 05:16] 结果怎么

teleboto, [27.04.16 05:16] [phoenixlzx] 我不管你怎么样 那是你自己的权利和我无关

Star Brilliant , [27.04.16 05:16] 结果我说了什么跑题的话了么?

Star Brilliant , [27.04.16 05:17] 那就无关好了

Star Brilliant , [27.04.16 05:18] 我不想刁难你

Star Brilliant , [27.04.16 05:18] 我也不希望你刁难

Star Brilliant , [27.04.16 05:18] 我

Star Brilliant , [27.04.16 05:19] 过往的恩怨也无所谓

那么,来大致梳理一下情况呗~

  • farseerfc 在 Telegram 上创建了一个日语学习群.然后在 #archlinux-cn 邀请加入.
  • 因为 fc 的邀请有好几个人加入了 (比如咱)
  • 一开始在试着用日语交流,还挺正常. (不过咱就是一直在发表情 😂😂)
  • (然后咱把 Telegram 最小化到后台了一阵子)
  • 再打开发现咱已经被移除出群了 (当然不止咱一个)
  • 然后就是上面那些聊天记录了😂😂

一些不负责小分析 _(:з」∠)_

  • 那个群是 farseerfc 开的, 然后给了 phoenixlzx Administrator,姑且算他俩的私人空间

    因为不满足公共空间的第一个特征:"不属于任何个人,不属于任何组织/机构。"

  • 很显然,因为是私人空间,所以其他人有没有言论自由,要看管理员是否愿意给.

  • 然后,因为是学习向群组,一定不希望被无关内容打扰.(这个好像大家都默许)

  • 最后,因为太多人开始跑题于是 phoenixlzx 开始把某些她认为造成跑题的人移出群.

  • 对此创建者 farseerfc 既没有表示反对又没有采取补救措施?

    当然也是因为被移除的人都没有要求再回去的缘故,所以咱认为这不是 fc 的锅

  • 就是这样, 事实已经说明了一切

于是咱自己的结论如下:

  • 如果只发表情和 sticker 算是对消息流的干扰而导致咱被移除的话,那是咱的错.

  • 但是如果 phoenixlzx 能给个更准确的解释说不定更好?

    或者他希望通过私聊解释只是因为不是双向联系人做不到 (Telegram 一大天坑 😂😂😂 )

  • 不管怎么样,咱并没有对 phoenixlzx 的做法表示不满,毕竟:

    "在【别人的】私人空间有没有言论自由捏?这就要看那个私人空间的主人是否给你言论自由。如果空间的主人允许,你就有;反之,则没有。"

好吧下面进入自问自答环节 😂

但是仔细想想还是先把问题列出来再分开回答吧 (才不是没时间了呐~)

Q1 : 社区或群组要不要有规则,如果有的话,谁来制定,怎样制定?

Q2 : 有比一般用户更高权限的用户是否该有更高的限制?

Q3 : 在群组中防止信息流被无关信息干扰是不是共识,具体操作起来呐?

Q4 : 关于封禁或移除之类的措施要不要在事后由操作者给相关人员一个看似合理的解释?

Q5 : 曾经在某个项目有过节的两人能不能在另一个项目上重归于好?

......


暂时想到的就这么多,欢迎各位在下方的评论里给出自己的解答或是邮件联系咱呗~

by ホロ at April 25, 2016 04:00 PM

April 23, 2016

April 22, 2016

ヨイツの賢狼ホロ

闲聊技术文章的写作姿势

不过真的有一种正确的姿势么 _(:з」∠)_

其实咱为啥写这个 几乎全是瞎扯 的博客的一个主要原因就是有时找不到合适的文章或文档 😂😂

所以,技术文章怎么啦~ (╯T︿T)╯ ┻━┻

擅长前端的 老司机 卡夫 ( frantic1048 ) 推荐了一篇叫做 技术文章常见的 5 个问题 的文章. o(* ̄3 ̄)o

里面提到了撰写技术文章遇到的常见的问题:

  • 目的不明确。“所以,搞着些玩意儿是要干啥?”
  • 文章内容太过狭窄。“噢,这篇文章只面向 20 岁的见习风系魔法学徒使用,不看了”
  • 贴代码没注释。“这个野生的咒语是干啥的?”
  • 前后不一致的口吻。“我感觉快要精分了 ~(>_<~)”
  • 写到最后没有个结论。“(..•˘_˘•..)”

frantic1048 in 知乎

( ,,´・ω・)ノ"(´っω・`。)

提前注明一下 : 下面的栗子纯属虚构呐~ 如有雷同..... (放心这不会发生的😋

技术文章问题之一 : 目的不明确 <(=﹁"﹁=)>

由于深受语文教育的毒害 ,一般都会认为一篇文章都要有一个主要表达的意图或是观点呗 ( 没错就是那个众人寻他千百度却在灯火阑珊处的中心思想😂😂 ), 当然汝说的如果是一篇 形散神聚的 散文那就又是另一个怎么也解释不清的玄学了 (明明是我先的......

然而实际情况是,有时容易搞不清楚文章的主题,典型的情况就是...... ( 咱给忘了 (つд⊂)

试想一下一个希望看到某个主题的读者在看到全篇都在讲另一个主题的时候的感觉, 真的好想把浪费咱时间的作者咬死 😂😂

技术文章问题之二 : 文章内容过于狭窄 ~(>_<~)

内容过于狭窄就容易给读者 "这篇文章不适合咱" 的错觉,于是就关掉了......

有可能是因为很多时候自己的博客有点像自己的笔记,解决一个问题以后写一篇,于是整片文章都在讨论如何解决某一个具体的 问题,看着就 "内容过于狭窄" 了 | ω・`)

在这里咱要好好反省一下自己,因为咱好像一直在写像是教程一类的东西于是就没有多少深度 😂

技术文章问题之三 : 贴代码没注释 (╯>_<)╯ ┻━┻

写代码没注释就像汝拿着一本魔法书却不知道怎么使用呐~

“这个野生的咒语是干啥的?” _(:з」∠)_

比如上面那个歪果仁提的栗子:

<!-- offset 2 -->
{{ range $index, $element := .Site.Pages }}
    {{ if gt $index 1 }}
    <li>
        <span class="date">{{ .Date.Format "Jan" }}
        <strong>{{ .Date.Format "2"}}</strong></span>
        <h3><a href="link">{{ .Title }}</a></h3>
        <p>{{.Description}}</p>
    </li>
    {{ end }}
{{ end }}

尽管因为咱以前用过 Jinja2 所以知道这是 Jinja 模板的一部分,但肯定有好多人看到 HTML 就一阵惊慌失措啦 ( 更别提 HTML 里还有一堆大括号啦 (╯>▽<)╯ ┻━┻ )

在这里咱要好好反省一下自己*2,好像咱也经常忘记写注释......

顺便给 frantic1048 点个赞 ( 例如这篇 )

o(* ̄3 ̄)o

技术文章问题之四 : 前后不一致的措辞 ( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)

比如前面用 "我" 后面不知道到了哪里就变成了 "我们" 这一类的问题,

读起来感觉自己都要精分啦 (╯@﹏@)╯ ┻━┻

技术文章问题之五 : 没有总结 “(..•˘_˘•..)”

......

上面就是一个绝佳的栗子 😂😂

那么啥样的姿势比较好咧? ~(>_<~)

其实上面那篇文章里也给出了四个建议 😂😂

建议之一 : 拥有个性 (σ≧∀≦)σ

要知道汝写的是文章而不是 死板的 API 文档呐~ 一个好的写作风格说不定可以帮汝拉来新读者哟~ 😋

建议之二 : 但是也不要个性过了头 <(ノ=﹁"﹁=)ノ┻━┻

既然是技术博客嘛,一定的严谨和专业性还是有必要的啦~ ( 比如不要有太多的错别字啦 (╯@_>@)╯ ┻━┻ )

建议之三 : 主线要有主线的存在感 ʃ ̂͜•̄ ̱̩ ̄͜►

不要把主线搞得像阿卡林一样没有存在感啦~

即使要插支线剧情也要以不同的形式让读者能轻易分辨,不要和主线混在一起,以及别太长。

建议之四 : 基本的排版 (・∀・)

文章分节的标题之类的可以帮助读者能够快速了解文章大体内容啦~


介于咱也不是什么写博客的菊苣,咱也就只能抛个砖引个玉.欢迎各位大触前来指教呗~

by ホロ at April 22, 2016 04:00 PM

April 19, 2016

Phoenix Nemo

公共场合请使用指纹识别器

前几天带本本去导师办公室修改论文,虽然开机启动速度快,但是还是在老师的注视之下紧张敲错了三遍密码…得,本来没在意的也记住密码了(ry

所以为啥有指纹识别器的本子偏偏要输密码(:з」∠)

检查设备

总之先来看下指纹识别器是哪家生产的好了。

1
2
Phoenix-X1-Carbon :: ~ » lsusb | grep -i 'finger'
Bus 001 Device 003: ID 138a:0017 Validity Sensors, Inc. Fingerprint Reader

搜索一下就发现 X1 Carbon Gen3 这么受欢迎的本子早已上了 ArchWiki https://wiki.archlinux.org/index.php/Lenovo_ThinkPad_X1_Carbon_(Gen_3)

安装驱动

安装 fprintd 包,这个包会依赖 libfprint,但是官方仓库中的 libfprint 目前的版本在此指纹识别器上无法正常工作,表现为 enroll 只扫描一次,并且无法验证指纹。

Note that recent versions of fprint are broken for this model : One is able to enroll a finger but recognition always fails.

GitHub 上已经有了 vfs5011 相关的 issue 和 fix,但是还没有发布新的稳定版。所以暂时安装 aur/libfprint-git 包。

配置指纹验证

Fprint - ArchWiki 上已经给出了配置方法。将 auth sufficient pam_fprintd.so 加入 /etc/pam.d/system-local-login 中的第一位置即可。同样方法可以用于 /etc/pam.d/ 下的其他文件。例如 KDE 登陆使用的 sddm

扫描指纹,以普通用户身份命令:

1
$ fprint-enroll

默认是右手食指。可以使用 -f 选项指定手指。正常的表现为成功扫描五次即可保存指纹,并且在需要验证的时候自动启动指纹识别器。不过还有个小问题,如果保存多个指纹,似乎只能识别保存指纹列表中的第一个。

然而我懒得折腾了就这样吧

前几天带本本去导师办公室修改论文,虽然开机启动速度快,但是还是在老师的注视之下紧张敲错了三遍密码…得,本来没在意的也记住密码了(ry

所以为啥有指纹识别器的本子偏偏要输密码(:з」∠)

April 19, 2016 08:48 AM

April 18, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (6) - 安装 Debian

接着咱再来装 Debian ~(>_<~)

下载 Debian

话说 Debian 从官网到 Wiki 都有一种年久失修的气息😂😂

这是官方的下载页面

嗯……看不懂的话直接去崔土豪源吧😂😂

DVD : https://mirrors.ustc.edu.cn/debian-cd/8.4.0/amd64/iso-dvd/

( 不用下载带 Update 的 iso )

Live DVD : https://mirrors.ustc.edu.cn/debian-cd/8.4.0-live/amd64/iso-hybrid/

( 后面的 xxxx-desktop 表示的是某种环境的 Live 系统 )

然而咱并没有找到 Debian 的系统需求啊 (╯•̀∧•́)╯ ┻━┻

后面咱就用 DVD 映像啦 ~(>_<~)

区分 MBR 和 UEFI 系统 | ω・`)

MBR 系统启动安装映像之后大概像这样 _(:з」∠)_

MBR 系统启动之后大概像这样
  • Install : 基于终端的安装界面
  • Graphical Install : 基于 GUI 的安装界面 | ω・`)
  • Advanced Options : 高级选项......
  • Help : 帮助
  • Install with speech synchesis : 在文字转语音支持下安装 ( 然而估计用不到 😂😂 )

( 对于 Live ISO ,会多一个 "Start Debian Live" 的选项,可以来进行测试 o(* ̄3 ̄)o

而 UEFI 启动大概像这样 (´・ω・`)

UEFI啦~

那么 Advanced Options 都有哪些咧 ?

这是高级选项 _(:з」∠)_
  • Expert Install : 以 Expert Mode 进行安装 ( 专家(啰嗦) 模式 )
  • Rescue Mode : 修复当前系统的急救模式
  • Automated Install : 自动安装 ( 然而咱没用过 😂😂 )

( 下面三个带 Graphical 的选项就是图形界面下的啦~ )

第一阶段:语言和区域,设置网络和创建用户

  • 选择语言,在安装程序中选择的语言会是汝安装好的系统的语言呗~
选择语言
  • 例行提示所选语言的翻译不完整 _(:з」∠)_
提示翻译不完整……
  • 选择汝的区域,一般选择汝所在的位置就好啦~
选择区域
  • 配置键盘映射,默认的应该就合适 <(=﹁"﹁=)>
键盘映射
  • 探测网络设备,偶尔会提示缺少某些驱动,先记下来.

    ( VirtualBox 不缺驱动所以没截图 😂😂 )

  • 探测连接,没有的直接按取消吧 😂😂

探测网络连接
  • 探测网络连接失败,接着选 "现在不进行网络设置" 然后下一步.
探测网络连接失败   _(:з」∠)_
  • 设置一个主机名,一般可以随便些~
设置主机名
  • 这里可以选择为 root 用户设置一个密码,也可以不设置

    考虑到安全性还是不要设置的好 <(=﹁"﹁=)>

可选为 root 用户设置个密码
  • 接着创建一个用户,因为 root 没有密码,所以这个用户可以通过 sudo 获得 root 权限 ~(>_<~)
创建新用户 创建新用户 为新用户设置密码

然后又到最坑的环节啦 😂😂

第二阶段 : 磁盘分区和安装基本系统 Σ( ° △ °|||)

  • 选择一种分区方式,为了不坑选择手动 ʃ ̂͜•̄ ̱̩ ̄͜►
选择一种分区方式
  • 如果汝计划在一块新硬盘上安装系统的话,先创建一下分区表呗~

    点击设备名称来创建分区表 <(ノ=﹁"﹁=)ノ┻━┻

分区菜单 为设备创建分区表
  • 接下来点击那个新的 "空闲空间" 创建一个新分区呗~
创建新分区
  • 设置新分区的大小.
新分区的大小
  • 调整新分区的属性,一般设置挂载点就好 ( / 是必须的 (╯ˊ_>ˋ)╯ ┻━┻ )
编辑分区的详细信息
  • 然后效果大概像这样 _(:з」∠)_
分区的详细信息
  • 对于 UEFI 系统,还需要一个 EFI 系统分区呗~
创建一个 EFI 系统分区 包括 EFI 系统分区的分区表
  • 单击 "分区设定结束并将设置写入磁盘" ,这时会提示没有创建交换空间 😂😂

    对于 RAM 小于 1GB 的用户,交换空间通常是推荐的 ( 一般推荐是RAM 的两倍...... ),但是对于拥有大量的物理内存的用户来说是否使用主要看个人口味了 (尽管它对于休眠到硬盘支持是必须的)。

    自己看着办呗~ ......

    大土壕 hjc 这样说:

    David Huang 🌚, [16.04.16 04:38] 有啊

    David Huang 🌚, [16.04.16 04:38] 能把更冷的内存压缩后放磁盘上,将腾出来的空间用于更热的缓存

    David Huang 🌚, [16.04.16 04:39] 比如我chrome泄露了50个G的内存

    David Huang 🌚, [16.04.16 04:39] 我总共有64G内存

    David Huang 🌚, [16.04.16 04:39] 这个时候系统就会把这50G压缩后放在硬盘上

    David Huang 🌚, [16.04.16 04:40] 然后这些空间用于缓存

    David Huang 🌚, [16.04.16 04:40] 明显提高系统运行速度

    David Huang 🌚, [16.04.16 04:40] →_→

提示没有交换空间 ......
  • 接着该确认了.

    一旦选了是,就没有回头路了呐~

确认提交对硬盘分区的更改
  • 开始安装基本系统,去喝杯咖啡呗~ 😂

只有 DVD 安装需要的第三阶段 : 设置软件包管理器

  • 只有在汝有其他的 DVD 映像的时才需要扫描呐~
插别的 DVD ?
  • 虽然可以在这里选择网络映像,但前提汝要有足够的网速和时间 😂😂
使用网络镜像
  • 要不要参加软件包流行度调查随便啦~
参加软件包流行度调查?
  • 选择安装的软件包组,一般就是再选一个桌面环境 😂
选择软件包集
  • 然后接着装(可以去把刚刚泡的咖啡喝了 😂
安装软件包

只有 MBR 安装需要的第三阶段 : 安装 GRUB 启动管理器

( 其实 UEFI 安装也有这一步啦。只是不需要汝手动设置啦~ )

  • 要把 GRUB 安装到 MBR 上吗? ( 当然是要啦~ )
要把 GRUB 安装到 MBR 上吗?
  • 然后选择要安装到的硬盘上呗~
然后选择要安装到的硬盘

最后 ......

  • 收工重启 ......
重启
  • 两个选项,分别是启动系统和高级选项 _(:з」∠)_
GRUB
  • 高级选项的两个选项,第一和刚刚的第一个一样,第二个是进入恢复模式 (╯T皿T)╯ ┻━┻
高级选项
  • 该登录啦~
登录

咱要不要再装个 openSUSE 😂😂

by ホロ at April 18, 2016 04:00 PM

Issac Ge (Tech)

C++ 最佳空白实践

众所周知,C++ 编译器凭任意空白和分隔符来解析 token, 所以空白可以是随意的——不换行,无数空行都可以。然而我们是人类,不是没有心的编译器,我们当然不能容忍工程出现C那种混乱大赛的代码,熟悉导致喜欢,便有必要制定相应的编码规范了,其中关键之一便是空白

八十字符宽

计算机刚出世时,编程卡片为八十列;无独有偶,Unix 早期的终端,每行最大显示字符数也为八十个;Unix 大多文本工具也沿袭了这传统,至今在 Maillist 上可以看到不少资深 Linux 工程师习惯把邮件正文 wrap 成在 80 字符内,man 手册也是;此外,在可读性尤佳的前提下,A4 纸宽度刚好能容纳八十个字符;最后,现代宽屏可以显示一百六十个以上的字符,且 Windows 支持并列窗口,在 Linux 的窗口管理器上上更大显神威。

于此可以推导出第一号价值观假设文本行最佳字符上限是八十。即,第一号编码规范C++ 代码每一行以 \n 硬断行且不超过 80 个字符。

如果违背此规则,那么,如果文本编辑器不支持软断行,于是它宽度又小于某行的长度时,该行后面的内容就被截断,一般情况下得横向滚动才能看到。反之,哪怕文本编辑器智能地软断行,用户需要在一行内阅读超过 80 个字符上的编码,并理解其逻辑。这不光无谓地增加逻辑的复杂度,且眼球滚动到下一行要跨越「开头到截断位置」的整个长度,比如一行超过屏幕宽度并被软断行,用户眼球的聚焦点需要移动大约一百六十个字符才能继续阅读代码,您感受一下。

那么,如何让文本编辑器鼓励用户遵循第一号编码规范?御用文本编辑器是 Vim, 它支持 80 字宽高亮,且可以不软断行,可以在宽屏下并列两个 windows.

块缩进

C++ 的元逻辑单元即是语句(statement),且复合多条语句的逻辑单元则是代码块(compound statements or blocks)。显然,整个源代码可以一一分割成众多代码块,且块块嵌套。且我们会不禁对其形成这样的第二号价值观假设块内同等缩进的代码属于同一个逻辑单元,且可以是 Iteration statements 的真子集,并因空白缩进数量不同,而有别于上下文的其他逻单元。

于是我们可以提炼出第二号编码规范凡是在代码块内的语句,均缩进一定同等宽度空白。我把它叫做块缩进。Vim 默认的 C++ filetype 会自动在 compound statements 缩进,且 ultisnip 插件也可以提供若干事先缩进好的代码块。

那么新问题来了:块缩进的空白宽度多少为宜?事实上第二号编码规范已经蕴含了假设:所有块缩进一定是第一层块缩进空白宽度的整数倍。熟悉计算机科学的同学都知道,计算机的进位制天生只有二进制,1 << 1 的计算结果就是 10. 凑巧,Vim 的默认缩进快捷键也是 <>, 且缩进空白宽度的设置为 shiftwidth, 也就是说,shiftwidth 就相当于第一层块缩进空白宽度,且我们按了多少次 <> 来缩进,那么不论相应的缩进实际宽度如何,都必然是 shiftwidth 的整数倍。于是我们这些习惯计算机思维的工程师自然有第三号价值观假设块缩进的空白宽度必然是二的幂。接着问题就简化为:第一层块缩进即元块缩进的空白宽度多少为宜

显然,设为一个空格宽度,任何正常人看着都不舒服,毕竟我们也很容易想象到:在如此低的缩进对数下,源代码可以一口气嵌多达八十个块!显然第四号价值观假设诞生了:我们不喜欢如此令人窒息的最大块嵌套层次上限,所以元块缩进的空白宽度不宜为一。那设为二?可以嵌套的层数就骤减为 40, 看起来也好接受多了;设为四,没什么太大的变化;再变本加厉地设为八呢?事实上,C++ 作为复杂的编程语言,自然总会免不了嵌套多达三四层的代码块,于是若元块缩进的空白宽度为八,那么在源代码嵌套到第四层的同时,意味着缩进了 4 * 8 = 32 个字符,即剩余代码字符宽度一下缩水进一半,已经很难再容下命名空间的嵌套、模板参数以及长 Indentifier 了,而且这对下文要提到的「换行缩进」影响很坏。显然不是所有人能忍受这宽度的,第五号价值观假设应运而生:元块缩进的空白宽度最多只能是四。

Vim 有很棒的插件 Yggdroot/indentline, 可以高亮缩进。

换行缩进

其实还有一个情况没提到:一条语句本身就超出八十字符宽上限。这情况太常见了,您想象一下接收众多容器的类成员函数定义的第一行吧,比如 std::string Women::Women(std::string name, std::int age, std::string address) {...}. 在不 using 命名空间的编码规范下,C++ 的一条语句就像这样动不动就超出 80 字符宽上限。所以就有必要对其硬断行,即换行缩进了。

好在,我们可以很容易发现,几乎所有超限的语句,无一不例外地包含了把若干子语句嵌套起来的一对标点,比如双括号。我们就可以从这地方入手,即有第三号编码规范:换行缩进可以从特殊标点符号之后硬断行。比如上面的代码例子可以改写为:

1
2
3
4
std::string Women::Women(
std::string name, std::int age, std::string address) {
...
}

也可以这样写:

1
2
3
4
5
6
std::string Women::Women(
std::string name,
std::int age,
std::string address) {
...
}

所以事实上我已经不再推崇 Google C++ Style 的那种缩进风格了,毕竟它有些换行缩进挺不伦不类,缺点也非常明显,我就不解说了:

1
2
3
4
5
std::string Women::Women(std::string name,
std::int age,
std::string address) {
...
}

我说过是在特殊符号之后断行,所以以下也是可以的:

1
2
3
4
for (int k = 0; k <= n_; ++k) {
std::cout << "polynomial_parameters_[" << k << "]: " <<
polynomial_parameters_[k] << " ";
}
1
2
assert(m_ == left_monomial.size() &&
left_monomial.size() == right_monomial.size());

聪明人应该发觉换行缩进的规律了,不过还请让我继续讲完:如何换行缩进?除了同样遵循从第一到第五的价值观假设,再追个第六号价值观假设要能区分换行区分和块缩进

其实很简单,在遵循第一二号编码规范的前提下,只要让它们的元缩进空白宽度不同就行了。再看看:哪个缩进更为频繁?当然是块缩进!所以为了少敲字,第四号编码规范来了:换行缩进的元缩进宽度是块缩进的两倍。所以说元块缩进的宽度为什么不能是八——因为这意味着元换行缩进的宽度要有十六个!所以元块缩进为二、元换行缩进为四的风格就是最理想的了,当然,我在 Python 编程时试过元块缩进为四元换行缩进为八的风格,也可以接受。实际上,PEP 8 也提倡换行缩进,虽然缩进量和块缩进一样。其实 Python 天生比 C++ 更适合换行缩进,因为它允许参数列表中最后一个参数后面可以跟着额外的逗号!这么一来在排版上相当完美,比如 setup.py:

1
2
3
4
5
6
7
8
9
10
11
12
extension = Extension(
"rect",
sources=["rect.pyx"],
language="c++",
include_dirs=opencv_incs,
extra_link_args=opencv_libs,
)

setup(
cmdclass={'build_ext': build_ext},
ext_modules=cythonize(extension),
)

再次,换行缩进所要硬断行的语句终究只是一条语句,我们不允许它会复杂到像需要多个嵌套换行缩进,否则就违背设定八十字符宽从而控制语句逻辑复杂度的初衷了。有第七号价值观假设不允许同一行多次换行缩进。换句话说,对应的第四号编码规范换行缩进不能再嵌套换行缩进。毕竟以下代码看起来就很糟糕:

1
2
3
4
5
FullscreenDetector::FullscreenDetector(
Ptr<CascadeClassifier> cascade,
Ptr<CaffeClassifier> caffe,
struct FsDetectorParam& params):
_cascade_c(cascade), _caffe_c(caffe), prepara_init(false) {

Vim 同样有另一个高亮不同层次嵌套符号的插件 rowchen1990/rainbow, 意外地对加强了换行缩进的可读性。

access specifiers

我说过同等缩进的代码块属于同一个逻辑单元,但 C++ 中却有例外:类内的 access specifiers. 即 private, publicprototect. 为了更好地对类进一步划分逻辑单元,来自 Google C++ Style 的第五号编码规范就相当高明:所有 access specifiers 关键字只缩进一个空白。 完美地与元块缩进区分开来了。读者就好一眼看出类内代码所属的不同逻辑单元。

空白即空格

说了这么久,是时候该断定何谓空白了,即有第六号编码规范缩进用的空白一律为空格。毕竟 \t 终究只是一个排版用的制表符,我怀疑字符编码从来不会规定它的字符宽度会是多少,按奥卡姆剃刀,我当然十分嫌弃。

后记

事实上我本来不想列举一条又一条假设和取向,如此长篇大论地推广浅薄的编码规范,但是现实中有人就很迷信八空格缩进的 Kernel Style, 并回避了我的「如何换行缩进」问题(事实上,Linux 工程师 @fixme 说 Kernel Style 从来没说明过,同一条语句超出 80 字符时怎么办),这造就了他的 C++ 源代码不光缩进宽度超长、还动不动突破 80 字符宽的风格,最后他对二空格缩进的价值观「变成PHP是世界上最好的语言了」更是令人费解。所以我希望这篇文章能一劳永逸地说服我所关心的人,且彼此更加舒服地编程。


Written with StackEdit.

众所周知,C++ 编译器凭任意空白和分隔符来解析 token, 所以空白可以是随意的——不换行,无数空行都可以。然而我们是人类,不是没有心的编译器,我们当然不能容忍工程出现

April 18, 2016 02:05 AM

April 17, 2016

百合仙子

用 nfqueue + Python 回复 IPv6 DNS 请求

本文来自依云's Blog,转载请注明。

发生了这么一件事:服务器访问某些 URL 时经常会花费好几秒的时间。重现并分析 strace 记录之后,发现是 DNS 的 AAAA 记录的问题。

情况是这样的:CentOS 6 默认启用了 IPv6,于是 glibc 就会同时进行 A 和 AAAA 记录查询。然后呢,上游 DNS 是运营商的,不给力,经常在解析 AAAA 记录时花费几秒甚至十几秒,然后超时或者返回个 SERVFAIL。

不过咱在天朝,也没有 IPv6 网络可用,所以就禁用 IPv6 吧。通过 sysctl 禁用 IPv6 无效。glibc 是通过创建 IPv6 套接字的方式来决定是否进行 AAAA 请求的。查了一下,禁用掉 ipv6 这个内核模块就可以了。可是,rmmod ipv6 报告模块正在使用中。

lsof -nPi | grep -i ipv6

会列出几个正在使用 IPv6 套接字的进程。重启服务,或者重启机器太麻烦了,也不知道会不会有进程会起不来……于是我想起了歪心思:既然是因为 AAAA 记录回应慢,而咱并不使用这个回应,那就及时伪造一个呗。

于是上 nfqueue。DNS 是基于 UDP 的,所以处理起来也挺简单。用的是 netfilterqueue 这个库。DNS 解析用的是 dnslib

因为 53 端口已经被 DNS 服务器占用了,所以想从这个地址发送回应还得用底层的方法。尝试过 scapy,然而包总是发不出去,Wireshark 显示 MAC 地址没有正确填写……实在弄不明白要怎么做,干脆用 RAW 套接字好了。man 7 raw 之后发现挺简单的嘛,因为它直接就支持 UDP 协议,不用自己处理 IP 头。UDP 头还是要自己处理的,8 字节,其中最麻烦的校验和可以填全零=w= 至于解析 nfqueue 那边过来的 IP 包,我只需要源地址就可以了,所以就直接从相应的偏移取了~(其实想想,好像 dnslib 也不需要呢~)

代码如下(Gist 上也放了一份):

#!/usr/bin/env python3

import socket
import struct
import traceback
import subprocess
import time
import signal

import dnslib
from dnslib import DNSRecord
from netfilterqueue import NetfilterQueue

AAAA = dnslib.QTYPE.reverse['AAAA']
udpsock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
PORT = 53

def handle_packet(pkt):
  s = time.time()
  try:
    ip = pkt.get_payload()
    # 28 = 20B IPv4 header + 8B UDP header
    dns = DNSRecord.parse(ip[28:])
    if dns.q.qtype == AAAA:
      ret = dns.reply()
      src = socket.inet_ntoa(ip[12:16])
      sport = struct.unpack('!H', ip[20:22])[0]
      p = ret.pack()
      # print(ret, p)
      checksum = 0
      p = struct.pack('!HHHH', PORT, sport, len(p) + 8, checksum) + p
      udpsock.sendto(p, (src, sport))
      pkt.drop()
    else:
      pkt.accept()
  except KeyboardInterrupt:
    pkt.accept()
    raise
  except Exception:
    traceback.print_exc()
    pkt.accept()
  e = time.time()
  print('%.3fms' % ((e - s) * 1000))

def main():
  nfqueue = NetfilterQueue()
  nfqueue.bind(1, handle_packet)
  try:
    nfqueue.run()
  except KeyboardInterrupt:
    print()

def quit(signum, sigframe):
  raise KeyboardInterrupt

if __name__ == '__main__':
  signal.signal(signal.SIGTERM, quit)
  signal.signal(signal.SIGQUIT, quit)
  signal.signal(signal.SIGHUP, quit)
  subprocess.check_call(['iptables', '-I', 'INPUT', '-p', 'udp', '-m', 'udp', '--dport', str(PORT), '-j', 'NFQUEUE', '--queue-num', '1'])
  try:
    main()
  finally:
    subprocess.check_call(['iptables', '-D', 'INPUT', '-p', 'udp', '-m', 'udp', '--dport', str(PORT), '-j', 'NFQUEUE', '--queue-num', '1'])

写好之后、准备部署前,我还担心了一下 Python 的执行效率——要是请求太多处理不过来就麻烦了,得搞多进程呢。看了一下,一个包只有 3ms 的处理时间。然后发现 Python 其实也没有那么慢嘛,绝大部分时候不到 1ms 就搞定了~

部署到咱的 DNS 服务器上之后,AAAA 记录回应迅速,再也不会慢了~

调试网络程序,Wireshark 就是好用!

PS: 后来有人告诉我改 gai.conf 也可以。我试了一下,如下设置并没有阻止 glibc 请求 AAAA 记录——它压根就没读这个文件!

precedence ::ffff:0:0/96  100

PPS: 我还发现发送这两个 DNS 请求,glibc 2.12 用了两次 sendto,但是 Arch Linux 上的 glibc 2.23 只用了一次 sendmmsg~所以大家还是尽量升级吧,有好处的呢。

by 依云 at April 17, 2016 01:37 PM

April 11, 2016

ヨイツの賢狼ホロ

入手 Raspberry Pi 3

社团为了完成某个和咱没有关系的项目买了块树莓派3诶,然而不妨碍咱玩就是了~

汝不会连树莓派是啥都不知道吧 😂😂

树莓派(英语:Raspberry Pi),是一款基于Linux的单板机电脑。它由英国的树莓派基金会所开发,目的是以低价硬件及自由软件刺激在学校的基本计算机科学教育。

树莓派基金会提供了基于ARM架构的Debian、Arch Linux和Fedora等的发行版供大众下载,还计划提供支持Python作为主要编程语言,支持BBC BASIC(通过RISC OS映像或者Linux的"Brandy Basic"克隆)、C语言和Perl等编程语言。

---- Wikipedia:树莓派

若干准备动作 _(:з」∠)_

树莓派3的配置大概像这样:

  • SoC(系统单晶片) : Broadcom BCM2837(CPU,GPU DSP和SDRAM、USB)
  • CPU : ARM Cortex-A53 64位 (ARMv8系列) 1.2GHz (四核心)
  • GPU :Broadcom VideoCore IV
  • RAM : 1GB
  • 和上一代比多内置了了无线网卡和蓝牙模块

当然因为只是块板子嘛,还要准备些外设:

  • 一个显示器 ( 当然其实可以用 GPIO(通用输入/输出) 连接串口 ) 和 HDMI 线
  • 一张 MicroSD 卡
  • USB 接口的鼠标和键盘
  • 至少 5V/2A 的电源适配器和 Micro USB 线 ( 这个给汝的手机充电的插座和数据线应该能满足呗~ )
  • 以太网线 ( 如果汝打算用有线连接 )

于是在准备完成以后......

为树莓派写入系统 ( Arch Linux ARM )

作为 Arch Linux 用户,当然最好是接着用 Arch 啦,还好有 Arch Linux ARM 😂

Arch Linux ARM 文档 的光辉照耀下,一切正常.

然后把写入好系统的 MicroSD 卡插入树莓派,连上显示器和电源,开机.

为树莓派写入系统 ( Raspbian )

Rsapbian 是基于 Debian 修改成的,树莓派基金会官方支持的操作系统啦~

下载在这里 , 安装教程在这里 .

然而后面的操作都是在 Arch Linux ARM 上的 😂😂

安装 Xfce 桌面环境

首先要连上网,准备好接受 ArchWiki 的圣光 呗~

默认的 alarm 用户竟然没有 sudo 权限 Pia!<(=o ‵-′)ノ☆ , 不过没啥关系, 接着被圣光笼罩呗~

默认的 http://mirror.archlinuxarm.org/ 会自动解析到离用户较近的镜像, 也可以手动换成 中科大(崔土豪) 源, 方法在这 .

换好源以后更新一下系统 ( 记得两个 y 是强制刷新~ )

$ sudo pacman -Syyu

然后安装需要的软件 ( xorg xfce 和一个登录管理器,这里是 lightdm )

$ sudo pacman -S xorg xfce lightdm lightdm-greeter

至于如何配置 lightdm 咱就偷下懒推荐一下百合仙子 lilydjwg从 slim 到 lightdm 啦~

然后启动 lightdm 服务:

$ sudo systemctl start lightdm

树莓派3的性能写写博客还是可以的啦~

只是在生成 HTML 的时候系统负载会飙升 😂😂

rpi3 写博客中~

by ホロ at April 11, 2016 04:00 PM

Justin Wong

给妹子看的 Arch Linux 桌面日常安装

謝邀。

准备工作

首先,准备一张你参加活动得到的 Ubuntu 或者 Deepin ,或者其他什么发行版的安装光盘,是的它有包装很漂亮,哦别急着找光驱,找个打火机把它烧掉,以示决心。

然后,拿出你收藏多年的《鸟哥的Linux私房菜》,不用翻开,啊烧掉有点可惜,把他送给你的冤家就好了。 鳥哥是 RedHat 玩家,而且内容太老了,作为新手的你用鳥哥指导 Arch Linux 安装只能误入歧途。 (鳥哥很萌哒,我不该黑他)

洗个手,沐浴更衣,斋戒三天,挑选良辰吉日,面向紫禁城方向摆好计算机,准备迎接挑战。

在开始之前,请在心中默念三遍:

Arch Linux是世界上最好的发行版,我一定能掌握它!

安装

假设你的男朋友已经给你装过一个ArchLinux, 启动它,然后:

# pacman -S arch-install-scripts

保证你能连接Internet,且/mnt没有被挂上什么奇怪的东西

准备磁盘

首先进行分区,你新买的ssd,假设是/dev/sdb,我们使用fdisk进行分区,

先安装工具

# pacman -S fdisk parted

然后

# fdisk /dev/sdb

g建立分区表,然后n建立一个新分区,大小200MB,我们暂时不用它, 再n建立一个足够大的分区,如果你不需要交换空间,就把剩下的空间都分给他, 否则就再留下和内存大小相当的空间做swap。

于是我们得到了这样的分区结构:

  • /dev/sdb1: 200M,空着
  • /dev/sdb2: ~110G 用来装东西
  • /dev/sdb3: 交换区

接下来设置引导标签,

# parted /dev/sdb
set 1 bios_grub on
quit

然后格式化分区,对SSD,使用4K的块大小

# mkfs.ext4 -b 4096 /dev/sdb2

接下来就可以挂载了,使用discardnoatime选项对你的SSD有好处

# mount -t ext4 -o discard,noatime /dev/sdb2 /mnt

安装基本系统

运行

# pacstrap /mnt base base-devel vim

安装基本系统,base是基础软件包组,base-devel是基础开发包组,vim是世界上最好的编辑器。

配置基础系统

生成fstab

运行

# genfstab -U -p /mnt >> /mnt/etc/fstab

你可以先打开/mnt/fstab查看一下,保证/的挂载点有discardnoatime选项,如果分了交换区,就

# echo "$(blkid -o export /dev/sda3|grep '^UUID') swap swap defaults 0 0" >> /mnt/etc/fstab

chroot

chroot到新安装的基本系统中,chroot就是进入某个目录,把它变成/的意思啦

# arch-chroot /mnt

运行passwd,设置root密码,要敲两遍,不要忘了它。

主机名、时区、blah…

用vim打开/etc/hostname,往里面写一个作为主机名的名字,只要字母、横线和数字。

然后修改时区,

#  ln -s /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime

然后用vim打开/etc/locale.gen,然后找到以下四行,取消注释:

en_US.UTF-8
zh_CN.UTF-8
zh_CN.GBK
zh_CN.GB2312

然后运行# locale-gen

再编辑/etc/locale.conf,里面写上

LANG="en_US.UTF-8"

现在生成启动要用到的ramdisk,

# mkinitcpio -p linux

现在# pacman -S wpa_supplicant dialog,保证新系统可以联网。

现在你可以安装其他觉得需要的包,比如bash-completion什么的。

引导器

有很多引导器可以选,作为妹子的你,装grub-bios就好啦

# pacman -S grub

然后

# grub-install --target=i386-pc --recheck --debug /dev/sdb
# grub-mkconfig -o /boot/grub/grub.cfg

重启

退出chroot环境,exit, 接着就可以reboot了。

欢迎来到新大陆

这是一片新大陆,一片荒芜,却充满生机,欢迎成为这里的开垦者。

基础

先使用# wifi-menu连接互联网。

添加用户

# useradd -m yooo
# passwd yooo

你应该需要sudo,以运行# visudo,在root ALL=(ALL) ALL下面加一行yooo ALL=(ALL) ALL

装X

# pacman -S xorg xorg-xinit xterm xorg-xeyes xorg-xclock

然后就可以startx一下看看有没有一个完爆win 3.1的图形界面了,如果没有就给我打电话…

装yaourt

/etc/pacman.conf里加入

1
2
3
[archlinuxcn]
SigLevel = Optional TrustedOnly
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinuxcn/$arch

然后

# pacman -Sy archlinuxcn-keyring yaourt

这里添加的 ArchLinuxCN 源是 archlinuxcn.org 的第三方源,包括了不少常用软件。

做出选择

现在,你可以选择简单模式,还是Hard模式。

简单模式

安装gnome

# pacman -S gnome

完成之后,运行

# systemctl enable gdm
# systemctl start gdm

第一行是让gdm开机自启动,第二行是现在就启动它…

一切都应该work out of box, 如果没有的话,找gnome的人喷他们,他们觉得自己能造出普世的开箱即用桌面环境。

困难模式

安装i3窗口管理器

# pacman -S i3

安装 lightdm 显示管理器,

# pacman -S lightdm-gtk3-greeter

然后

# systemctl enable lightdm
# systemctl start lightdm

登陆进i3之后会自动加载配置向导,基本上一路next即可。

安装网络管理器

# pacman -S netork-manager-applet
# systemctl enable NetworkManager.service
# systemctl start NetworkManager.service

列个软件包列表,应该都是你需要的

  • firefox, flashplugin: 浏览器和flash插件
  • xfce4-terminal: 我推荐的终端模拟器
  • tmux: 你懂的
  • nautiluspcmanfmnemo: 文件管理器
  • rofi: 启动器
  • compton: 开透明什么的需要
  • pnmixer: 调音量
  • gthumb: 看图
  • gnome-screenshot, deepin-screenshot: 截图
  • lxappearence: 设置主题、外观
  • numix-theme, numix-circle-icon-theme-git: 我喜欢的主题和图标,装完用lxappearence设置生效
  • nitrogen: 设置壁纸
  • conky: 系统状态监视
  • xfce4-power-manager: 电源管理
  • mate-notification-daemon: 桌面通知

还有好多日常软件日后慢慢告诉你…

拷贝配置文件

把旧系统中,/home/yooo/里的以下文件拷到现在的$HOME对应的位置里:

  • .bashrc: Shell配置
  • .xprofile: 进入X时的环境文件
  • .i3/*: i3的配置文件
  • .vimrc, .vim/: vim配置文件
  • .tmux.conf: tmux配置文件
  • .fonts/: 一些字体
  • .config/fontconfig/: 字体配置

其他的,例如壁纸之类,看着拷回来就是了…

输入法

安装fcitx

# pacman -S fcitx-im fcitx-sunpinyin fcitx-cloudpinyin fcitx-configtool

然后,确保自己的~/.xprofile里有以下三行:

export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS="@im=fcitx"

你的~/.i3/autostart.sh会再启动i3时自动运行fcitx,右键那个图标,把sunpinyin给enable了。

多媒体

播放器和解码器:

# pacman -S gstreamer ffmpeg smplayer

音频

# pacman -S alsa-utils pulseaudio-alsa

把自己加到用户组里

# gpasswd -a yooo audio
# gpasswd -a yooo video

一些字体

你现在的字体应该还比较难看,装上这些包:

# pacman -S wqy-microhei ttf-dejavu ttf-droid cantarell-fonts adobe-source-han-sans-cn-fonts

你应该还需要写带中文的$\TeX$文档,

# pacman -S texlive-most
# yaourt -S acroread-fonts-systemwide

未完待续

以上。

謝邀。

准备工作

首先,准备一张你参加活动得到的 Ubuntu 或者 Deepin ,或者其他什么发行版的安装光盘,是的它有包装很漂亮,哦别急着找光驱,找个打火机把它烧掉,以示决心。

然后,拿出你收藏多年的《鸟哥的Linux私房菜》,不用翻开,啊烧掉有点可惜,把他送给你的冤家就好了。 鳥哥是 RedHat 玩家,而且内容太老了,作为新手的你用鳥哥指导 Arch Linux 安装只能误入歧途。 (鳥哥很萌哒,我不该黑他)

洗个手,沐浴更衣,斋戒三天,挑选良辰吉日,面向紫禁城方向摆好计算机,准备迎接挑战。

在开始之前,请在心中默念三遍:

Arch Linux是世界上最好的发行版,我一定能掌握它!

April 11, 2016 10:11 AM

百合仙子

MongoDB 到底要吃多少内存?

本文来自依云's Blog,转载请注明。

发现一只32G内存的服务器,上边跑了几个 sharding 模式的 mongod,把内存吃到只剩下4G,8G swap 更是丁点不剩。

我见过吃内存的 mongod,可没见过大胃口的 mongod 啊。不过以前我也没怎么见到在这么大内存的机器上跑的 mongod。不过不管如何,把 swap 全吃掉总归是不对的。

于是翻了翻 mongodb 源码,发现出现这种情况还真是机器的配置的问题。代码里有这么一段(在 GitHub 上的位置):

        if (cacheSizeGB == 0) {
            // Since the user didn't provide a cache size, choose a reasonable default value.
            // We want to reserve 1GB for the system and binaries, but it's not bad to
            // leave a fair amount left over for pagecache since that's compressed storage.
            ProcessInfo pi;
            double memSizeMB = pi.getMemSizeMB();
            if (memSizeMB > 0) {
                double cacheMB = (memSizeMB - 1024) * 0.6;
                cacheSizeGB = static_cast<size_t>(cacheMB / 1024);
                if (cacheSizeGB < 1)
                    cacheSizeGB = 1;
            }
        }

大概这就是决定它自己要用多少内存的代码了。先留出1G,然后再留出40%,剩下的能吃就吃!于是,好几只 mongod 开始抢食了!默认vm.swappiness=60的内核看到内存快用完了,于是开始往 swap 挪。结果造成内核挪多少,mongod 吃多少……

这种情况在机器内存少的时候没有出现,大概是因为内存少的时候,mongod 留出的比例比较高,内核就没那么卖力地把数据往 swap 上挪了。而且这次是好几只 mongod 哄抢呢。

by 依云 at April 11, 2016 07:10 AM

April 08, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (5) - 安装 Fedora

汝是不是想说'废话少说快教我怎么装 Linux 发行版'啦~

如果汝已经在运行一个 Linux 发行版的话,那么可以跳过接下来的几节.

如果汝有些心虚,想在虚拟机上先尝试一下,可以先去读一下 扫盲操作系统虚拟机系列@ 编程随想的博客

如果汝要直接装在电脑上,先做个USB启动盘啦~

( 啥? 不会? 看看这个 ? )

下载 Fedora Workstation

Fedora Workstation Live 镜像让您可以为自己电脑制作完整的立即可用的 Fedora Workstation 系统介质。您可以使用 Live 镜像测试、体验 Fedora,同时无需改动硬盘内容。当您满意之后,您可以从 Live 镜像安装 Fedora 到您的硬盘。

要使用该镜像,您需要可创建或刻录 DVD 的驱动器或者至少跟镜像大小一样的 USB 闪存盘。

这是官方的下载页面

Fedora 23 Workstation 系统需求 😂

这是最低需求啦~

  • CPU : 1Ghz 及以上
  • 内存 : 1GB 及以上 ( 如果汝不需要桌面环境可以少些 ~(>_<~) )
  • 硬盘空间 : 10GB 或更多的剩余空间

如果汝希望使用硬件加速 3D 图形,汝需要:

  • GMA9xx/GeForce FX5xxx /Radeon 9500 或更新的显卡 _(:з」∠)_ 或者

  • 汝的 CPU 支持 SSE2 指令集,这样就可以通过 LLVMpipe 利用 CPU 加速 3D 图形.

    看看汝的 /proc/cpuinfo 的 code:flags 一节里有没有 code:SSE2 啦~

在 Windows 下检查 ISO 的散列值

1, 从 https://fedoraproject.org/verify 根据选用的映像下载需要的散列值文件, 并把它们放在一起啦~

2, 打开 Windows PowerShell.切换到放置映像和散列值文件的文件夹.

3, 收集计算散列值需要的信息.

> $image = "<此处是汝的 ISO 文件的名称>"
> $checksum_file = "<此处是汝的 ISO 文件的散列值文件名称>"
> $sha256 = New-Object -TypeName System.Security.Cryptography.sha256CryptoServiceProvider
> $expected_checksum = ((Get-Content $checksum_file | Select-String -Pattern $image) -split " ")[0].ToLower()

4, 计算 ISO 的散列值,放轻松些 ( 可以去煮杯咖啡~ )

> $download_checksum = [System.BitConverter]::ToString($sha256.ComputeHash([System.IO.File]::ReadAllBytes("$PWD\$image"))).ToLower() -replace '-', ''

5, 然后比较~

> echo "Download Checksum: $download_checksum"
> echo "Expected Checksum: $expected_checksum"
> if ( $download_checksum -eq "$expected_checksum" ) {
echo "Checksum test passed!"
} else {
echo "Checksum test failed."
}

区分 MBR 和 UEFI 系统 | ω・`)

MBR 系统启动安装映像之后大概像这样 _(:з」∠)_

MBR 系统启动之后大概像这样
  • Start Fedora Live : 启动 Fedora 的 Live 环境,可以试用或是进行安装.
  • Troubleshooting : 供排解问题使用的额外选项 | ω・`)
  • 按下 Tab 键可以在启动前修改内核参数 ( 然而啥是内核参数咧 😂😂 )

那么 Troubleshooting 都有哪些咧 ?

这是疑难解答选项 _(:з」∠)_
  • Start Fedora Live in basic graphics mode : 以基本图形 (不启用硬件加速模式) 启动 Fedora 的 Live 环境.
  • Test this media & start Fedora Live : 在启动 Fedora 的 Live 环境之前先检查一下安装介质的完整性 Σ( ° △ °|||)
  • Run a memory test : 运行内存测试.....
  • Boot from local drive : 从本地硬盘启动操作系统.....

而 UEFI 启动大概像这样 (´・ω・`)

UEFI啦~

那还等啥? 直接 "Start Fedora Live" 啦~

准备安装啦~

如果汝选择的是 "Try Fedora" , 从左侧的 Activities(活动) 中可以找到安装程序 (╯ ̄- ̄)╯ ┻━┻

从左侧的 Activities (活动) 中可以找到安装程序 (╯ ̄- ̄)╯ ┻━┻

就是这里啦~ (用鼠标往左上角推)

Install Fedora to disk 在这里啦~

开始安装 (σ≧∀≦)σ

首先选择安装时使用的语言啦~

选择安装时使用的语言

接下来进入安装程序摘要,一般来说只要选择 "安装位置" 来调整存储设备就好.

安装程序摘要

咱是在 VirtualBox 中演示的安装,汝的屏幕上显示的内容可能和咱的不一样.

不过还是小心些好~


先从上方选择汝的硬盘,然后选择 "我要手动配置分区" ( 毕竟汝不大可能在一块全新的硬盘上安装吧~ ), 再点击 "完成" 进入下一步.

对于 MBR 系统

至少要有一个根分区 ( / ) _(:з」∠)_

点击下面的 + 号图标来创建一个新的分区:

创建一个新的分区~

选择挂载点和容量,然后确定.

对于 UEFI 系统

除了根分区以外还需要一个 EFI 系统分区~

UEFI 分区举例

( 咱偷懒用了自动分区 😂😂😂 )


准备好分区后,按 "完成" 提交汝的更改呗~

提交更改

这才是真正的开始安装啦 o(*≧▽≦)ツ

这时汝会发现最下面的 "开始安装" 可以点击了诶~

开始安装

接下来就开始安装啦~ 但是还需要再做两件事 _(:з」∠)_

  • 为 root用户设置密码:

    root 用户和 Windows 中的 Administrator 账户类似,都具有控制整个系统的权限,

    因此汝要设置一个安全的密码并保管好它哟~

设置 root 用户的密码
  • 然而由于 root 的权限太大,所以一般不建议用 root 进行日常操作,下一步就是创建一个普通用户,并为它设置一个密码.
创建一个新用户并设置密码

如果汝选择 "将此用户设置为管理员" 那么这个用户就可以通过 sudo 命令来获得管理员权限.

( 有点像 Windows 里的用户账户控制 😂😂 )

然后稍等一会儿就好啦~

安装完成啦~

重启进入新安装的 Fedora

要从 Live 环境重新启动,点击右上角,再点击电源图标,选择 "重启" _(:з」∠)_

重启

重启以后就会进入到这个 简洁(简陋) 的启动选项界面啦~

一般选第一个 ( 第二个是恢复模式 _(:з」∠)_ )

选择启动选项

然后稍候片刻进入登录画面,用汝刚刚创建的用户和密码登录吧~

登录界面

by ホロ at April 08, 2016 04:00 PM

March 30, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (1) - 一些名词解释

是不是有时觉得 Linux 中的概念有点天花乱坠 _(:з」∠)_

这篇文章会随着系列的更新介绍咱用到的术语的意思呐,也许汝不一定都要知道~有更新时会通知汝啦~

但是咱不是专业的啦,如果汝正好是个 Linux 高手的话, 来评论里或是直接和咱交流下呗~

本文 部分(几乎全部) 内容来自于维基百科 o(* ̄3 ̄)o ( 不过和咱一样都是知识共享 署名-相同方式共享 3.0协议授权啦~ )

基本中的基本概念 _(:з」∠)_

操作系统

操作系统(英语:operating system,缩写:OS)是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的核心与基石。 操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出装置、操作网络与管理文件系统等基本事务。 操作系统也提供一个让使用者与系统互动的操作界面。 操作系统的型态非常多样,不同机器安装的操作系统可从简单到复杂,可从非智慧型手机的嵌入式系统到超级电脑的大型作业系统。 许多操作系统制造者对它涵盖范畴的定义也不尽一致,例如有些操作系统整合了图形用户界面,而有些仅使用命令行界面,而将图形用户界面视为一种非必要的应用程式。

操作系统理论在计算机科学中,为历史悠久而又活跃的分支;而操作系统的设计与实现则是软件工业的基础与核心。

(下面是一幅典型的操作系统架构图~)

典型的操作系统结构图

操作系统位于底层硬件与用户之间,是两者沟通的桥梁。用户可以通过操作系统的用户界面,输入命令。操作系统则对命令进行解释,驱动硬件设备,实现用户要求。以现代标准而言,一个标准PC的操作系统应该提供以下的功能:

  • 进程管理(Processing management)
  • 内存管理(Memory management)
  • 文件系统(File system)
  • 网络通信(Networking)
  • 安全机制(Security)
  • 用户界面(User interface)
  • 驱动程序(Device drivers)

操作系统内核

在計算機科學中,内核(英语:Kernel),又稱核心,是一個電腦程式,用來管理軟體發出的資料I/O(輸入與輸出)要求,將這些要求轉譯為資料處理的指令, 交由中央處理器(CPU)及電腦中其他電子元件進行處理,是現代操作系统中最基本的部分。它是为众多应用程序提供对计算机硬件的安全访问的一部分软件, 这种访问是有限的,并由内核决定一个程序在什么时候对某部分硬件操作多长时间。直接对硬件操作是非常复杂的。所以内核通常提供一种硬件抽象的方法, 来完成这些操作。通过进程间通信机制及系统调用,应用进程可间接控制所需的硬件资源(特别是处理器及IO设备)。

严格地说,内核并不是计算机系统中必要的组成部分。程序可以直接地被调入计算机中执行;这样的设计, 说明了设计者不希望提供任何硬件抽象和操作系统的支持;它常见于早期计算机系统的设计中。最终,一些辅助性程序,例如程序加载器和调试器, 被设计到机器核心当中,或者写入在只读记忆体里。这些变化发生时,操作系统内核的概念就渐渐明晰起来了。

所谓的"操作系统内核",就是操作系统最核心最关键的部件啦。它负责一些最基本的工作,比如:管理硬件驱动、管理内存、管理文件系统、管理进程、等等。这些工作只要少了任何一样,整个操作系统都没法运转。

Linux 相关 ~(>_<~)

Linux 内核

Linux内核(英语:Linux kernel),是一种计算机操作系统内核,以C语言和汇编语言写成,符合POSIX标准,以GNU通用公共许可证釋出。Linux内核最早是由芬兰黑客林納斯·托瓦茲为尝试在自己的英特尔x86架构计算机上提供自由免费的类Unix系统而开发的。该计划开始于1991年,林納斯·托瓦茲当时在Usenet新闻组comp.os.minix登载帖子[7],这份著名的帖子標示着Linux内核计划的正式开始。

在计划的早期有一些Minix的黑客提供了协助,而今天全球有无数程序员正在为该计划无偿提供帮助。

从技术上说Linux只是一个内核。“内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等功能的系统软件。一个内核并不是一套完整的操作系统。有一套基于Linux内核的完整操作系统叫作Linux操作系统,或是GNU/Linux(在该系统中包含了很多GNU计划的系统组件)。

Linux 内核的特点是:彻底的开放性。所谓的"开放性"包括如下几方面:

  1. 任何人都可以随意获取(可以从 Linux Kernel 官网直接下)
  2. 任何人都可以免费获取(完全不用花银子)
  3. 任何人都可以参与开发(阿猫阿狗都可以向 Linux 社区提交代码,只要你提交的代码符合要求,就会被合并到内核主线)

Linux 操作系统

Linux 是一種自由和開放源碼的類UNIX作業系統。该操作系统的内核由林纳斯·托瓦兹在1991年10月5日首次发布。 在加上使用者空間的應用程式之後,成為Linux作業系統。Linux也是自由软件和开放源代码软件发展中最著名的例子。 只要遵循GNU通用公共许可证,任何个人和机构都可以自由地使用Linux的所有底层源代码,也可以自由地修改和再发布。 大多數Linux系統還包括像提供GUI的X Window之類的程序。除了一部分專家之外,大多數人都是直接使用Linux發行版,而不是自己選擇每一樣組件或自行設置。

严格来讲,术语Linux只表示操作系统内核本身,但通常采用Linux内核来表达该意思。Linux则常用来指基于Linux内核的完整操作系统, 包括GUI组件和许多其他实用工具。由于这些支持用户空间的系统工具和库主要由理查德·斯托曼于1983年发起的GNU计划提供,自由软件基金会提议将该组合系统命名为GNU/Linux,但Linux不屬於GNU計劃。

Linux 发行版

Linus 领导的开源社区只负责开发内核,不开发其它的东西(比如:运行库、图形界面、应用软件、等)。

这就引出一个问题——光有一个赤裸裸的内核,用户是没法用的(就好比你光拿到一个汽车引擎,你是没法开车的)。为此,就有一大帮开源社区或商业公司,在这个裸露的内核外面,再包上一些东西(比如:运行库、应用软件)。经过这样包装之后,就成为"发行版"。

在这种模式下,会有各种各样的发行版,正好可以覆盖千奇百怪的需求;其次,同质化的发行版之间会产生竞争,最终只有优秀的发行版会存活,差劲的发行版会逐渐消亡——这就是开源生态圈的"达尔文主义"。

如果用一个词来形容 Linux 的优点,那就是——多元化。内核的开发是多元化的(任何人都可以参与),发行版是多元化的(任何人都可以搞发行版)。

硬盘相关

MBR ( Master Boot Record , 主引导记录 )

主引导记录(Master Boot Record,缩写:MBR),又叫做主引导扇区,是计算机开机后访问硬盘时所必须要读取的首个扇区,它在硬盘上的三维地址为(柱面,磁头,扇区)=(0,0,1)。在深入讨论主引导扇区内部结构的时候,有时也将其开头的446字节内容特指为“主引导记录”(MBR),其后是4个16字节的“磁盘分区表”(DPT),以及2字节的结束标志(55AA)。因此,在使用“主引导记录”(MBR)这个术语的时候,需要根据具体情况判断其到底是指整个主引导扇区,还是主引导扇区的前446字节。

从主引导记录的结构可以知道,它仅仅包含一个64个字节的硬盘分区表。由于每个分区信息需要16个字节,所以对于采用MBR型分区结构的硬盘,最多只能识别4个主要分区(Primary partition)。所以对于一个采用此种分区结构的硬盘来说,想要得到4个以上的主要分区是不可能的。这里就需要引出扩展分区了。扩展分区也是主要分区的一种,但它与主分区的不同在于理论上可以划分为无数个逻辑分区。[2]

扩展分区中逻辑驱动器的引导记录是链式的。每一个逻辑分区都有一个和MBR结构类似的扩展引导记录(EBR),其分区表的第一项指向该逻辑分区本身的引导扇区,第二项指向下一个逻辑驱动器的EBR,分区表第三、第四项没有用到。

Windows系统默认情况下,一般都是只划分一个主分区给系统,剩余的部分全部划入扩展分区。这里有下面几点需要注意:

  • 在MBR分区表中最多4个主分区或者3个主分区+1个扩展分区,也就是说扩展分区只能有一个,然后可以再细分为多个逻辑分区。
  • 在Linux系统中,硬盘分区命名为sda1-sda4或者hda1-hda4(其中a表示硬盘编号可能是a、b、c等等)。在MBR硬盘中,分区号1-4是主分区(或者扩展分区),逻辑分区号只能从5开始。
  • 在MBR分区表中,一个分区最大的容量为2T,且每个分区的起始柱面必须在这个disk的前2T内。你有一个3T的硬盘,根据要求你至少要把它划分为2个分区,且最后一个分区的起始扇区要位于硬盘的前2T空间内。[3]如果硬盘太大则必须改用GPT。

UEFI ( Unified Extensible Firmware Interface, 统一可扩展固件界面)

统一可扩展固件界面(Unified Extensible Firmware Interface, UEFI)是一种个人电脑系统规格,用来定义作业系统与系统固件之间的软件界面,作为BIOS的替代方案[1]。可扩展固件接口负责加电自检(POST)、连系作业系统以及提供连接作业系统与硬体的介面。

UEFI的前身是Intel在1998年开始开发的Intel Boot Initiative,后来被重命名为可延伸韧体介面(Extensible Firmware Interface, EFI)。Intel在2005年将其交由统一可扩展固件接口论坛(Unified EFI Forum)来推广与发展,为了凸显这一点,EFI也更名为UEFI(Unified EFI)。UEFI论坛的创始者是11家知名电脑公司,包括Intel、IBM等硬件厂商,软件厂商Microsoft,及BIOS厂商AMI、Insyde及Phoenix。

by ホロ at March 30, 2016 04:00 PM

March 29, 2016

ヨイツの賢狼ホロ

自定 Pelican 主题

论颜值的重要性 (雾

谁叫这是个看脸的世界呢~

Pelican 的默认主题的效果是啥, 大概像这个样子 (╯>_<)╯ ┻━┻

觉得不爽,那就改它呗~

首先把默认的 simple(什么都没有) 主题复制出来,接下来就基于它来修改呗~

# cp 的 -R (--recursive) 参数表示递归的复制文件夹中的文件.

# 如果汝的 Python 安装在不同的目录下,记得改了.

cp -R /usr/lib/python3.5/site-packages/pelican/themes/simple /path/to/your/pelican/

不过话说回来为啥不直接看 Pelican 官方的文档咧?

Creating themes

Step 1 : 了解一下 Pelican 主题的结构

典型的 Pelican 主题大概像这样:

├── static                    // 各类静态数据
│   ├── css                   // 例如 CSS.....
│   └── images                // 和图像
└── templates                 // 用来生成页面的模板
    ├── base.html             // 模板的基础
    ├── archives.html         // 文章归档
    ├── period_archives.html  // 分时段的文章归档
    ├── article.html          // 文章
    ├── author.html           // 按作者分类的文章归档
    ├── authors.html          // 作者列表
    ├── categories.html       // 分类列表
    ├── category.html         // 按分类的文章归档
    ├── index.html            // 首页
    ├── page.html             // 页面
    ├── tag.html              // 标签
    ├── pagination.html       // 分页
    └── tags.html             // 标签列表

如果觉得哪个用不到,直接删掉好了~

另外,像首页啦,分类列表,标签列表这些直接生成一个页面的模板 ( 区分于文章和页面这样的模板 ),如果汝有用到其他的,记得在 pelican.conf 里设置:

# 直接生成的页面的列表,不用加上 .html 的扩展名.

DIRECT_TEMPLATES = (('index', 'archives', 'search'))

Step 2 : 修改基础模板 ( base.html )

(请允许咱不厌其烦的把 html 代码贴在上面 _(:з」∠)_ )

<!DOCTYPE html>
    <!--
    像这样用大括号包围起来的是变量啦,可以来自 pelicanconf.py
    文章,页面,和分类也提供了一些变量呐~
    -->
    <html lang="{{ DEFAULT_LANG }}">
    <head>
    <!--
    其它模板页面可以扩展或是替换掉 block 中的内容呗~
    -->
    {% block head %}
    <title>{% block title %}{{ SITENAME }}{% endblock title %}</title>
    <meta charset="utf-8" />
    <!--
    Python 中的 if 语句,如果后面的变量有内容的话,显示块中的内容呗~
    -->
    {% if FEED_ALL_ATOM %}
    ......
    {% endblock head %}
</head>

<body id="index" class="home">
    <header id="banner" class="body">
            <h1><a href="{{ SITEURL }}/">{{ SITENAME }} <strong>{{ SITESUBTITLE }}</strong></a></h1>
    </header><!-- /#banner -->
    <nav id="menu"><ul>
     <!--
    Python 中的 for 循环 <(=﹁"﹁=)>
    -->
    {% for title, link in MENUITEMS %}
        <li><a href="{{ link }}">{{ title }}</a></li>
    {% endfor %}
    {% block content %}
    {% endblock %}
    <footer id="contentinfo" class="body">
            <address id="about" class="vcard body">
            Proudly powered by <a href="http://getpelican.com/">Pelican</a>,
            which takes great advantage of <a href="http://python.org">Python</a>.
            </address><!-- /#about -->
    </footer><!-- /#contentinfo -->
</body>
</html>

因为 Pelican 用的是 Jinja2 模板引擎嘛,所以 先去看看 Jinja 的文档嘛~

如果看不懂的话,pia 啦~ (╯・﹏・)╯ ┻━┻ 这里只举一个加入 CSS 的栗子:

首先把 CSS 放到 static/css 文件夹里,然后修改 base.html

{% block head %}
    <!-- static 文件夹输出以后就是 /theme 啦~ -->
    <link href="{{ SITEURL }}/theme/css/metro.css" rel="stylesheet">

{% endblock head %}

就这样 ~(>_<~)

Step 3 : 修改子模板

再举一个文章的栗子 (´・ω・`)

<!-- entends 就是扩展啦,后面是基于的模板页面的名称 -->
{% extends "base.html" %}
{% block head %}
<!-- 用 super () 来包含 block 默认的内容 -->
{{ super() }}
{% for keyword in article.keywords %}
<meta name="keywords" content="{{keyword}}" />
{% endfor %}

{% endblock %}
{% block content %}
<!-- 这里加上需要的内容 -->
{% endfor %}
</dl>
{% endblock %}

本来打算贴出模板里能用的变量的,不过咱有了要翻译 Pelican 文档的想法了呐~ ( todo list 要爆炸的节奏 )

by ホロ at March 29, 2016 04:00 PM

March 26, 2016

ヨイツの賢狼ホロ

Weechat + Glowing Bear 打造一个网页版 IRC

Weechat + Glowing Bear 打造一个网页版 IRC ,这样在哪里都可以聊天了呐~

为啥要自己搭建一个网页版 IRC 咧?

  • 不是啥设备都有聊天软件客户端呐~ (比如 PS Vita ) (╯@Д@)╯ ┻━┻
  • freenode 的 WebIRC 很不错,但是验证码是 Google 的,于是又引出了怎么翻墙的问题 ~

为啥是 WeeChat ?

多半是 farseerfc 的安利呗~

Prolgue: 安装 weechat

weechat 在好几个平台上都有二进制包啦~

  • Arch Linux: pacman -S weechat
  • Cygwin (Windows): select WeeChat packages in setup.exe
  • Debian 及其衍生发行版: apt-get install weechat-curses
  • Fedora Core: dnf install weechat
  • Gentoo: emerge weechat
  • Mandriva/RedHat (或其他基于 RPM 包管理器的发行版): rpm -i /path/to/weechat-x.y.z-1.i386.rpm
  • openSUSE: zypper in weechat
  • Sourcemage: cast weechat
  • OS X + Homebrew : brew install weechat --with-python --with-perl

如果需要编译的话 , 去看 weechat 的文档啦~

Act 0 : 准备 SSL 证书

首先运行一次 weechat 来生成需要的文件,然后输入 /quit 来退出.

$ weechat && mkdir -p ~/.weechat/ssl

如果汝有自己的域名的话,为何不试试 Let's Encrypt ?

如果没有的话,那就只好自己签名一个证书啦 _(:з」∠)_

  • 如果汝自己有证书:

    把证书和私钥保存成一个文件:

    $ cat /path/to/your/cert /path/to/your/privkey >> ~/.weechat/ssl/relay.pem

  • 如果没有域名的话,只好自己生成一个证书啦 (╯´ー`)╯ ┻━┻

    $ cd ~/.weechat/ssl

    $ openssl req -nodes -newkey rsa:2048 -keyout relay.pem -x509 -days 365 -out relay.pem

  • 接下来运行一下 weechat 来设置一下 relay:

    # 咱不知道怎么把 weechat 设置成服务,于是就用 screen 了 😂😂

    $ screen weechat

    # 加载证书和私钥

    /relay sslcertkey

    # 为 relay 设置一个密码 ( 用实际的密码替换 "mypassword" )

    /set relay.network.password "mypassword"

    # 打开中继

    /relay add ssl.weechat 9001

    然后可以用 Ctrl + a + d 断开 screen 了 (´・ω・`)

Act 1 : 连接到 relay

如果汝不想自己搭建的话,可以用 glowing-bear 自己的呗~

链接在这: https://www.glowing-bear.org/

按照上面的指南来连接吧~

如果汝要自己搭建一个的话,首先需要一个 Web 服务器啦~ ( Apache 和 Nginx 都不错,ArchWiki 上能找到文档~)

然后从

glowing-bear 的 Github 项目页面上参考上面的提示把 glowing-bear 下载到本地呐~

就是这样?

常用操作一览

  • 指定一个服务器:

    /server add <名称>/<端口> <irc服务器的域名> [ -ssl ( 启用SSL ) ] [ -autoconnect 在启动时自动连接 ]

    /server add freenode chat.freenode.net/6697 -ssl -autoconnect

  • 连接到服务器:

    /connect <名称>

    /connect freenode

  • 修改昵称

    /nick <新昵称>

  • 加入一个频道

    /join <频道名称>


by ホロ at March 26, 2016 04:00 PM

March 25, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (4) - 八卦一下软件包管理器

软件包管理器差不多是 Linux 发行版的标准配置了吧~

软件包和软件包管理器是啥?

软件包是对于一种软件所进行打包的方式。一般来说一个软件包包含这些内容呐~

  • 软件的源代码或可执行文件.
  • 一些供其它应用 ( 例如软件包管理器 ) 解析的元数据. (例如软件的名称,描述,版本,等等......)
  • 一组用来执行安装前后事务的脚本.

而软件包管理器,当然就是来安装/卸载/更新软件包的一组应用程序咯~

软件包管理器是在电脑中自动安装、配制、卸载和升级软件包的工具组合, 在各种系统软件和应用软件的安装管理中均有广泛应用。

一般来说,一个软件包管理器有这样的功能:

  • 从软件仓库中查询软件包的信息,并在需要时下载.
  • 同时处理软件包需要的其它软件 ( 常常称作"依赖" )
  • 验证下载的文件的完整性 ( 例如通过散列值或是数字签名 )
  • 通过归档工具解开软件包,然后把文件安放到正确的位置上.
  • 其它方便用户的功能 ( 例如软件包组,自动检查更新等等 )

为啥需要个软件包管理器?

首先大家先来回忆一下在 Windows 里是如何装软件的呗~

  • 打开搜索引擎搜索一下
  • 找到个没被墙的下载网站.....
  • 从网页上数十个硕大而带有欺骗性的广告的缝隙中找到真正的下载链接.
  • 然后下载......
  • 下完以后运行,挑掉一堆勾😂😂,一路下一步直到完成 _(:з」∠)_

是不是很痛苦? 不过通过软件包管理器,汝就可以把安装软件的过程简化到 "安装某个软件" 就可以啦~

而且大多数软件包管理器都是从特定的软件仓库下载软件包,一般不用担心会夹带私货等问题 o(* ̄3 ̄)o

大家经常说的软件源,镜像源是啥?

软件包管理器会自动上网去下载软件,但他可不是四处瞎找,而是去固定的地方找。

这个固定的地方有个名字,叫做软件源。那里专门提供各 种打包好的软件以及相关的信息介绍,供软件包管理器们下载。

这样的软件源有很多,遍布世界各地,软件包管理器应该去哪个呢?其实他自己也不知道,

他需要一个列表,一个软件源列表。软件包管理器工作的时候,就会去一个软件源列表记录的地方去下载软件。

有的人可能离的挺近,去默认的源就很方便,有的人去默认的源可能就很费劲,没准得绕过半个地 球才行。默认的源不够快,自然就需要找个快一点的源来代替。

然后世界各地的 Linux 用户们就会去建设不同的镜像源来方便本地的 Linux 用户呐~ ( 例如有爱的崔土豪 cuihao ~)

典型的软件包管理器的工作方式 _(:з」∠)_

咱来举个安装软件包的栗子~

用户 : 我想安装foo

软件包管理器 : 先让咱在软件仓库里找一下 (´・ω・`)

如果找不到的话,软件包管理器就会告诉用户 "咱找不到汝说的 foo 软件包呐~"

如果找的到的话:

"咱在软件仓库里找到 foo 了呐~,不过 foo 说要带上它的助手 baz 才会来嘛~

( 就是说要安装 foo 需要同时安装它的依赖项 baz )

如果用户同意了的话,软件包管理器就会去软件仓库把 foo 和 baz 带回来 ( 也就是下载这两个软件包 )

接着软件包管理器会检查下载来的软件包是否和数据库中的描述 (散列值 ) 一致, 如果相同的话就会开始安装啦~

在安装结束后,软件包管理器一般都会把具体过程写到自己的日记 (日志) 里方便以后使用呗~

当然啦,不同的软件包管理器有不同的表现呐~

几种常见的软件包管理器 (及其前端)

dpkg ( Debian Package Manager, Debian 软件包管理器 )

dpkg是Debian软件包管理器的基础,它被伊恩·默多克创建于1993年。 用于安装、卸载和供给和.deb软件包相关的信息。

dpkg本身是一个底层的工具。上层的工具,像是APT,被用于从远程获取软件包以及处理复杂的软件包关系。

apt-get / apt / aptitude 和 Synaptic (新立得软件包管理器) 是流行的 dpkg 前端.

基于 Debian 的发行版 (例如 Ubuntu 和 Linux Mint ) 也采用 dpkg 作为包管理器.

RPM ( The RPM Package Manager,RPM 包管理器)

RPM包管理员(简称RPM,全称为The RPM Package Manager)是在Linux下广泛使用的软件包管理器。

RPM此名词可能是指.rpm的文件格式的软件包,也可能是指其本身的软件包管理器(RPM Package Manager)。

最早由Red Hat研制,现在也由开源社区开发。RPM通常随附于Linux发行版,但也有单独将RPM作为应用软件发行的发行版(例如Gentoo)

不过和 dpkg 不一样的是使用 RPM 的 Linux 发行版都喜欢自己造轮子呐~

  • Yum(Yellow dog Updater, Modified),最常见的 RPM 前端.

    由Duke University团队,修改Yellow Dog Linux的Yellow Dog Updater开发而成. Yellow Dog Linux本身,Fedora (22 以前)、Red Hat Enterprise Linux,和 CentOS 都在使用它作为前端.

  • DNF,全称Dandified Yum,是RPM发行版的软件包管理器 Yellowdog Updater, Modified(yum)的下一代版本。Fedora 22 开始成为默认的 RPM 前端.

  • ZYpp (或称 libzypp ) 是一个软件包管理引擎,通常在 openSUSE/SUS E以 YaST 、Zypper 为前端使用。不像其他的软件包管理器,它提供一个强力的可满足性求解器来计算软件包相依性,也提供了一组方便的软件包管理API.它是一个由 Novell 所赞助的开放源代码且为自由软件的项目,采用GNU通用公共许可证第二版或更新授权。

  • urpmi 是 Mageia/Mandriva Linux 及其派生发行版的软件包管理系统,它解决了RPM包管理员容易让用户经常遇到相依性地狱的问题,也可以从官方或非官方的来源获得软件包.

pacman

pacman软件包管理器是 Arch Linux 的一大亮点。它将一个简单的二进制包格式和易用的构建系统结合了起来。 不管软件包是来自官方的 Arch 库还是用户自己创建,pacman 都能方便得管理。

pacman 通过和主服务器同步软件包列表来进行系统更新, 这使得注重安全的系统管理员的维护工作成为轻而易举的事情。

这种服务器/客户端模式可以使用一条命令就下载/安装软件包,同时安装必需的依赖包。 pacman 用 C 语言编写,使用 .pkg.tar.xz 打包格式。

Arch Linux 和 基于 Arch Linux 的发行版使用 pacman 作为软件包管理器.

( 最早 pacman 既是前端又是后端,后来为了方便 pacman 和其它程序协作,分离出 libalpm 作为后端 )

作为现 Arch Linux 用户,自然要挺一下 Pacman 啦~ ,这里贴出 Arch Linux Trust User farseerfc 在知乎上的一篇回答呗~

为什么说Arch Linux的pacman包管理系统更先进?相比与apt或rpm等好在哪里呢? - fc farseer 的回答 - 知乎

Portage

Portage是Gentoo Linux所使用的包管理器,基于ports collection机制。Portage的高度灵活性令Gentoo独立于操作系统并获得了元发行版的称号。

Portage主要特色是从源码编译用户所需要安装的软件包。此过程中用户可以调整编译器和目标程序的选项以符合系统需要或自己的喜好。与系统管理相关的功能包括:允许平行版本安装、追踪跨软件包依赖、维护记录已安装软件的数据库、提供本地ebuild库、使本地库与远程库相同步。与个别软件包安装相关的功能有:为目标机器指定编译选项、定制构成软件包的组件。

只是作为基于源代码的软件包管理器,即时编译很消耗 CPU 和 时间 😂😂😂


由于软件包管理器的命令都不相同,咱接下来的文章中会用到 apt / dnf / pacman 当作例子呗~

ArchWiki 上的 Pacman/Rosetta 页面 有几种常见的软件包管理器的命令比较呗~

按照汝的发行版学习一些基本的操作吧 (下次咱要说啥咧?)

by ホロ at March 25, 2016 04:00 PM

March 24, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (3) - 选择一个发行版

有这么多 Linux 发行版,咱该选哪个呢?

Linux 的发行版实在是太多啦~,光是比较知名的就有数十种 ( DistroWatch 是个比较各种发行版流行程度的网站~ ).

如何选择真是个难题呐~ (╯@_>@)╯ ┻━┻

萌新选择发行版的第一奥义 (๑•̀ㅂ•́)و✧

萌新选择发行版的第一奥义是......

一定要选择一个成熟的发行版~

大多数成熟的发行版都具有这样的特征:

  • 用户和活跃的开发者很多呐~

    成熟的发行版名气都比较大,自然用户就很多呗~

    用户可是有可能转变成 (大多数) 不吃人的开发者呐~

    成熟的发行版通常都会有很多新人遇到几乎相同的问题,于是就有了第二个特征~

  • 有详尽的文档

    被要求控制自己的本能的 开发者为了方便回答各种萌新向问题,就会写出各种各样的文档啦~

    成熟的发行版通常都会有完善的文档 (有些发行版还有多语言版的文档呐~)

  • 有一群有爱的开发者~

    成熟的发行版一般都会有一群有爱的开发者啦~

    他/她/它们编织代码和文档,尽心尽力的回答用户的问题, 努力跟踪上游的更改.Ta们可是很辛苦的哟~

    别害怕啦,Ta们 (多数) 不会吃人啦~

Act 2 : 选择发行版时要考虑的几个因素

说了这么多,那么选择发行版时到底要考虑哪些因素咧? o(* ̄3 ̄)o

发行版的制作群 : 社区发行版 or 商业发行版

汝以为以为"非营利组织"的研发能力不如"商业公司"?

其实不然——非营利组织也可以做出精品。想想浏览器的例子:非营利组织开发的 Firefox 远远好于(头号软件公司)微软开发的 IE。

对于这两者的选择,主要的考虑因素是:隐私。

商业发行版在隐私保护方面不如社区发行版。举个栗子 ヨイツの賢狼ホロ, _(:з」∠)_ Ubuntu 属于商业发行版(其后台是 Canonical公司)。Ubuntu曾经爆了一个丑闻:其桌面搜索功能存在隐私泄露风险(相关报道在 这里

简而言之: 如果汝在意自己的隐私,那么建议用社区发行版呐~

发行版的定位 : 通用 or 专用

所谓的"通用发行版",顾名思义就是:这个发行版可以派上各种用场;反之,"专用发行版"是为特定用途设计,只能用于某些特定场合。

两种各有优缺点——通用发行版虽然用途广,但汝需要自己定制一下啦~。专用发行版虽然用途单一,但很多软件和配置预先都帮你设置好了,可以达到 "开箱即用" 的标准呗~

所以:

  • 如果汝第一次尝试 Linux?

    建议先尝试"面向桌面"的专用发行版。它们的用户数都比较大,门槛都比较低,上手相对容易。

    用了一段时间之后,如果汝觉得要进一步学习的话,不妨来试试那些通用发行版呗~

  • 已经在用某个 Linux 发行版,想进一步提高?

    去试试通用发行版呗~ 一般通用发行版的文档都很齐备,有问题可以先去查查文档,也可以提高汝的英语水平呐~

( 汝问哪个发行版算通用/专用 ,待会儿告诉汝啊~所以现在先别着急 😂😂😂 )

软件的更新速度 : 保守型 or 激进型

简单来说,保守型的发行版通常更在意系统和软件的稳定性/可靠性/安全性。 为了做到这点,适当地牺牲了"新功能"。所以,它们通常都不会采用最新版本的内核或软件。而是采用不太新,但久经考验的版本。

而激进型的呢,这类发行版优先保证"新功能"。所以它们总是第一时间升级内核版本或软件版本。

所以:

如果汝比较关注安全性/稳定性,就选择保守型的发行版. 喜欢新功能就选择激进型的发行版呗~

发行版的发布周期 : 基于版本发布 or 滚动更新

按版本发布的发行版,就像Windows 和 OS X 一样,按周期发布一个新版本 (只是有些发行版升级版本时经常挂掉以至于只好重装......)。

但是有少部分发行版采用滚动发布,对于"滚动发布"的模式,不存在版本号,也不需要重装系统。对于这类系统,你只需要安装一次,以后只要通过更新就可以更新系统啦~

采用滚动方式发布的 Linux,通常都是激进型的啦 ( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)

简而言之:

看汝的喜好啦~

说了这么多,到底该选择哪个发行版咧? <(ノ=﹁"﹁=)ノ┻━┻

下面咱就推荐一些发行版咯~ 汝可以根据上面几个因素,挑出几个汝认为合适的发行版试试呗~

(按字母顺序排序,顺便夹杂一些咱自己的偏见 😂😂😂 )

Arch Linux

属性:激进的社区发行版

Arch Linux 是一个针对 i686/x86-64 平台独立开发的 GNU/Linux 发行版,遵循轻量、简洁、优雅的开发原则,借灵活的架构应用于各种环境。Arch 安装后只提供最基本的系统,用户可以根据自己的需求来搭建不同的系统环境。官方并不提供图形化的配置工具,多数系统配置是通过修改文本文件来进行的。Arch 尽力提供最新稳定版本的软件。

Arch Linux 采用“滚动升级”策略,这样可以实现“一次安装,永久更新”。升级到下一个“版本”的 Arch Linux 几乎不需要重新安装系统,只需一行命令,你就能轻松的享受到最新的 Arch Linux。

Arch Linux 努力和上游软件源码保持一致,只有使程序能够在 Arch Linux 正常编译运行的补丁才会被加入更新中。

总之, Arch Linux 是一个灵活、简洁的、满足有一定经验的 Linux® 用户的需求的发行版。它强大且易于管理的特性,使其成为可以完美胜任服务器和工作站的发行版。它可以变成任何你想要的样子。如果你也认为这是一个 GNU/Linux 发行版该做的,欢迎你来自由使用并参与其中,为社区做出贡献,欢迎来到 Arch Linux!

---- Arch Linux 中文社区

( PS : 咱现在在用这个 o(* ̄3 ̄)o ,目前感觉良好~ )

Debian

属性:偏保守的社区发行版

Debian 计划是一个致力于创建一个自由操作系统的合作组织。我们所创建的这个操作系统名为 Debian。

操作系统是使计算机运行的基本程序和工具的集合,其中最主要的部分称为内核 (kernel)。内核是计算机中最重要的程序,负责一切基本的调度工作,并让您运行其他程序。

Debian 系统目前采用 Linux 内核或者 FreeBSD 内核。 Linux 是一个最初由 Linus Torvalds 创建,目前由全球成千上万的程序师共同维护的软件。 FreeBSD 是一个包括内核和其它软件的操作系统。

我们所创建的这个操作系统中的大部分基本工具来自于 GNU 工程;因此我们把它们命名为 GNU/Linux 。这些工具同样都是自由的。

当然,人们真正需要的是应用软件,也就是帮助他们完成工作的程序:从文档编辑,到电子商务,到游戏娱乐,到软件开发。Debian 带来了超过 43000 个 软件包 (为了能在您的机器上轻松的安装,这些软件包都已经被编译包装为一种方便的格式) — 这些全部都是自由软件。

这有点像一个高塔:在最底层的是内核,在内核上面的是所有的基本工具,然后是所有您在计算机上运行的软件。最后,在这个高塔顶端的就是 Debian — 把每件事情谨慎的组织和配合在一起,使得它们能够在一起和谐地运作。

---- Debian.org

( PS : 咱在 Arch 前就在用 Debian,后来为了使用新软件和因为升级版本时挂了才换的 Arch ~ )

Fedora

属性:偏激进的社区发行版

Fedora 是一个基于 Linux 的操作系统,旨在为用户提供稳定、安全且易于使用和管理的自由和开源软件。Fedora 发行版是 Fedora 项目的各种自由软件创造中最大的一个。由于其与生俱来的优势,"Fedora" 这个单词通常可以用于表达 Fedora 项目或 Fedora 发行版二者之中的任意一个。

我们尝试总是做正确的事情,并只提供自由开源的软件。我们积极努力保护和推广任何人都可以自由使用和重新发布的解决方案。为此,Fedora 本身的基础设施均由自由软件强力驱动。有鉴于此,所有的开发人员都专注的与 上游开发团队一起紧密工作,于是所有人都能从我们的工作中受益,并尽可能快地获得我们所做的改变。由于 Fedora 推动了大量的 创新项目,这个重点已经有显著和持久的影响。

我们认为软件专利是有害的,它是阻碍软件创新的拦路虎,且不符合自由开源软件的价值观。尽管通过紧密集成专有软件或专利组件可能在表面上改进易用性,但这决不是长久之计。在短期的易用和自由软件的长期发展之间,Fedora 始终倾向于后者。

---- Fedora Project Wiki

Gentoo Linux

属性:激进的社区发行版

首先,欢迎使用Gentoo,您将会进入一个选择自由和性能至上的世界。Gentoo的一切都是为了自由选择。在安装Gentoo时就数次明确表明了这一特点——用户可以自己选择想要编译的一切内容、选择安装Gentoo的方式、选择想用的系统日志程序等等。

Gentoo 是一个快速、现代化的元发行版,它的设计简洁、灵活。Gentoo 围绕自由软件建立,它不会对它的用户隐瞒“引擎盖下的细节”。Gentoo 所使用的软件包维护系统 Portage 是用 Python 编写的,这意味着用户可以轻松地查看和修改它的源代码。 Gentoo 的软件包管理系统使用源代码包(虽然也支持预编译软件包),并通过标准的文本文件配置Gentoo。换句话说,开放无处不在。

“自由选择”是 Gentoo 运行的关键,这点很重要,大家要理解。我们尽量不强迫用户去做任何他们不喜欢的事情。

---- Gentoo Wiki

openSUSE

属性:可保守可激进的社区发行版

openSUSE 发行版是一个稳定、易用和完整的多用途发行版,适用于从普通用户到开发者,从个人电脑到服务器,从初学者、有经验的用户到超级极客,总而言之,她适用于任何人!

最近发布的 openSUSE 13.2 ,更新了所有的应用程序的版本,包括服务器的应用程序和桌面的应用程序,并引入一些新的特性,目前她吸纳了1000多个的开源项目。

此外,openSUSE 还是 SUSE 公司屡获大奖的 SUSE Linux 企业版 的产品基础。

---- openSUSE wiki

openSUSE 有 接近滚动更新的 Tumbleweed ( 风滚草 ) 分支和偏保守的 Leap 分支.

它的一个特色功能是 YaST。这玩意儿类似 Windows 的控制面板,帮你搞定一大堆系统管理的杂事(比如:硬盘分区、软件升级、用户管理、网络配置、等等)

Ubuntu Desktop

属性 : 跟保守的比偏激进、跟激进的比偏保守,所以不知道该算是激进还是保守的商业发行版

Ubuntu是基于Debian发行版和GNOME桌面环境,与Debian的不同在于它每6个月会发布一个新版本(即每年的四月与十月),每2年发布一个LTS长期支援版本。

普通的桌面版可以获得发布后18个月内的支援,标为LTS(长期支持)的桌面版可以获得更长时间的支援。例如,Ubuntu 8.04 LTS(代号Hardy Heron),其桌面应用系列可以获得为期3年的技术支援,伺服器版可以获得为期5年的技术支援。

而自Ubuntu 12.04 LTS开始,桌面版和伺服器版均可获得为期5年的技术支援。2013年3月有消息指出,Ubuntu计划在4月25日Ubuntu 13.04发布后,将非LTS版本的支援时间自18个月缩短至9个月,并采用滚动发布模式,允许开发者在不升级整个发行版的情况下升级单个核心套件。

---- Wikipedia:Ubuntu


其实 Linux 发行版远不只这几个啦~ 维基百科上有一篇叫做 Linux 发行版 的条目,上面有更丰富的介绍呐~

那么汝现在赶紧去挑一个发行版啦~ 下一次咱会八卦一下 Linux 的软件包管理器呗~

by ホロ at March 24, 2016 04:00 PM

中文社区新闻

要求于2016年4月23日前升级至 pacman-5.0.1

最近 pacman-5.0 更新支持了事务性挂钩(transactional hook)。通过这个新特性,比如说我们可以在每次升级之后统一刷新一次字体缓存,而不是在安装每个字体包之后都刷新。这个特性不但将加快更新速度,并且将减少开发者们和受信用户们打包时的负担。

为了允许打包者们开始利用挂钩,我们要求所有用户于2016年4月23日前更新至 pacman-5.0.1 及以上版本。 pacman-5.0.1 是在2016年2月23日发布的,这表示用户有两个月的时间更新他们的系统。

by farseerfc at March 24, 2016 12:04 PM

March 23, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (2) - 萌新向学习建议

咱到底该如何使用基于 Linux 内核的操作系统咧?

本来想八卦一下 Linux 的历史来着,但是考虑到oo和oo,就决定 放个传送门 ~

为了省点字,接下来咱提到的 "Linux" 就是 "基于 Linux 内核的操作系统" 啦~

首先咱来排解一下几种常见的误区呗~

哇,大家提到的都是命令,Linux 是不是很难学?

的确命令行界面 ( 而不是图形用户界面 ) 是 Linux 的精髓没错,但是汝不要因为这个就望而却步呐~

有一些面向桌面的发行版就通过图形化的设置和管理界面和简单的设置指南赢得了 "用户友好的发行版"的 美誉(?)

什么? 汝在怀疑 Linux 的易用性? (拖出去砍了~)

汝不妨去看看现在流行的 Android 系统,它就是基于 Linux 内核的哟~

那么 Linux 是不是学起来很容易?

容易的话就用不到咱写这些了呗~

为啥很多人有这种想法捏?主要是被"急功近利"的风气影响,变得浮躁了呐~

「像汝这么聪明的人,只要学会审情度势,一般的事情都能做得很好。不过呢,无论谁都有适合和不适合的事情。虽说是咱让汝做的,但看来汝可能不太适合这一行,感觉这不是汝所期望的。」

「汝若真想和那些家伙一较高下的话,早就最大限度地利用上咱了。」

「汝更希望能稳健地,一步一个脚印地前进,咱也认为这样更适合汝。而在咱所指引的前方,则是完全相反的结局。不是吗?」

oo 在 Windows 上能用 Linux 上就不行, Linux 真难用 ......

Linux : 怪我咯? 😂😂😂😂😂😂😂

一般硬件厂商会优先开发市场占有率最高的那个系统的驱动程序,哪个系统?目前来说,就是 Windows 啦。而 Linux 就经常遇到一些无法使用的硬件,很多人还抱怨 Linux 无能,这不是冤枉么~~~

「比起在书上抹墨水,汝会更热衷于在咱脸上抹黑。」

「……你觉得自己说这句话很妙吗?」

「因为汝这种人说谎不眨眼的啊。一定会有的没的乱写一通。真是的,汝究竟打算写什么书啊?」

「你是不是想说我的脸皮跟书一样厚?」

那么到底该如何渐进的学习 Linux 咧?

「汝的脑筋虽然转得快,但经验还是不够。」

「但是反过来说,只要经过岁月的累积就可以变成有智慧的人。」

「你是说几百年后吗?」

「哈哈哈哈哈,汝的脑筋转得真快。」

( 这是咱的一种建议,仅供参考哦,如果汝有更好地建议的话,不妨来告诉咱呗~ )

  • 先从虚拟机开始尝试,等熟练以后再安装在实体机上

    虚拟机,顾名思义,是"虚拟的"啦。即使是格式化了虚拟机的硬盘,都不会影响到汝的实体机呐~(Host OS)

    在汝摸索的阶段,可以充分利用虚拟机的"快照功能"哦~"快照功能"就如同"后悔药"。 万一汝不小心搞坏了系统,直接回退到这个快照,系统就恢复原样啦。

    常见的虚拟机软件(比如 VirtualBox、VMware),在虚拟系统(Guest OS)中仿真出来的虚拟硬件,往往是比较常见的硬件。 因为是比较常见的虚拟硬件,Linux 通常都能直接识别出那些虚拟硬件啦~ 这就避免了折腾硬件驱动的麻烦。

    如果不知道怎样用虚拟机的话 ,`看看编程随想的 "扫盲操作系统虚拟机" 系列呗~ <https://program-think.blogspot.com/2012/10/system-vm-0.html>`_

  • 从图形界面开始,一步一步掌握各种命令呗~

    首先汝试着先用图形界面完成日常化的操作呗~

    可以先从图形界面入手。先通过图形界面,了解 Linux 的各种功能。等到慢慢熟悉了,再逐步学习命令行界面的使用。

  命令行界面是 Linux 的精髓之一。善于使用命令行,汝的效率会成倍提高的呐~。

  所以,总有一天汝是要面对命令行界面的啦~。

  • 先从系统默认的配置开始,再逐渐 DIY 出属于汝自己的配置呗~

    有些"傻瓜化"的发行版,它会内置各种汝需要的软件。

    一旦装好系统之后,(只需使用它的默认设置)就可以完成日常操作了。显然,这类发行版更容易上手呐~。

  但是,如果汝想在 Linux 领域有所深入,想要充分发挥其特长,不应该仅仅停留在"傻瓜化"的层面;

  汝需要逐渐的摸索,不断地折腾,搞定各种"DIY"。在折腾的过程中,汝自然会学到很多东西呐~ ( 折腾是生命的动力......) 。


「应该只是你的脑袋用了太久,变得老旧不堪用吧。」

「呵呵呵呵。汝知道狼为什么要在山里头袭击人类吗?」

「那是因为狼想吃人类的脑袋,好得到人类的智慧。」

「汝还太嫩了,根本不是咱的对手。」


大概就这些? 下次咱再教汝选择一个合适的发行版呐~

by ホロ at March 23, 2016 04:00 PM

March 21, 2016

ヨイツの賢狼ホロ

为啥汝不放弃不自由?

是什么让汝甘愿选择被不自由限制而不是放弃封闭走向自由?

这个算不算引子?

解放一个习惯于被奴役的民族比奴役一个习惯于自由的民族更难

----孟德斯鸠 (启蒙思想家)

#archlinux-cn 里的 farseerfc 说自己要离开 Telegram 了,于是用 fishroom 换掉了兢兢业业若干年 虽然偶尔会黑化 的阿卡林......

原因好像是 Telegram 有要变的封闭的趋势:

Peter Cai - PGP C297B594, [21.03.16 20:53] 我不认为他们会开

Peter Cai - PGP C297B594, [21.03.16 20:53] 我也不希望开源。。

farseerfc 😂 0xC13D4796, [21.03.16 20:53] 從一開始就說要開,然後到現在連協議都封閉了,只有官方授權的客戶端開發者能看到最新協議……

wicast C, [21.03.16 20:53] 开源也没啥卵用感觉…

Peter Cai - PGP C297B594, [21.03.16 20:53] 除非能出现第二个freenode

Peter Cai - PGP C297B594, [21.03.16 20:53] 不然开了等于没用

wicast C, [21.03.16 20:54] 卧槽…连协议都封闭了么…

teleboto, [21.03.16 20:54] [toxsync] (quininer) 其实不如把现有功能做成 xmpp 插件

Peter Cai - PGP C297B594, [21.03.16 20:54] 我看文档和以前一样

wicast C, [21.03.16 20:54] 吃枣药丸

Peter Cai - PGP C297B594, [21.03.16 20:54] 反正本来就看不懂

teleboto, [21.03.16 20:55] [toxsync] (yatseni) 是freenode是悲剧吗

farseerfc 😂 0xC13D4796, [21.03.16 20:55] cutegram 的開發者抱怨了很久了,所以現在二步驗證什麼的都還在從開源出的客戶端代碼慢慢逆向協議

Peter Cai - PGP C297B594, [21.03.16 20:55] https://core.telegram.org/mtproto

teleboto, [21.03.16 20:55] [xmppbot] [Lisa] teleboto: ⇪网页标题: MTProto Mobile Protocol

Peter Cai - PGP C297B594, [21.03.16 20:55] 🌚这个一直是这样

teleboto, [21.03.16 20:55] [toxsync] (quininer) 中心服务爱好者快转 wire 吧

Peter Cai - PGP C297B594, [21.03.16 20:56] wire有什么好转的。。

Peter Cai - PGP C297B594, [21.03.16 20:56] 。。还不如转WhatsApp

teleboto, [21.03.16 20:56] [toxsync] (quininer) wire 很好啊 =-=

wicast C, [21.03.16 20:56] [In reply to farseerfc 😂 0xC13D4796] 有不开源的部分?

teleboto, [21.03.16 20:56] [toxsync] (quininer) wire 是完整的 axolotl 协议实现

teleboto, [21.03.16 20:57] [toxsync] (yatseni) qtox 1.3.0有什么改进?

teleboto, [21.03.16 20:57] [toxsync] (quininer) yatseni: markdown 支持?

farseerfc 😂 0xC13D4796, [21.03.16 20:57] https://core.telegram.org/schema 這邊公開到 layer 23 , cutegram 支持到 layer 25

teleboto, [21.03.16 20:57] [xmppbot] [Lisa] teleboto: ⇪网页标题: Current TL-schema

Peter Cai - PGP C297B594, [21.03.16 20:57] telegram至少还有bot API

wicast C, [21.03.16 20:57] 真是吃枣药丸🌚

farseerfc 😂 0xC13D4796, [21.03.16 20:58] [In reply to wicast C] 這倒沒有的樣子,總之協議現在在代碼裏……

wicast C, [21.03.16 20:58] Tg也就前端的东西做的还行

teleboto, [21.03.16 20:58] [toxsync] (quininer) bot api 这部分是完全闭源的吧?

Peter Cai - PGP C297B594, [21.03.16 20:59] 是的。

Peter Cai - PGP C297B594, [21.03.16 20:59] 但是至少有。。

Peter Cai - PGP C297B594, [21.03.16 20:59] 其他中心化服务哪个有。。

Peter Cai - PGP C297B594, [21.03.16 20:59] wire这玩意连自己艹都没办法

farseerfc 😂 0xC13D4796, [21.03.16 21:00] https://github.com/telegramdesktop/tdesktop/blob/master/Telegram/SourceFiles/mtproto/mtpCoreTypes.h#L371 現在 tdesktop 在 layer 49 了已經……

David Huang, [21.03.16 21:00] [In reply to Peter Cai - PGP C297B594] telegram总有一天要走向封闭的(

teleboto, [21.03.16 21:00] [toxsync] (quininer) 不用说"总有一天",一直是封闭的

Peter Cai - PGP C297B594, [21.03.16 21:01] [Forwarded from teleboto] [toxsync] (quininer) 不用说"总有一天",一直是封闭的

然后咱突然想到了百合姐的某篇文章:

在那个世界里我活得很好。即使是遭受重大的人生挫折时也不曾对那个世界感到疲惫,依旧会写代码,写博客。

可现在,我累了。

其实我有好些想写博客的材料,但是都没有写。我也有好些项目的想法,可是它们还在我的 TODO wiki 里。Arch Linux 中文社区还有许多要做的事情,可我也不想去做了。

我不知道是为什么。也许是孤单吧。一直以来都只有自己。即使 Arch Linux 社区,在做事的人也渐渐少了。而曾经在网上认识的朋友,渐渐地都有了自己的生活。随着 Google Hangout 取代 Google Talk、新浪微博取代 Twitter,还有微信,这些封闭的东西取代了自由的工具,可以放有用或者有意思的机器人的地方却越来越荒芜了。

也许是年纪渐渐大了。青春越来越少,而我却依旧在飘荡。

---- 依云's Blog:我想我失去了最后的领地

连咱也何尝不是如此? 虽然咱会用像 XMPP , Tox 和 GNU/Linux 一类的自由软件,也曾经试图以 Richard Stallman 为目标,然而还是没法做到. Pia!<(=o ‵-′)ノ☆

最后咱还是不得不承认咱没办法完全放弃不自由呐~ 那么到底是为啥咧?

自由对自己的代价太大 _(:з」∠)_

( 也就是获得自由带来的损失比不自由所带来的限制更大? )

举一个咱自己的栗子 (´・ω・`) :

前几天入手一部预装 Windows(Windoge) 10 的平板,想当然的咱想装上 Arch Linux 啦,结果当咱装上以后:

  • 触屏和网卡是废的 ( (╯T∧T)╯ ┻━┻ 装 Arch Linux 时没有网可是致命的 )
  • 分辨率太高以致于默认的字太小😂😂😂 ( GNOME 的 HiDPI 只能整数倍调整差评,KDE plasma 调一调倒是能看了...... )

于是只好留着 Windows 😂😂😂

所谓的自由根本没法实现?

比如 iOS 和 Windows Phone ,汝都没法更换上面的操作系统,也不知道上面的系统都干了些啥......

尽管 Telegram 越来越封闭 , 现在它还有相对开放的 Client / Bot API,而更 "流行" 的 QQ / 微信 / WhatsAPP / Skype /.... 咧?

尽管 Android 手机 / Windows 设备可以刷机,然而流行的硬件却没有一个是彻底开放的,谁能相信后门不会在固件或是硬件上?

(╯°△°)╯ ┻━┻

没法带领身边的朋友逃离不自由?

还是举咱自己的栗子? (╯>▽<)╯ ┻━┻ :

  • 尽管咱卸载了 QQ ,但还是装在了另一台手机上......

    周围的人和学校的辅导员都还在用 QQ , 咱试图向社团的同学安利 Telegram ,然而......

    (╯=﹁"﹁=)╯ ┻━┻ (亏还把自己称作计算机精英协会......干脆全吃掉然后解散好了(雾))

  • 虽然咱自己很少用 Windows 了,然而经常被拉去修 Windows 电脑:

    Baka Windows 总是会越来越慢,而原因基本上都是招来了病毒,木马或是oo全家桶😂😂

    就算咱耐心的一个一个卸载,过几天还是会以同样的理由被拉回去重修......

    以后就干脆直接重装系统了 (╯´︿`)╯ ┻━┻

    /me 再遇到这样的事干脆直接砸了好了

  • 明明有那么多种纯文字的标记语言可以用可咱还是要用 Office (ノ=Д=)ノ┻━┻

    (╯T▽T)╯ ┻━┻ 哪怕是 LibreOffice 也好啊 (然而并没有)

    (╯=﹁"﹁=)╯ ┻━┻ 没 LibreOffice 哪怕是新版的 Microsoft Office 能部分兼容 OpenDocument 也好啊 (然而几乎全都是 03 )

    嘿嘿嘿......像造点大新闻了呐~

    某学校 M$ Office 用户一夜间全部失踪 ( 雾 again~ )

等等等等......


「真是太感谢了。我终于能融入这个新世界了。」

「我们没法像过去那样自由自在了,但是……」

「但是,这个世上还有我们的位置,还有我们的任务。虽然故乡还未曾得见,但不要哭鼻子哦?不能给这个年轻人添麻烦。」

给渴望自由的人的空间越来越少了呐~所谓的自由,大概一直在路上吧......

by ホロ at March 21, 2016 04:00 PM

March 18, 2016

ヨイツの賢狼ホロ

发布 Pelican 博客的几种方式

汝的 Pelican 博客有几篇文章了没?想不想让其他人也看到?

如果汝在一开始使用了 pelican-quickstart 来创建汝的博客的话,后面可能会方便点呗~ ( 因为它帮汝生成了一个 Makefile 呐~ 然而 baka Windows 并不能用 Makefile (ノ=Д=)ノ┻━┻ )

没用 pelican-quickstart ? 可以自己来写一个 Makefile 呗~

样例在这:

(这里用到了 Github Gist 嘛,如果看不到的话, 链接在这 )

对于喜欢自己动手的 菊苣 来说, Makefile 里的命令稍加改造就可以直接执行呐~

在下面的例子中,上面是 Make 规则,下面是实际运行的命令呗~

( /path/to/your/content/ 是汝的内容存放的目录, path/to/your/settings.py 是汝设置文件的目录, 记得用汝实际的位置替换呗~ )

make html

pelican /path/to/your/content/ -s path/to/your/settings.py

首先当然是要生成汝的博客啦~

如果加上 -r 或者 --autoreload 参数, Pelican 就会在源文件更改时自动更新输出哟~

如果汝在一开始使用了 pelican-quickstart ,会生成一个发布时使用的 publishconf.py 文件呐~

(需要时就用它呗)

make html

pelican /path/to/your/content/ [-s path/to/your/settings.py]

接下来先在本机上预览一下~

如果出了错再重新上传一遍岂不是很痛苦 (╯>_<)╯ ┻━┻

如果汝在一开始使用了 pelican-quickstart 会在汝的文件夹下生成一个 developer_server.sh 文件,像这样?

(这里用到了 Github Gist 嘛,如果看不到的话, 链接在这 again~ )

如果是这样的话让它帮忙就好了啦~

# 一共有 start | stop | restart 三个选项,该知道是啥了吧 (´・ω・`)

sh developer_server.sh start

或者切换到输出的目录,然后直接运行 pelican.server

python -m pelican.server

在汝的浏览器上打开 http://localhost:8000 看看效果呗~

如果一切 OK 的话,用 publishconf.py 生成发布时用的文件呗~

如果汝用自己的服务器?

如果汝用自己的服务器的话,修改汝的 Makefile 的这一段:

如果汝在用FTP : ( 不过为啥还在用不安全的 FTP 啊 (╯‵Д′)╯ ┻━┻ )

FTP_HOST=localhost # 这是主机的域名或者 IP 地址

FTP_USER=anonymous # 这是用户名

FTP_TARGET_DIR=/ # 这是上传到的文件夹

然后安装 lftp ( Makefile 里用的是这个 )

如果汝在用 SFTP (SCP/SSH) :

SSH_HOST=localhost # 这是主机的域名或者 IP 地址

SSH_PORT=22 # 如果主机的 SSH 端口不是默认的记得改~

SSH_USER=root # 这是用户名

SSH_TARGET_DIR=/var/www # 这是上传到的文件夹

然后安装 scp ( Makefile 里用的是这个 )

接下来只要直接 Make 相应的目标就可以啦~

make ssh_upload

pelican /path/to/your/content/ -s path/to/your/publishconf.py

scp -P $(SSH_PORT) -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)


make ftp_upload

pelican /path/to/your/content/ -s path/to/your/publishconf.py

lftp ftp://$(FTP_USER)@$(FTP_HOST) -e "mirror -R $(OUTPUTDIR) $(FTP_TARGET_DIR) ; quit"

如果汝打算用 Github Pages ?

farseerfc 写过一篇利用 Travis 生成 Github Pages 的教程:

用 Travis-CI 生成 Github Pages 博客

要上传到像 Amazon S3 ,Dropbox 一类的地方 , 还是看Pelican官方的文档吧

by ホロ at March 18, 2016 04:00 PM

March 17, 2016

ヨイツの賢狼ホロ

浅说基于 Linux 内核的操作系统 (0) - 写在前面

挖了个新坑,就是这样 _(:з」∠)_

挖这个坑的动机

咱这学期以"二周目成员"的形式加入了学院的计算机社团,然后就是"三周目成员"的招募啦~,接着就要开始学习C语言啦,然而配置环境就是个复杂的工程呗.

"要啥Windows啦,换Linux多好."

----咱是这么想的.

然而当他们告诉咱没用过Linux时,😂😂😂(咱想不到该说什么了)

接着咱去看了几本关于Linux的书,发现国内出版的书正交性不够(只针对特定的发行版),国外的书的话咱的同学看着会很痛苦😂

于是咱就有了写这系列文章的动机,然而却一直拖着 (´・ω・`) ,直到社长说要让咱做一次基于 Linux 内核的操作系统的讲座 (╯•̀﹏•́)╯ ┻━┻

「基本上,得记住的文字种类太多了。还有呐,莫名其妙的组合也太多了。虽然人类会说只要照着说话规则写字就好,但是这显然是骗人的呗。」

---- 咱的水平明明还没那么高啊~

然后在 #archlinux-cn 又受到了调侃 (╯@_@)╯ ┻━┻

ヨイツの賢狼ホロ, [19.03.16 05:20] /me 社长叫咱准备一期 Linux 相关的讲座😂😂

archcnbot, [19.03.16 05:21] [KaseiWang] 狼主席什么时候上位啊

ヨイツの賢狼ホロ, [19.03.16 05:22] [In reply to archcnbot] 咱可不是主席😂😂

archcnbot, [19.03.16 05:22] [Shirasaka-Hazumi] 要上台

cuihao, [19.03.16 05:22] 狼主席!

archcnbot, [19.03.16 05:22] (quininer) 狼主席!

StarDuster, [19.03.16 05:22] 狼主席

archcnbot, [19.03.16 05:22] [Shirasaka-Hazumi] Chair Lang

archcnbot, [19.03.16 05:23] [felixonmars] 狼主席什么时候上位啊

archcnbot, [19.03.16 05:23] [felixonmars] 我突然发现

ヨイツの賢狼ホロ, [19.03.16 05:23] 😂😂😂

archcnbot, [19.03.16 05:23] (quininer) 突然发现

archcnbot, [19.03.16 05:23] [felixonmars] 有个很厉害的搜索引擎,叫狼内存

archcnbot, [19.03.16 05:24] (quininer) 'google 狼内存

archcnbot, [19.03.16 05:24] [varia] quininer: Wolfram 中文名| Mathematica小组| 果壳网科技有意思 [ http://www.guokr.com/post/653834/ ]

archcnbot, [19.03.16 05:24] [Lisa] varia: ⇪网页标题: Wolfram 中文名 | Mathematica小组 | 果壳网 科技有意思

StarDuster, [19.03.16 05:24] 噗

咱参考了哪些内容?

咱参考了这些内容,先道个谢~


既然是 "写在前面" 嘛,就不能说的太多 其实是还没想好怎么写~ , 那么下次再见了😂😂

by ホロ at March 17, 2016 04:00 PM

这是所谓的时间管理浅说 _(:з」∠)_

时间管理到底是啥咱也不太知道呐~ 不过还是谢邀

灵感来自前几天 #archlinux-cn 的对话:

ヨイツの賢狼ホロ, [14.03.16 22:23] /me 下一篇文章的方向是啥咧😂

farseerfc 😂 0xC13D4796, [14.03.16 22:23] 想看看萌狼聊時間/計劃管理

pandada8, [14.03.16 22:24] 时间管理 aka 怎样关掉im

ヨイツの賢狼ホロ, [14.03.16 22:24] [In reply to farseerfc 😂 0xC13D4796] ……

ヨイツの賢狼ホロ, [14.03.16 22:24] 现在纯粹是因为咱比较闲而已啦😂😂

Frantic1048, [14.03.16 22:26] [In reply to farseerfc 😂 0xC13D4796] +1

Kasei Wang, [14.03.16 22:26] 想知道萌狼早上怎么起来的

ヨイツの賢狼ホロ, [14.03.16 22:27] [In reply to Kasei Wang] 直觉?😂

Frantic1048, [14.03.16 22:27] 论如何能够保持大一的作息水平 ~(>_<~)

Kasei Wang, [14.03.16 22:29] [In reply to ヨイツの賢狼ホロ] 讲一下怎么做到早起吧(今天起来十点半多了

Frantic1048, [14.03.16 22:29] [In reply to Kasei Wang] 9 点起的 +1

ヨイツの賢狼ホロ, [14.03.16 22:29] 怎么都那么晚😂😂

Frantic1048, [14.03.16 22:30] [In reply to pandada8] 不管怎么放都能连出自己都无法相信的纯熟的关闹钟手法 (´_`)

pandada8, [14.03.16 22:30] 我觉得你总不至于下床后再上床睡觉

farseerfc 😂 0xC13D4796, [14.03.16 22:30] [In reply to Frantic1048] 然後5分鐘內忘記並睡死

---- Telegram 默认复制出来的格式就这样 😂😂😂

其实咱对时间管理没有啥研究啦,这篇文章估计也只是简单地说说咱的 经验(瞎掰) 而已 😂😂

时间管理到底是啥玩意?

时间管理(Time Management)就是用技巧、技术和工具帮助人们完成工作,实现目标。 时间管理并不是要把所有事情做完,而是更有效的运用时间。 时间管理的目的除了要决定你该做些什么事情之外,另一个很重要的目的也是决定什么事情不应该做; 时间管理不是完全的掌控,而是降低变动性。时间管理最重要的功能是透过事先的规划,做为一种提醒与指引。

---- Wikipedia:时间管理

如此长的定义看的咱都要睡着了诶😴,如果咱没理解错的话,时间管理就是尽可能的提高时间利用率,在有限的时间里做最有效的事呗~

「那个时候的咱呢,的确是不谙世事。相信世间看不惯的事情全都有解决的方法。 讨厌被依赖崇敬的话就去旅行,没有朋友去交就好了。 而且,从心底里相信温水般的快乐时间会永远持续下去。 不过也经常因此哭鼻子就是。那也许很合汝的胃口呐。 呵呵……不过呢,越是回想起苦涩的回忆,脸上就笑得越开心。」

---- 时间管理的重要性(雾)

从时间管理下还衍生出 项目管理Attention management (注意力管理?) (´・ω・`)

坊间流传的几种时间管理分析方法

关于坊间流传的几种时间管理分析方法咧, 英文维基百科 上提到了几种

(中文的坑好像还没填 (ノ=Д=)ノ┻━┻)

就这样?

Q1:Kasei Wang:想知道萌狼早上怎么起来的

~ Frantic1048:论如何能够保持大一的作息水平 ~(>_<~)

这个...... 咱不知道该怎么说好了 (╯°Д°)╯ ┻━┻

如果咱要硬解释一下的话,可能就是老套的 "早点睡觉" 了~(>_<~)

晚上早点睡 ~(>_<~) ,就是这样 😂😂

「听说,上天是把我们的身体塑造成一天只需要睡一次觉。」

「咱是狼呐。」

「又没有人起床,也只能睡觉呗。不睡觉只会觉得冷,而且还会饿肚子。」

「嗯,毕竟现在这季节比较冷清。不过,还真是怪异。」"

---- 这个时候说这个是不是不太合适 😂😂

由此可以得出这样的结论 (雾):

  • 不要睡回笼觉 (╯ ̄Д ̄)╯ ┻━┻

    但是如果汝觉得下午容易犯困的话,中午小憩一刻也无妨 (只是不要睡过头...... )

  • 起床整理完以后记得吃早餐哟~ (´・ω・`)

    记得食用富含蛋白质的食物呐~

  • 如果汝有能力的话,可以拉拢和汝在一起的人也早起咯~ 不从的话就吃掉好了

Q2:为啥说咱很高产?

真相是咱不像 lilydywg , acgtyrentfarseerfc 那样写的出相对比较有深度的文章啦~ ( 倒是萌新向教程比较多 😂😂 )

「咱可是贤狼啊。起码还是知道这世界上有很多东西是我所不了解的。」

如果真要说出啥原因的话,咱觉得应该有这几种:

  • 现在纯粹是因为咱没有工作因此比较闲而已啦~

  • 平常想法比较多?

    比如在写这篇文章之前咱还计划过其他的主题呐~ ( (╯•̀_>•́)╯ ┻━┻ 虽然到现在还没付诸实施就是了 )

  • 没被太多强加的事情干预?

    「要如何看待事情是自己控制的。既然咱想要回到北方,不管怎样都得离开那里。既然没有人要拉住咱,咱用后脚踢砂子离开就是了,这样也比较能够死心。不过,咱不可能就这么安安静静离开。」

    就像这样? ( 然而想不做被强加的事情似乎很难的样子呢~ )

  • 写博客算是一种真正的兴趣?

    如果你够幸运的话,还可以让“自己的兴趣”成为“自己的职业”——这是很幸福的事情 :)

    如此一来,就把“工作”和“娱乐”合为一体。你将不再有“工作时间”和“业余时间”的差异——不论是“工作时间”还是“业余时间”,对你而言都是“娱乐时间”。很爽的!

    当这两者统一之后,还有更多其它的好处。比如说,你在自己的工作中,就可以比别人走得更远,因此也就更有可能成为该领域的【优秀】者。

    ---- 编程随想的博客:什么是【真正的】兴趣爱好?以及它有啥好处?

    至少现在来说,写博客算是咱的一个兴趣吧 ~(>_<~)

  • 不常刷微博和 SNS ?

    自从看了 为啥俺不常用微博——兼谈时间管理心得“传统博客”过时了吗?——兼谈各种媒介形态的优缺点 再加上咱用 IFTTT 帮咱发文章更新,咱已经不知道有多久没上 Twitter 和 Google+ 了 (。>ω<)。

大概就这些 (っ╹ ◡ ╹ )っ?

推荐一些时间管理相关的资源?

解释这些,当然要找专业的来啦 o(* ̄3 ̄)o

  • 知乎上的 "时间管理" 话题 ,干货丰富,注意前方争论出没 😂😂
  • 褪墨 ,翻译和分享时间管理和个人提升等等主题上的内容和经验的网站,看起来比较专精 (´_`)

by ホロ at March 17, 2016 04:00 PM

March 14, 2016

Issac Ge (Tech)

unknown unknown

我小时候玩仙剑,大概是在百度知道之类的地方,看到有人「兴奋」地分享:你知道吗?只要在游戏里面按下 Alt+F4, 就会有好事发生噢!

当时我连「我不知道我被他骗了,实际上是会强制关掉游戏」的事实都不知道,自然被坑了,后来我知道了有个术语专门描述这现象:”unknown unknown”. 无独有偶,V2EX 曾经发生过类似但更为惨烈的悲剧,即某楼主请教如何在 OS X 清理垃圾,一楼唆使「执行 rm -rf /」,从而楼主二十四小时内再也没出现过,可以说是因为楼主不知道「他不知道 rm -rf / 的实际效果」。

从此以后,我便很照顾 unknown unknown 困境的人们,只需要喂给他们打破 unknown unknown 困境的一点关键词,聪明人就会自发打开通往全新世界的一扇大门。比如有人在 docs 大海捞针地找某关键词,我就只说一句「按下 Ctrl-F 以查找」,他肯定会很感激无比。

最近,StarBrilliant 在 Python 众里批评了我,来龙去脉如下:

Isaac Ge: 我以为 str() 会调用实参的 str 成员,但官方文档没这么说,莫非 Python 标准并不规定这实现办法?
StarBrilliant: 说了的。Python的 slot 大法
Isaac Ge: 官方文档对 print() 的说明也挺语焉不详:
「All non-keyword arguments are converted to strings like str() does and written to the stream」
我不知道它到底会不会调用实参的 str, 或是自动用 str() 来转换它怎么的。
StarBrilliant: 你已经说了一堆“语焉不详”了
实际上文档写得清清楚楚,只是你每次都找错地方

接着他又如此评价我拼接字符串的代码:

path = expanduser('~') + '/Logs/' + __package__ + '/'
log_pathname = path + name + '.' + time.strftime(
            '%m-%d-%H:%M') + '.log'
fhdr = logging.FileHandler(log_pathname, 'a')

StarBrilliant: 你这个字符串拼接,我给0分。
Python 那么多种拼接字符串的方法,你非要用加号

我习惯在 devdocs.io 查编程语言的文档,但事后我发现它原来只包含 Library Reference, 我所要找的答案其实是在 Language Reference, 也就是说我一开始就不知道「我不知道自己找错了地方」;同理,我也不知道「我不知道除了 + 之外的其他字符串拼接法」。

虽然这事件里 StarBrilliant 语气冲,但我不怪他,当然他如果能直截了当地抛出 “Language Reference”, “slot” 和 “String Concatenation join” 等关键词,少评价我的 unknown unknown 错误,就再好不过。事实上,讨论群正是大家互相扶持走出 unknown unknown 困境的好地方,当然,前提是群成员都会自觉地「按图索骥」,即直接用先进的搜索引擎来搜索关键词。实际上我之所以政审入群要求,是为了过滤只会伸手不会搜索的平庸之辈。

最后再升华为编程规范吧:友善对待处于 unknown unknown 的编程之徒,并积极地按别人的图来索骥。

Written with StackEdit.

我小时候玩仙剑,大概是在百度知道之类的地方,看到有人「兴奋」地分享:你知道吗?只要在游戏里面按下 Alt+F4, 就会有好事发生噢!

当时我连「我不知道我被他骗了,实际上是会强制关掉游戏」的事实都不知道,自然被坑了,后来我知道了有个术语专门描述这现象:”unk

March 14, 2016 09:22 AM

March 13, 2016

ヨイツの賢狼ホロ

简单总结一下咱自己用过的一些 CMS

仔细数数咱也用过不少 CMS(内容管理系统) 了呐~,或许咱应该小小的总结一下?

PS:本文会带有大量个人的主观意见😂😂

WordPress:大众和普通的CMS

WordPress 的大名想必各位都知道吧。

WordPress是一个注重美学、易用性和网络标准的个人信息发布平台。WordPress虽为免费的开源软件,但其价值无法用金钱来衡量。

WordPress的图形设计在性能上易于操作、易于浏览;在外观上优雅大方、风格清新、色彩诱人。

使用WordPress可以搭建功能强大的网络信息发布平台,但更多的是应用于个性化的博客。 针对博客的应用,WordPress能让您省却对后台技术的担心,集中精力做好网站的内容。

---- WordPress 中文首页

WordPress 也是咱第一个用的内容管理系统啦,作为希望用户专注于内容的 CMS ,WordPress 有几点做的非常棒:

  • 内置可视化编辑器,无需掌握大量标记语法就可以开始写文章。
  • 每次大版本更新都会更新一套主题 (Twenty 系列),都非常赞~
  • 五分钟安装向导名副其实 (真的只要五分钟一个 WordPress 网站就可以投入使用了2333)

当然缺点也是有的 :

  • 作为用 世界最好的 PHP 语言编写的 Web应用,需要一个资瓷 PHP 的 Web 服务器来运行😂😂
  • 树大招风,WordPress 也容易成为垃圾评论和骇客的目标 ( 前几星期的 Linux Mint 事件 就是骇客通过 WordPress入侵了他们的服务器 😂😂😂 )
  • 用默认主题显得同质化,自定义主题又太复杂......

所以咱最后还是换掉了 WordPress 😂😂😂😂

MediaWiki:潜力无限的Wiki平台

没听过 MediaWiki 汝总该听说过维基百科吧,维基百科就是运行在维基媒体基金会开发的 MediaWiki 上呐~

MediaWiki是一个最初为维基百科量身打造的自由wiki套件,用PHP语言写成。

现在,非营利的维基媒体基金会下辖的所有wiki项目、互联网上的众多其他wiki网站也基于此套软件搭建。

---- MediaWiki.org

简单来说 MediaWiki 是一套 Wiki 系统,不过通过扩展也可以实现各种其他功能 ( 例如 WikiData ) .

咱要说 MediaWiki 又有啥优点咧?

  • 因为是 Wiki 系统嘛,所以方便 协作(一同填坑) 😂😂
  • 文档丰富,基本上覆盖了大部分内容 ( 给用户的帮助在重写ing~ )
  • 扩展丰富,可以实现更多功能

当然还是老样子,缺点也是有的:

  • 和 WordPress 一样,作为用 世界最好的 PHP 语言编写的 Web应用,需要一个资瓷 PHP 的 Web 服务器来运行😂😂
  • (可能是唯一?) 不太适合博客型网站 (因为不方便生成RSS)
  • 部件繁杂,不知道哪里出问题就吐核了 (不过会有堆栈跟踪,偶尔会派上些用场😂😂)
  • 没有权限汪们想要的精确到条目的权限控制😂😂
  • MediaWiki 标记太复杂啦 (╯・_・)╯ ┻━┻ ( 或者可以 安装可视化编辑器 ,可还是好复杂 (╯X﹏X)╯ ┻━┻ )

不过咱还在坚持用它当咱自己的资料库呗~

Ghost:轻博客的开端?

Ghost是用JavaScript编写的博客平台,基于MIT许可证开放源代码。Ghost的设计主旨是简化个人网站发布以及网上出版的过程。

Ghost是一款个人博客系统,它是使用Node.js语言和MySQL数据库开发的,同时支持MySQL、MariaDB、SQLite和PostgreSQL。用户可以在支持Node.js的服务器上使用自己的博客。

Wikipedia 上的 "Ghost (博客平台)" 条目

咱曾经 安装过 Ghost ,安装过程看着挺吓人,但是按照官方的文档来也可以一次成功~

咱的第一印象就是:比 WordPress 轻多了,真的.

Ghost 最大的优点是原生支持 Markdown 和 HTML ,汝就可以愉快的书写咯~~

不过 Ghost 是 Node.js 应用,安装 Node.js 首先就是个大公程。

另外作为开发中的软件,还有很大的空间……

Pelican:笔记本?

第一次接触到 Pelican 是 farseerfc 的博客+安利 (雾), 然后正为 MediaWiki 的 RSS 扩展苦手的咱干脆就换成了 Pelican.

farseerfc 说 Pelican 有这些优点:

  • 純 Python 實現。 這意味着我可以換用任何 Python 解釋器而不必擔心兼容性問題。比如我就換成了 PyPy。

    因为是纯 Python 实现,可以 通过Travis-CI 自动生成 html, 也可以通过 msys2 在 Windows 上运行.没有方便的 Linux 环境再也不是偷懒的理由了呐~

  • 多語言支持。因爲 Pelican 的作者似乎是個法國人。不過這個似乎大部分人不需要…… 我是想儘量把一篇博客寫成三種語言作爲鍛鍊吧。

    fc 的博客就有三个语言啦~(虽然咱现在没用到)

  • ReST 。這樣我就可以用 Leo 的 @auto-rst 直接寫 ReST了。簡單方便快捷有效。

    ReST 的学习曲线有些陡峭,但掌握之后就是一马平川了哟☺🙂😄

咱说 Pelican 还有这些优点:

  • 生成的是静态网站,找个 Web 服务器就可以放 (或者放在 Github Pages 上,极客风格 (?) 十足 )😂😂😂
  • 使用的是 jinja 模板引擎 (咱照着默认的 simple 主题做了现在这套主题, 虽然只是能看而已 😂😂😂)

不过 Pelican 也不是完美的:

  • 静态网站的评论是个难题啊 ( 只能靠第三方服务,例如 Disqus )
  • 没有类似 WordPress , MediaWiki 和 Ghost 的文章编辑界面 ( 虽然 retext 很好用~ )
  • Linux 风格的 Makefile 让迁移有些小小的难度 ( 不然为啥会在Windows 上用msys2...... )

不过现在咱还要接着用 Pelican 呐~😂😂

by ホロ at March 13, 2016 04:00 PM

Justin Wong

定制GH60机械键盘

引: 年初时开源哥搞了个喜闻乐见的团购定制vim键盘的活动, 我饶有兴致地参团了,然而这事儿最后被厂家(TEX)放了鸽子,也就不了了之了。

不过我对键盘的购买欲倒是被激活了,原有的FC660M是个好键盘,但是不能定制键位,切稍微比我的挎包长了那么一点点, 加之最近股市大跌,愈发觉得钱不花真不值钱(谁来打醒我),便总是想买个新的。

挑了半天,poker2 和即将上市的 poker3 还是不够灵活,不能为所欲为…… 所以目光转向了硬件开源的 GH60。

在哪儿买的

首先调研了一番,在这里看见博主推荐一个 常州的卖家,于是也就找这个卖家做了。掌柜很nice,我对键盘并不是很懂, 也是第一次买定制键盘,掌柜给我科普了挺多。

最后选了无钢板茶轴+塑料外壳+HHKB配列(左shift和backspace拆成两个按键),卖家帮我焊接组装,3天搞定发货了。

上王道。

先说下手感吧,感觉远不如原先的FC660M手感好,轴感觉有些「松」,不知是不是没有钢板的原因,虽然同为原厂茶轴, 这块键盘的轴感觉很硬,按键不干脆,有一种「没上润滑油」的摩擦感。另外就是空格键,卫星轴做过工很一般,左边 稍微用点力敲,右边就会脱出,需要再按回去。

卫星轴的问题,想了个土办法解决了,在空格键右边卫星轴孔处塞了点纸巾 -_-||| 。轴太硬的问题,淘宝买了WD40 润滑剂,打算加点试试。

所以如果想follow自己也去买的话,注意一定要买带钢板的,当然有能力的同学就自己组装了。

刷固件

说完不开心的,来说点开心的。GH60最爽的就是完全可编程。中国买到的GH60基本都是satan的版本,与GeekHack的有所不同, 需要用tmk_keyboard_custom 这个项目编译出来的固件, 并且在config.h中加入一行

1
#define GH60_REV_CHN 1

你可以选择自己定义keymap或者已有的keymap,不过 tmk_keyboard_custom 的 gh60 中 keymap_common.h 有些问题, 建议手动跟 tmk_keyboard 中的代码 merge 一下。另外,即使不少自带的keymap 也会报 keys_count 找不到的错,需要在对应的 keymap_xxx.c 中加入以下代码

1
2
3
4
5
6
7
8
9
#ifdef KEYMAP_IN_EEPROM_ENABLE
uint16_t keys_count(void) {
return sizeof(keymaps) / sizeof(keymaps[0]) * MATRIX_ROWS * MATRIX_COLS;
}

uint16_t fn_actions_count(void) {
return sizeof(fn_actions) / sizeof(fn_actions[0]);
}
#endif

也可以直接使用我 fork 的 tmk_keyboard_custom,就不用改那么多代码了。

1
git clone --recursive https://github.com/bigeagle/tmk_keyboard_custom.git

计算机上要装 avr-gccdfu-programmer,Arch 的话源和 AUR 里就有。进入 keyboard/gh60 目录可以看到一群 keymap_xxx.c, 首先把固件编译出来:

1
make KEYMAP=xxx

刷固件时需要按下键盘背面的按钮进入dfu模式。

1
sudo sleep 5; sudo make KEYMAP=xxx dfu # 先把 sudo 密码敲了,在之后的 5 秒期间,按下键盘背面的按钮进入 dfu 模式

可以看到内部其实就是一个Atmel的单片机。

另外比较坑的一点就是,刷完之后一定要清空EEPROM,否则keymap不生效。清空的方法是,刷完dfu之后, 拔USB,按住space+backspace,插USB,等三秒,松开。注意这里的 space 和 backspace 都是键位刷新之前对应的键位。 而某次和 @jeasinema 折腾的时候,把 space 键给弄没了,于是无法刷新键位,解决办法是,把 tmk_core/common/bootmagic.h 中的 BOOTMAGIC_KEY_SALT 定义到别的按键上去,再用 X+backspace 刷新键位……

更高级的用法可以参见项目文档

我的Keymap

这里发一下我的keymap,除了Fn0之外,把数字键3也变成了一个Fn键,也就是正常按时候是3,按住不放就是一个Fn,于是 3+hjkl = 左下上右(vim用户都懂的)。

代码在这里,实现了 tricky_esc 功能(就是shift+ESC=~)。

引: 年初时开源哥搞了个喜闻乐见的团购定制vim键盘的活动, 我饶有兴致地参团了,然而这事儿最后被厂家(TEX)放了鸽子,也就不了了之了。

不过我对键盘的购买欲倒是被激活了,原有的FC660M是个好键盘,但是不能定制键位,切稍微比我的挎包长了那么一点点, 加之最近股市大跌,愈发觉得钱不花真不值钱(谁来打醒我),便总是想买个新的。

挑了半天,poker2 和即将上市的 poker3 还是不够灵活,不能为所欲为…… 所以目光转向了硬件开源的 GH60。

March 13, 2016 01:17 PM

YubiKey 4 简介与配置

2012 年我买了自己的第一块 YubiKey, 当时功能还很少,后来康哥在参加 BlackHat 会议 时,参展的 yubico 公司直接送 Yubikey NEO,于是我免费得到 一个。

Yubikey NEO 比早前的 Yubikey 增加了 OpenPGP Smartcard 和 U2F 支持,还可以通过 NFC 获得 Yubico One-Time-Password。唯一遗憾的一点是它的 OpenPGP Smartcard 支持到 2048 位 RSA,而我本人的 GPG 密钥都是 4096 位的,所以为了 使用它我只好增加了一个 2048 位的签名子密钥。

15 年 11 月 Yubico 又推出了 YubiKey 4,增加了 4096 位 RSA 加密支持(貌似只有加密,没有签名), 加上一些其他原因(后文),时间又正好赶上妹子回国,于是让妹子在 Amazon 买了帮我带了回来。

首先说一下功能,YubiKey 4 可以同时工作在三种模式:

  • 传统键盘设备模式: Yubico OTP, Challenge-Response, 静态密码, HOTP 等, 这个模式又有两个slot,对应于短按和长按操作,生成两种密码
  • Smartcard 模式: OpenPGP card 和 PIV card,可以用来安全地保存 RSA 私钥
  • U2F 模式: 一种两步认证协议,Google, Dropbox, Github 等网站都支持

@BlahGeek 之前入手 YubiKey 4 时写得 blog 描述得更详细一些,可以参考。

各功能配置

首先安装相关工具,Arch 用户直接

sudo pacman -S yubikey-personalization yubikey-personalization-gui

然后打开所有功能模式

ykpersonalize -m86 # 同时打开 HID+Smartcard+U2F 

传统键盘设备模式

这部分比较简单,使用 yubikey-personalization-gui 即可进行图形化配置,前文 也讲过 YubiKey 和 PAM 结合做认证。

由于 Yubico OTP 需要认证服务器(默认是 yubico cloud)做认证,所以如果你修改了 Yubico OTP 配置的话,还需要把密钥等信息上传到 Yubico Cloud, 这里 有一份图文并茂的官方文档。

OpenPGP Card

如果你使用 GPG 来做加密和签名,那么 OpenPGP Card 可以进一步加强安全性和便利性。

首先你需要设置一下 YubiKey。

gpg --card-edit  # 打开设置

首先敲 admin 命令打开管理模式,可以使用 help 命令查看帮助,然后用 passwd 命令设置 PIN, Admin PIN 和 Reset Code, 可以是字母和数字,PIN 的默认值是 123456,Admin PIN 的默认值是 12345678。请 牢牢记住 这三个密码。

  • PIN 码是平时最常用的密码,如果输错三次就会被锁定,需要使用 Reset Code 来解锁,Reset Code 输错三次,只能物理重置
  • Admin PIN 是管理卡信息(如添加密钥、修改密码)使用的密码,不能短于 8 位,输错三次则管理功能被锁定,只能物理重置记住,千万不要在需要输入 Admin PIN 的时候输入短于 8 位的密码,这样会直接锁定 (我的 YubiKey NEO 就是这么悲剧的)。

你可以继续设置一些其他信息,比如持卡人姓名、公钥的URL等等,也可以下次再弄。

一个 GPG 密钥包含多个 RSA 密钥对,一对主密钥,若干对不同用途的子密钥,一对密钥包括一个公钥和一个私钥。 一般 gpg --gen-key 得到的,就包括一对主密钥,可以用于签名;一对子密钥用于加密。

不推荐把主密钥放进 YubiKey 里,因为主密钥还有一个重要功能就是维持社交关系,时间流逝,子密钥可能经常变化, 而别人只需要记住你的主密钥ID就可以随时更新。如果把主密钥放进 YubiKey 里,万一丢了,那么你就无法证明你是你了。

假设你已经生成好了一个 GPG 密钥组,用

gpg --edit-key i@example.com

编辑密钥,例如我的密钥:

gpg --edit-key i@bigeagle.me
gpg (GnuPG) 2.1.11; Copyright (C) 2016 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

pub  rsa4096/865BAC3A
     created: 2014-12-28  expires: 2020-10-17  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/167D42E5
     created: 2014-12-28  expires: 2016-08-16  usage: E   
     card-no: 0006 04239808
ssb  rsa2048/1C27920A
     created: 2016-01-25  expires: 2017-01-24  usage: S   
     card-no: 0006 04239808
[ultimate] (1). Justin Wong <i@bigeagle.me>
[ultimate] (2)  Justin Wong <bigeagle@xdlinux.info>
[ultimate] (3)  Justin Wong <justin.w.xd@gmail.com>
[ultimate] (4)  Yuzhi Wang (Tsinghua) <yz-wang12@mails.tsinghua.edu.cn>

gpg> 

其中 pub 开头的是主密钥,865BAC3A 就是我的主密钥 ID,功能有签名(S, sign)和证书(C, certificate); ssb 开头的是子密钥,我有两个: 167D42E5 是我的加密(E)子密钥,密钥长度 4096bit,算法是 RSA;1C27920A 是签名子密钥,长度 2048bit,算法 RSA。绝大多数情况下不需要记住这些密钥 ID。

例如我们现在想把加密和签名子密钥放进 YubiKey 中,那么首先生成一个签名子密钥,用 addkey 命令,跟着向导走几步即可。 接下来把子密钥导入 YubiKey,使用 key <数字> 选择密钥对,0是主密钥对,1以上是子密钥,选中后 ssb 变会多一个 * 号, 可以多次输入key X命令同时选中多个密钥。然后用 keytocard 命令,此时会提示输入 Admin PIN,正确输入,导入完成。注意,私钥 一旦进入YubiKey就无法取出,如果你需要备份请提前做,如果你可以取出请找 Yubico 要奖赏。

这样以后就必须在 YubiKey 插入的时候才能完成 GPG 操作,使用时输入 PIN 码解锁即可。 另一个好处是可以方便的在别人的计算机上完成 GPG 操作,不仅免去了导入导出密钥的麻烦,更重要的更安全。在插入卡 的时候,如果你设置了公钥组的URL,使用 fetch 命令即可导入自己的公钥,配合卡上的私钥即可。

还需要注意的是,如果有 GPG Agent 运行,而 YubiKey 被拔出,那么之后的操作会提示找不到卡(即使重新插入), 运行一下 gpgconf --reload scdaemon 即可。我配合 @xiaq 的 udevedu, 每次插入就 reload 一下,脚本在 gist 里了。

另外,如果使用 YubiKey NEO 的话,则可以配合 OpenKeyChains 通过 NFC 在 Android 手机上进行 GPG 操作。

U2F 两次认证

现在吼多网站都提供两次认证加强安全性,比如 Google, Dropbox 。 常见的两次认证是使用 Google Authenticator, Duo Mobile 等工具产生 TOTP (Time-based One-Time Password), 每次登陆的时候都要开手机运行App,总还是麻烦了些,而 U2F 则可以通过插入 YubiKey 并轻触按钮完成认证。

目前只有 Google Chrome 浏览器完全实现了 U2F 支持,Firefox 需要安装插件 但还不太完美。我试了一下,

  • GitHub 注册设备操作 Firefox 没响应,用 Chrome 注册设备后,Firefox 可正常认证。
  • Google 只允许 Chrome
  • Dropbox 只允许 Chrome

另外有pam-u2f 可以用于 Linux 的各项认证操作,替代传统的 Challenge-Response,用法也很简单。

Arch 用户直接安装 AUR 里的 pam_u2f,首先注册设备

pamu2fcfg -u<username>

这是 YubiKey 上的灯会闪烁,轻按一下,终端里就会打出一行字,格式为

<username>:<KeyHandle1>,<UserKey1>

把这一段内容放在 ~/.config/Yubico/u2f_keys

编辑需要的 PAM 服务(例如sudo),在合适的位置加一行

auth sufficient pam_u2f.so

这样需要认证的时候,YubiKey 灯会闪,轻按一下即可完成认证。

最后

还有好多没折腾的功能,比如 PIV Smartcard,后续折腾出来继续更新 #flag。

2012 年我买了自己的第一块 YubiKey, 当时功能还很少,后来康哥在参加 BlackHat 会议 时,参展的 yubico 公司直接送 Yubikey NEO,于是我免费得到 一个。

Yubikey NEO 比早前的 Yubikey 增加了 OpenPGP Smartcard 和 U2F 支持,还可以通过 NFC 获得 Yubico One-Time-Password。唯一遗憾的一点是它的 OpenPGP Smartcard 支持到 2048 位 RSA,而我本人的 GPG 密钥都是 4096 位的,所以为了 使用它我只好增加了一个 2048 位的签名子密钥。

15 年 11 月 Yubico 又推出了 YubiKey 4,增加了 4096 位 RSA 加密支持(貌似只有加密,没有签名), 加上一些其他原因(后文),时间又正好赶上妹子回国,于是让妹子在 Amazon 买了帮我带了回来。

March 13, 2016 12:36 PM

March 11, 2016

Issac Ge (Tech)

Python 语法、进程和文件之间的编码关系

暴君按:您至少明白 Unicode 字符集和编码之间的关系,熟悉 Python 语法,以及操作系统的「进程」和「文件」概念。本文旨在理清并总结它们错综复杂的关系。

每次想到 Python 2, Python 3, bytes, str, unicode, GBK, UTF-8, 文件和进程之间的编码关系就头大,而且我讨厌 Python 2, 所以到目前为止只会习惯给 Python 2 源代码加上 # -*- coding: utf-8 -*-. 一直没敢深究其编码机制。

不过今天在阅读 Effetive Python 第三条,并在 Arch Linux 中文社区讨论一番,终于搞清了来龙去脉。

Linux 下靠 Locale 机制设置环境的编码,我直接在御用 ~/.config/locale.conf 指定 LANG=zh_CN.UTF-8. 于是御用编辑器 Vim, Gedit, 御用虚拟终端 Termite 和御用输入法 Fcitx-rime 应该沿袭了 UTF-8 编码。您可以自行检查下这些应用程序的设置。总之我用 Vim 或 Gedit 打开新文件后,用 Fcitx-rime 输入字符,又在虚拟终端 cat 文件时,它们始终能正确显示我所理想的字符,毕竟都沿用同一个编码,没什么好疑问的。

事实上 Python 3 也一样,默认用 UTF-8 编码解析源代码,且它有两种字符串对象:str 和 bytes. 前者用来储存 Unicode 字符集所能表达的字符,包括您在文本编辑器输入的 UTF-8 字符,但其值和编码无关,您无法直接获取它具体的二进制值,它在进程内部到底怎么编码对象的,也和您无关;后者则储存单字节所能表达的值,即不仅仅 ASCII 字符,也包括被编码了的 Unicode 字符,比如 UTF-8 字符. 所以,str 对象就需要 encode 到 bytes, 反之则用 decode. Python 3 的 open 函数与编码有关,即可以在 encoding 形参指定编码,默认是 UTF-8.

但 Python 2 就不一样了。它解释执行源代码时,默认用 ASCII 编码解释,所以若您想指定 UTF-8 编码,得手动在开头加特定注释;字符串对象分别为默认的 str 和 unicode, 后者才能接收 UTF-8 字符的值;open 默认以二进制形式打开,可以写入 str 对象;当 unicode 对象储存的值是 ASCII 编码字符时,它可以与 str 对象互动,比如相加,Python 3 就不能。

最后,在 Effective Python 第三条的基础上,总结编程规范:

  1. 源代码只用 UTF-8 编码,于是所有 Python 2 源代码开头必须包含 # -*- coding: utf-8 -*-.
  2. 只编写处理 Unicode 对象的核心函数,在函数作用域外处理有编码的二进制字符串(Python 3: bytes; Python 2: str)对象到 Unicode 对象(Python 3: str; Python2 2: unicode)的转换。
  3. 无视 Python 2 里 str 类型与编码为 ASCII 的 unicode 类型等价的特性。
  4. 不论版本,对文件读写二进制字符串对象时,必须显示指定 'r' 模式。

Written with StackEdit.

暴君按:您至少明白 Unicode 字符集和编码

March 11, 2016 11:46 AM

LastAvengers

入手 ThinkPad L450

元宵的时候,我从师兄手里买下了这台机子,全新,i5 4300U,8G内存,256G SSD,14寸 1366x768 屏幕。 只有 SSD 而没有 HDD 这点颇合我意,毕竟我没有囤积资源的癖好,256G 足矣,而且还能省下一笔 HDD 的钱。 机子在 ebay 上是 ¥3200,到手花了 ¥3700,以国内的价格来算还是值得的。

之前用的电脑是 Lenove G455,这台 10 年生产的机器陪伴着我姐走过了四年大学, 又在我的高强度使用下度过了大三上学期,现在它终于可以要退役了。这台电脑除了硬盘有点噪音之外,其实一切都运行良好。 单纯做编程的话其实够用,痛点主要是:

  • 无法用 FlashPlayer 流畅地播放 720P 的视频(当然这和 FlashPlayer 糟糕的性能也有很大关系);
  • 跑不起最近的 firefox 和 YCM:Gtk3 版的 FF 的 bugs 还是很多,虽然平时的 UI 响应似乎比 Gtk2 的时候好了一点,但是打开某些网页的时候还是会完全卡住,而 YCM 则有时会吃掉我 1G-1.5G 的内存,然而我的内存才 3G,实在是不堪重负。

现在一切都没问题了,这样的配置在我这个不太关心硬件的人看来,暂时是够用了。

ThinkPad 的外观比我想象中还要漂亮一些,塑料外壳摸起来很舒服,机身还算薄(不插上那个凸起的电池的话),键盘手感也不错。 另外崔土豪说屏幕可以 180 度展开,试了一下果然可以!说到屏幕…… 1366x768 其实还是低了,仔细看很容易看出像素点来。

机器预装 Windows 7,尽管我已经不用 Windows 好几个月了,但毕竟是个正版系统,用了这么多年盗版了,还是洗白一下吧。

至此,我使用的全部软件,全都是自由软件 & 正版软件啦!

Win7 可以升级到 10,升级的过程略坎坷,不知道是怪微软的更新服务器好还是怪国内糟糕的网络环境好。 Check Update 一直不动,从官网下载了在线升级器,下完了整个镜像之后死掉了。最后还是手动从官网下了镜像才装上的。

装完 Windows 后自然就装 Arch Linux 了,还好磁盘格式是 MBR(一直对 GPT 有莫名的恐惧),但是机器预装系统的时候已经把四个主分区都占用了 :( ,于是只好把最后的一个不知道是什么的 OS/2 格式的分区删掉,腾出主分区给 Arch。

Arch Wiki 的光芒照耀下,安装过程一切正常。

装好后尝试了一下 KDE,果然已经不适应了,pacman -Rsc 之,然后回到 XMoand。

趁着重新配置的时候更新了一下配置:

  • 使用 aur/ttf-iosevka 代替 Tsentsiu Mono HG 作为编辑器和终端的字体
  • 使用 xbindskey 管理快捷键,而不是用 xmoand 的 additionalKeys (听小药壶说可以用 scheme 来写 .xbindskeyrc)
  • 使用 terminator 代替 konsole
  • 使用 dzen2 + condy conky 代替 xmobar

    需要启动两个 dzen2,一个接受 xmoand 的输出,一个接受 conky 的输出,需要注意的是 dzen2 不支持 按屏幕的百分比显示, 我在网上找到了这个脚本,可以从 xrandr 获取屏幕宽度,按指定的 比例算出宽度来,我针对我的需要做了一点修改:

#!/usr/bin/sh
# Author: ervandew
# Source: https://github.com/ervandew/dotfiles/blob/master/bin/dzen2
#
# Wrapper around dzen2 that allows width and x to be defined as a screen
# percentage.  The percentage width is define via the new '-wp' arg and
# percentage x as -xp, both of which must be supplied before any other dzen
# arguments.
#
#   $ dzen2 -wp 30 -xp 60 ...
##

external="^\(VGA\|DVI\|DP\|HDMI\)-\?[0-9]\+"
internal="^\(eDP\|LVDS\)-\?[0-9]\+"
pattern="connected \(primary \)\?\([0-9]\+\)x.*$"

# get internal monitor's width only
# 仅获取笔记本屏幕的宽度
width=$(xrandr 2> /dev/null | grep "$internal $pattern" | sed "s/$internal $pattern/\3/")
# width=$(xrandr 2> /dev/null | grep "$external $pattern" | sed "s/$external $pattern/\3/")

while [ 1 ] ; do
    if [ "$1" == "-wp" ] ; then
        arg="$arg -w `expr $(expr $width '*' $2) / 100`"
    elif [ "$1" == "-xp" ] ; then
        arg="$arg -x `expr $(expr $width '*' $2) / 100`"
    else
        break
    fi
    shift
    shift
done

FG='#aaaaaa'
BG='#1a1a1a'
FONT='-*-terminus-*-r-normal-*-*-110-*-*-*-*-iso8859-*'

cat - | dzen2 $arg "$@" -bg $BG -fg $FG -fn $FONT -e 'button2=;' -xs 1

xmonad.hs 那边要这样写:

myLogHook xmproc = dynamicLogWithPP $ defaultPP
                    { ppCurrent = dzenColor "#87ceff" "#1a1a1a" . pad
                    , ppVisible = dzenColor "#aaaaaa" "#1a1a1a" . pad
                    , ppHidden  = dzenColor "#aaaaaa" "#1a1a1a" . pad
                    , ppUrgent  = dzenColor "#ff0000" "#1a1a1a" . pad
                    , ppWsSep   = " "
                    , ppSep     = "  |  "
                    , ppLayout  = dzenColor "#87ceff" "#1a1a1a" .
                                      ( \x -> case x of
                                        "Tall"            -> "^i(" ++ myBitmapsDir ++ "/tall.xbm)"
                                        "Mirror Tall"     -> "^i(" ++ myBitmapsDir ++ "/mtall.xbm)"
                                        "Full"            -> "^i(" ++ myBitmapsDir ++ "/full.xbm)"
                                        "Simple Float"    -> "~"
                                        _                 -> x
                                      )
                    , ppTitle   = (" " ++) . dzenColor "white" "#1a1a1a" . dzenEscape . shorten 50
                    , ppOutput  = hPutStrLn xmproc
                    }

-- NB: dzen2 DOSEN'T support the option `-wp` and `-wx` (p => percentage),
-- I use a shell wrapper from https://github.com/ervandew/dotfiles/blob/master/bin/dzen2
-- {bg,fg}color and font are also set by this wrapper
--
myBitmapsDir = "/home/la/.xmonad/dzen2"
myDzen2Wrapper = "/home/la/.xmonad/start_dzen2.sh"
myXmonadBar = myDzen2Wrapper ++ " -wp 70 -h 18 -x 0 -y 0 -ta l"
myStatusBar = "conky | " ++ myDzen2Wrapper ++" -xp 70 -wp 20 -h 18 -y 0 -ta r"

main = do
    xmproc <- spawnPipe myXmonadBar
    spawn myStatusBar
    xmonad $ defaultConfig {
--  ...
    }
  • 启用了 xmonad 的 smartBorder,这样在不需要边框的时候就不会有讨厌的边框了
import XMonad.Layout.NoBorders

myLayoutHook = avoidStruts $ layoutHook defaultConfig

main = do
    xmonad $ defaultConfig {
--  ...
    layoutHook = smartBorders $ myLayoutHook
--  ...
    }
  • 受上面那个 dzen2 wrapper 启发,在 .xinitrc 里面增加了判断外接屏幕是否存在的脚本:
# Dual screens auto dectection
internal="^\(\(eDP\|LVDS\)-\?[0-9]\+\)"
external="^\(\(VGA\|DVI\|DP\|HDMI\)-\?[0-9]\+\)"
pattern="connected \(primary \)\?\([0-9]\+\)x.*$"

inter_scr=$(xrandr 2> /dev/null | grep "$internal $pattern" | sed "s/$internal $pattern/\1/")
exter_scr=$(xrandr 2> /dev/null | grep "$external $pattern" | sed "s/$external $pattern/\1/")

# 笔记本屏幕为主显示器
if [ ! -z "$exter_scr" ] ; then
    xrandr --output ${exter_scr} --auto --output ${inter_scr} --primary --auto --right-of ${exter_scr}
fi
  • 使用 pacman 来管理 vim 插件(反正肥猫打包了一切

    • all plugins are managed by pacman
    • community/vim-nerdtree
    • community/powerline-vim
    • community/vim-doxygentoolkit
    • archlinuxcn/vim-fcitx
    • archlinuxcn/vim-youcompleteme-git

最后再贴一张图:

March 11, 2016 12:00 AM

March 08, 2016

百合仙子

ssh 会话复用及用户级的 sleep.target

本文来自依云's Blog,转载请注明。

这里看到 ssh 的 Control master 特性之后,就在~/.ssh/config里启用了这个特性:

ControlPath ~/.ssh/master-%r@%h:%p
ControlMaster auto
ControlPersist yes
Compression yes

会话连接复用,对于以交互操作的使用,很不错的!对低延迟的服务器可能只是少了用户认证过程,但对于连接国外服务器,少了 TCP 握手、SSH 握手与认证等来来回回的过程,连接会快非常多的,尤其是对于常用的服务器,比如 GitHub 之类的,提速非常明显。

然后,问题就来了:系统挂起再恢复之后,大部分连接会 stalled,需要手工断开连接。即使配置了超时,它也不一定及时。于是我想,既然 netctl-auto 之类的服务能够在挂起系统时适当处理,那么我是不是也能写一个用户级的 systemd 服务来处理这件事情呢?

于是我按系统级的配置方法弄好了,结果什么也没有发生……后来才明白,只有系统级的 sleep.target,没有用户级的啊。

在 Arch Linux 官方论坛看到有人这么尝试,让系统级的 systemd 调用用户级的 systemd。配置有点不对,但是想法是非常好的!

于是就有了我现在用的方案:

[Unit]
Description=sleep.target of a systemd user session
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
User=%I
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/bus
RemainAfterExit=yes
ExecStart=/usr/bin/systemctl --user start sleep.target
ExecStop=/usr/bin/systemctl --user stop sleep.target

[Install]
WantedBy=sleep.target

启用(enable)user-sleep@1000.service之后,系统挂起时,就会调用 ID 为 1000 的用户的用户级 systemd,也 reach sleep.target 啦。当然这个用户级的 sleep.target 也得自己写:

[Unit]
Description=Sleep
Documentation=man:systemd.special(7)
DefaultDependencies=no
StopWhenUnneeded=yes

然后就可以让用户级的服务WantedBy=sleep.target啦~

by 依云 at March 08, 2016 03:01 PM

March 07, 2016

Issac Ge (Tech)

编程语言与配置

暴君按:本文假设您懂操作系统、计算机网络和编程语言。

什么是配置?用可操作定义来说,只要某「文件」中存在一系列「变量名到值的映射」,且「值」变动时,「进程」的行为就会发生变化,那么这个文件就是配置。其实,事到如今大多工程师接触的往往是文本配置二进制配置那种东西一般只存在于硬件和网络里。硬件就靠汇编语言来控制内存数据的布局,精确小巧得到令人发指,比如 MBR 就是;网络则定义一堆协议,且层次越低,配置就愈发二进制化。

如何写配置?当配置本身就由编译型编程语言写成时,那么意味着每次修改配置就要重新编译,显然成本过于沉重;那解释型又如何呢?我最近写训练机器学习模型的脚本时,就直接在 config.pyglobal 作用域里一一地写定义 Python 对象的语句,即配置。并在其他脚本 from config import 即可。然而 Python 并不支持从绝对路径导入模块。也就是说 Python 作为编程语言,直接假设所有源代码文件应紧密地集中在同一个「目录」下,不可分割,C/C++ 也一样。显然我们只能把 config.py 配置连通其他脚本放在同一个目录下,没法把它移到「样本」目录那边去。好在训练脚本的规模很小,我只需在每次训练结束后,手动复制 config.py, 把它和训练出的模型归档在新目录即可。不过这些方案的共同点都是在编译时定义配置,即不在运行时读取。

如果不用编程语言而是由别的语言写成呢?一般来说要么靠命令行参数来解析配置,要么直接读取文件。但事实上它们的本质是一样的,区别在于 open() 打开的文件,一个是 shell 的 stdin 另一个是某文件而已,且后者不一定要由工程师手动解析。而且命令行参数往往也要写在 Shell 脚本里以自动化,到头来还是免不了配置被封装成文件。不过,stdin 本身是固定的,我们不需要操心配置来源,但读取文件时,我们往往不得不在编程语言源代码里硬编码「文件位置」进去。除非靠相对位置来读取,但这意味着配置又被源代码绑架了。

若要解析命令行参数,C 有古老的 getopt, C++ 有 boost::program_options , Python 一如既往地混乱,即同时有三个库:getopt, argparse 和 optparse. 其实还有个很火又跨编程语言的库 docopt, 我没用过,不知其功夫到底如何了得。

当读取文件时,若要手动解析,麻烦到我都不屑解释。若靠库解析,其实这行为本身就叫反序列化,即把位于储存媒体上的文件解析成编程语言上的内存对象。Python 有两个库 pickle 和 json, 前者序列化的二进制文件只有它自己能反序列化,反之亦然。后者则是通用的文本数据序列格式,即另一个编程语言可以用它的 json 库读取,其实民间还有好多通用的数据格式,比如 toml 啦,yaml 啦,够五花八门。Google 开源了御用序列化库 protobuf, 二进制配置,性能强劲,文档丰富,又支持众多编程语言,深度学习框架 Caffe 就紧紧抱住它的大腿。

最后,其实我还没提及配置由另一个编程语言写成的奇葩情况,这时就要看编程语言对另一个编程语言的支持如何了,至少 Python 解析 C/C++ 的解决方案还挺不少。虽然我宁可靠通用的序列化库来重新剥离出与编程语言无关的配置,再自由自在地反序列化。

Written with StackEdit.

暴君按:本文假设您懂操作系统、计算机网络和编程语言。

什么是配置?用可操作定义来说,只要某「文件」中存在一系列「变量名到值的映射」,且「值」变动时,「进程」的行为就会发生变化,那么这个文件就

March 07, 2016 11:48 AM

March 06, 2016

Issac Ge (Tech)

单位元对编程的启发

最近,我在处理一个文本文件,它有三列,分别为文件名,数字,字符串,且其中第一列中有若干重复了的部分,于是我需要把这些重复的行合并起来,即第二列合并为总和,第三列合并为一条新字符串,且用空格分隔。

我一开始想如此合并:

1
2
3
4
5
sum = 0
string = ''
for duplicate_line in duplicate_lines:
sum += int(duplicate_line.split()[1])
string = ' '.join(string, duplicate_line.split()[2])

但迭代完后 string 并不符合我的期望,它包含了一个 heading space! 这令我想起了抽象代数学上的「单位元」,即它在某二元运算中,与任意元素运算后,结果的值恒为后者本身。比如加法中的 0 与任何数字相加,恒返回后者的原值;乘法中的 1 也同理。

于是我们可以说,把 ' '.join() 当二元运算符来看时,不存在单位元,即 ' '.join([a, b]) 中 b 为任意字符串时,不存在 a 变量能使这函数返回 b 本身,哪怕变量 a 为空字符串时,也会返回包含了一个 heading space 和 b 值的新字符串!就像我上面的代码一样。不过 ''.join() 当然就有单位元即空字符串。

反观 Python 的 int 加法,它就有单位元,即 sum 的初值 0, 也难怪它和悲剧的 string 君不同,可以安全地返回我期望的值。

这启发了我又一条编程规范:要小心那些没有单位元的函数或运算符,并处理得当。其实上面合并 string 的代码可以妙用 list comprehension, 回避掉 heading space.

1
' '.join([duplicate_line.split()[2] for duplicate_line in duplicate_lines])

举一反三,Python Sequences 的 index 为什么从 0 而不是 1 开始计呢?您倒不如想想另一个问题:Sequences Index 的单位元是什么?即对 Index 进行二元运算时,加多少就返回原 Index? 当然是 0 了!再看 C 指针,它和 0 相加时就返回原指针,也难怪 C 的 Array Index 和 Python 的 Sequences Index 都从 0 开始,这是为了当直接把原 Index(甚至 C 的指针即地址)和 Index 初始值(即单位元)相加时,能方便且直接地得到原 Index(甚至 C 的原指针即原地址)。

Written with StackEdit.

最近,我在处理一个文本文件,它有三列,分别为文件名,数字,字符串,且其中第一列中有若干重复了的部分,于是我需要把这些重复的行合并起来,即第二列合并为总和,第三列合并为一条新字符串,且用空格分隔。

我一开始想如此合并:

March 06, 2016 02:47 AM

March 04, 2016

ヨイツの賢狼ホロ

在 Windows 上编织 Pelican 博客 -- MSYS2篇

用 Windows 那是迫不得已……

人生赢家 farseerfc 这样写到......

寄宿在 Github Pages 上的静态博客通常有两种方案,其一是使用 Jekyll 方式撰写, 这可以利用 Github Pages 原本就有的 Jekyll支持 生成静态网站。 另一种是在 本地 也就是自己的电脑上生成好,然后把生成的 HTML 网站 push 到 Github Pages , 这种情况下 Github Pages 就完全只是一个静态页面宿主环境。

我用 Pelican 生成博客,当然就只能选择后一种方式了。 这带来一些不便,比如本地配置 pelican 还是有一点点复杂的,所以不能随便找台电脑就开始写博客。 有的时候只是想修正一两个错别字, 这时候必须打开某台特定的电脑才能编辑博客就显得不太方便了。 再比如 pelican 本身虽然是 python 写的所以跨平台,但是具体到博客的配置方面, Windows 环境和 Linux/OSX/Unix-like 环境下还是有 些许出入 的。 还有就是没有像 wordpress 那样的基于 web 的编辑环境,在手机上就不能随便写一篇博客发表出来 (不知道有没有勇士尝试过在 Android 的 SL4A 环境下的 python 中跑 pelican ,还要配合一个 Android 上的 git 客户端 )。

---- Farseerfc.me:用 Travis-CI 生成 Github Pages 博客

确实,Pelican 虽然是跨平台的,但是......

如果汝用了 pelican-quickstart ,汝的目录下会有一个 Makefile 文件,那么问题来了, Windows 里上哪读 Makefile 啦(ノ=Д=)ノ┻━┻

所以只好在 Windows 里搞个类 Unix(Linux) 环境了(´・ω・`)

某人:其实把 Makefile 魔改成批处理文件也是可以的$#W#@$##%$^&%^%^$^%&%

为啥是msys2?

quininer :明明是 OneGet + PowerShell 大法好嘛~

在 Windows 世界里最出名的类 Unix 环境不是 Cygwin 么?

因为 msys2 有 pacman 啦~

因为 msys2 有 pacman 啦 ~ (╯T▽T)╯ ┻━┻

因为 msys2 有 pacman 啦 ~ (ノ=Д=)ノ┻━┻

重要的事情说三遍 (๑•̀ㅂ•́)و✧

总之为了 pacman 咱最后选了 msys2 😂😂😂

安装和设置 msys2

官方网站 或是 崔主席的镜像源 下载基本组件包啦~ ( cuihao 好棒~ )

如果需要, 把软件仓库换成崔主席的镜像呗~

接下来更新msys2和安装基本工具 ( 咱用了 Github 所以再装个 Git ):

pacman -Syu pacman -S base-devel make git

截至写这篇文章时,咱从pacman安装的 pip ( mingw-w64-x86_64-python3-pip ) 会因为一个 ImportError 没法装任何软件包呐~ ( pia之 (╯@ω@)╯ ┻━┻ )

所以只好装个 Windows 版的 Python 😂

安装 pelican 和 Windows 版 Python

去 Python.org 下载啦~ ,记得把 pythonpip 添加到系统的 PATH 中.( msys2 好像可以用 Windows 的 PATH ~)

接下来打开 msys2 shell (其实就是 Bash 啦 😂) 把 Windows 里的 python 软连接到 /usr/bin/python

# 不知道在哪? 用 whereis 命令查一下啦~
$ whereis python
/c/python35/python.exe
# 用 ln -s <源路径> <目标路径> 创建一个符号链接.
$ ln -s /c/python35/python.exe /usr/bin/python

然后用 pip 安装 pelican _(:з」∠)_

pip install pelican

试验

先用各种不同的方法把汝的 pelican 文件夹复制到 msys2 的主文件夹里啦~ ( 在汝安装 msys2 的文件夹中有一个 home/<汝 Windows 系统的用户名>/ 的文件夹啦 (╯°∧°)╯ ┻━┻ )

如果汝用了 pelican-quickstart 生成了 develop_server.sh 那它喂给 sh 啦~

sh develop_server.sh start

如果没有的话,那就自己 make 呗~

# 生成html
make html
# 运行测试服务器
make serve

有时汝可能用到一些其它程序,那么汝只好通过 pacman 安装或者自己编译啦 (╯‵﹏′)╯ ┻━┻

这篇文章其实是在 Arch Linux 上完成的所以并没有啥截图😂😂😂

by ホロ at March 04, 2016 01:00 PM