4
26
2015
4

鸢尾花

(点击看大图)

鸢尾 1鸢尾 2

鸢尾 3

好多年了,竟然在现实生活中见到了这么多鸢尾花。

多年前,外婆家种了那么一盆鸢尾,不过从来没有开过花。后来经历一场事故之后,那盆鸢尾和三七(问过 Google,很可能是「景天三七」)一起拿到了我家。有株三七还开过一次花,很小的五瓣尖角白花,中间还有好看的花蕊。但是鸢尾,始终不曾开过花,应该是没人照料的缘故。

后来,我去上大学了。某年四月,才得知那盆鸢尾竟然在我不在的时候悄然开花了。花很漂亮,但是五一假期回家的时候,父母刚搬过家,鸢尾已经被毫无同情心的父亲抛弃了。于是,虽然没有费心去养,可也在那么久了,而在它最美丽的时候,我却不在。只能面对130万像素的手机摄像头拍摄出来不清晰还偏色严重的照片失望。

没想到又过了好几年,竟然无意间发现了它们。只能说声好久不见了。

Category: 未分类 | Tags:
4
26
2015
2

发布两个编译好的 Haskell 程序(Arch Linux 64 位版本)

Haskell 程序一向编译起来费力,得先下个巨大的 GHC,然后从 Hackage 上下一堆包然后慢慢编译。所以我在这里把自己用的程序放出来。Arch Linux 的 Haskell 程序打包太复杂了,所以不打包了。连二进制包也懒得打。

这两个程序是 shellcheckcgrep

shellcheck 是一个 bash / POSIX sh 脚本 lint 工具。就是指出程序源码中可能出错的地方,相当于 jshint 之于 JavaScript、pylint 之于 Python(但是不含风格检查)、gcc / clang 的警告之于 C。

cgrep 就是 context-aware grep,比如搜索注释或者字符串里的东西之类的。支持解析几种编程语言。

程序是在 Arch Linux 上编译的,但其它 Linux 也许也可以使用。

下载地址:shellcheck-0.3.7.xz, cgrep-6.4.12.xz.

>>> sha1sum cgrep-6.4.12.xz shellcheck-0.3.7.xz
0588ee29a1a17c1cddc816a8193d8494db7c03cf  cgrep-6.4.12.xz
376b58d485603a7622f83f095a30bddc1da34376  shellcheck-0.3.7.xz
Category: Haskell | Tags: 下载 Haskell
4
15
2015
0

在 Python 里 disconnect UDP 套接字

UDP 套接字是可以使用 connect 系统调用连接到指定的地址的。从此以后,这个套接字只会接收来自这个地址的数据,而且可以使用 send 系统调用直接发数据而不用指定地址。可以再次调用 connect 来连接到别的地方。但是在 Python 里,一旦调用 connect 之后,就再也回不到最初的能够接收从任意地址来的数据的状态了!

这是 Python 的 API 限制,没办法给 connect 方法传递到 AF_UNSPEC 地址簇(在 C 代码里写死了的)。C 里边就可以做到的(代码来自这里):

int disconnect_udp_sock(int fd) {
 struct sockaddr_in sin;        

 memset((char *)&sin, 0, sizeof(sin));
 sin.sin_family = AF_UNSPEC;
 return (connect(fd, (struct sockaddr *)&sin, sizeof(sin)));
}

不过既然是 Python 的限制,拿 ctypes 就可以绕过了嘛,有些麻烦就是了:

from ctypes import CDLL, create_string_buffer

def disconnect(sock):
  libc = CDLL("libc.so.6")
  buf = create_string_buffer(16) # sizeof struct sockaddr_in
  libc.connect(sock.fileno(), buf, 16)

AF_UNSPEC 的值是 0,所以把一个和 struct sockaddr_in 一样长的全零缓冲区传给 connect 就可以了 :-)

Category: python | Tags: Python linux 网络
4
12
2015
13

遥远

不少我喜欢的技术都在我喜欢的公司里使用呢。只是,那里没有我。

Category: 未分类 | Tags:
4
7
2015
5

疯狂的 npm(图)

以前这服务器就经常被 OOM Killer 大开杀戒,各种服务都被杀害。虽然早就通过日志和其它信息知道是 npm 惹的祸,今天才有幸看到如此疯狂的 npm(点击查看大图):

crazy npm htop screenshot

说明一下,此 npm install 是正在安装 gulp 相关的东西。在本地跑的时候倒是没发现 npm 有如此「牛力」,只是比较费时费内存而已,不知道在这服务器上是发了什么疯。

Category: Javascript | Tags: javascript nodejs npm
4
6
2015
10

GitHub 的一个小细节

这是偶然间发现的。在 GitHub 桌面版网页上,按第一下 Tab 时,会在左上角显示一个「Skip to content」的链接,并且键盘焦点就在这里:

GitHub "Skip to content"

我被这样的小小地惊艳了一下。这个链接可以用来跳过不怎么常用的导航栏上那排链接和按钮。

作为经常打字聊天和写码的人,在电脑前的大部分时间手当然是在键盘而不是鼠标上,所以使用鼠标来进行一些操作很常见。虽然我有 keynavVimFx 来辅助,但是见到 GitHub 这么贴心的细节还是挺喜欢的。

这让我想起了国内的网址,大部分都根本不考虑 accessibility。比如问答社交网站知乎。我早已不「逛」知乎了,只是收到感兴趣的邀请时去看看。因为知乎的体验实在是太差劲了。

知乎取消了所有链接在获取焦点时周围的虚线。这意味着根本没办法使用键盘导航,因为你不知道当然焦点在哪里。

知乎的提交按钮完全无法使用键盘操作。看看 GitHub,写好评论什么的,按一下 Tab 焦点就去了提交按钮上,并且有非常明显的反馈。按空格或者回车就可以提交。如果决定放弃,再按一下 Tab 就好。这两个按钮的顺序是按使用频率而不是相对位置来获取焦点的,因为提交显然比放弃用得更多。Twitter 发送新消息、Google+ 评论的提交按钮也是这样。不过 Twitter 偶尔会需要按两次 Tab 才能提交,大概是改页面的时候不小心给改坏了,过段时间会修好。Google+ 分享新信息时会比较讨厌,因为要跳过好大一堆「添加照片」什么的按钮。

类似的 accessibility 处理,国外著名网站上经常能看到很好的实践,博客上经常能看到大家在关心「少数用户」的使用便捷性。而国内很少有关注这方面的,大家都跟乔布斯一样想,「不管合不合理,我是这么设计的所以你应该这么用」。

比如验证码。不管需不需要,都是字符图。这样盲人就用不了。而国外广泛使用的 Google reCAPTCHA 就可以选择通过声音收听验证码。当然是英语的。反正这全球最大的网站之一已经消失在中国大陆人的视野之中了。我知道专门有人建立了一个 QQ 群,视力正常的人帮助盲人识别验证码用的。

这大概是发达国家与发展中国家的侧面写照的缩影了吧。

最后扔一堆链接:

Category: 用户体验 | Tags: web github 知乎 UX
4
4
2015
15

一次面试结果的反思

很久以前的事情了。现在终于不再感觉到那么累了,想写,所以才写。权当日记吧,就懒得加各种链接和排版了。

这次的面试目标是百度运维工程师。

问题:为什么 Arch Linux 中文社区源的自动打包服务是自己弄的,而不使用现成的 CI 呢?

其实原因很简单:没想到。因为 lilac 自动打包脚本是由功能更简单、自动化程序也更低的脚本进化而来的,比如 nvchecker 更新、曾经自己用过的一些辅助脚本等。

当然,即使想到了,我也不会去用的,因为需要定制的东西太多。更新检查、依赖处理、错误回报、git 仓库管理什么的。传统的 CI 不像是天生支持这些的。最接近的 OBS 大家也知道,对 Arch 的支持很差。当然我可以进行二次开发,但工作量会很大、耗时会很长,因为那是我需要从头读文档、学习、尝试的一套系统,而对于 Linux 编程、Python 编程,我已经非常熟悉了。至于可重用性?首先我要解决它的可用性,东西都做不出来了,何谈可重用性呢?

当然 CI 系统对资源的消耗也不能忽视。

这个问题挺意外的,面试的时候没想这么清楚,没答到重点。

问题:为取得网站的高可用性,防止单个服务器挂掉影响整个服务,要怎么办呢?

我的回答是通过 DNS 和 anycast fallback。哪个服务器挂掉了就不用哪个了。DNS 的更新有些慢,在 DNS 应答中返回多个 IP 地址用处不大,大部分客户端都只会尝试第一个,我见过的只有 wget 会锲而不舍地穷尽一切方案去努力。Anycast 反应会更及时一些,CloudFlare 就喜欢用这个。

但是标答是 LVS。好吧这个词我没研究过。回来上网去看了一下,Linux Virtual Server,就是在前端放个负载均衡啦。我没有想到这个。今天我终于想到我为什么没有想到这个了——LVS 还是一台服务器嘛,只是逻辑上的服务器。作为一名程序员和数学爱好者而不是电器维修工,我对各种物理上的东西没什么深刻印象,反而对各种抽象的概念情有独钟。所以我自然而然地把「单个服务器」理解成单个逻辑上的服务器了,而不是或大或小的铁盒子。也就是说,我的理解是,当这个 LVS 系统挂掉了要怎么办。

我再一次把面试官想得到的答案当成了理所当然……

问题:正在进行通讯的两台主机之间的「网线」断了,一方再发送数据,这时会发生什么?

这个问题也很不明确,存在多种可能。

最简单的,直接连接发送方的网线断掉了。内核会收到硬件传回的信息,「carrier lost」,然后相应的路由表项被删除。就跟把相应的网络设备 down 掉一样。什么都不会发生,连重试都没有。应用程序就在那儿等着。

如果是位于局域网中,情形也差不多。只是会进行 TCP 重试,然后 ARP 广播「找人」。

互联网上的话,如果还有其它线路可用,数据包会走其它线路。如果所有线程都不通了,应该会返回 ICMP 主机不可达或者网络不可达。不知道这种情况下 TCP 和应用程序会发生什么。没条件实验。学校网络课实验自然不可能搞这么「高端」的东西。

当然,这么些可能我当时也没想全。

我发现我面试的时候思考能力变得很差的样子。其实凡是被人关注的时候都会发挥失常,虽然没有严重到别人盯着就写不出代码来。这也是我在社交活动常不满意的原因吧。

 

Category: 未分类 | Tags:
3
4
2015
7

Awesome 的 GitHub 今日贡献指示器:今天你 push 了吗?

GitHub 用户页有个 calendar,花花绿绿的甚是好看。不过,经常一不小心断掉了几十天的 steak 着实可惜,特别是用了私有仓库之后,自己看,有贡献,可别人看不到那些私有贡献的呀。其实要维持 steak 也不难,一个小小的提交就足够了——只要我知道我今天还没 push 什么公开的东西的时候。

当然啦,写个脚本天天推个无意义的更新挺容易的,但那样就没有乐趣了不是吗?一天快结束的时候发封邮件提示一下自己不错,但可能已经来不及了。而且这种事情还是随意点好,太刻意了就不好玩了,所以不需要那么强的提醒。弄一个简单的指示器在 Awesome 面板上正好。

效果图(指示器在右上角):

GitHub 今日贡献指示器的 Awesome 桌面

如果这天没有贡献(公开的提交或者 issue 等),那么这只 Octocat 就会失去色彩(变成灰度图)。

代码已上传至 myawesomerc 仓库。以下是实现细节:

首先,创建一个显示图片的 widget:

-- {{{ GitHub contribution indicator
github_contributed = awful.util.getdir("config") .. "/image/github_contributed.png"
github_not_contributed = awful.util.getdir("config") .. "/image/github_not_contributed.png"
github_widget = wibox.widget.imagebox()
function update_github(has_contributions)
    if has_contributions then
        github_widget:set_image(github_contributed)
    else
        github_widget:set_image(github_not_contributed)
    end
end
update_github(false)
-- }}}

-- 在 wibox 中添加这个 widget,需要放到正确的地方:
right_layout:add(github_widget)

函数update_github是给外部脚本用的。不可在 Awesome 配置里直接发起 HTTP 请求,会阻塞的!

当然,还要准备前两行代码提到的图片。从这里下载 Octocat 的图片,并做成彩色和灰度小图:

convert -resize 48x48 -background white -alpha remove Octocat.png github_contributed.png
convert -resize 48x48 -background white -alpha remove -colorspace Gray Octocat.png github_not_contributed.png

把图片放到相应的地方。然后写个脚本来更新这个指示器的状态,也就是获取数据之后再通过 awesome-client 调用update_github函数了。

#!/bin/bash -e

github_contributed () {
  count=$(curl -sS "https://github.com/users/$USER/contributions" | grep -oP '(?<=data-count=")\d+' | tail -1)
  [[ $count -gt 0 ]]
}

get_display () {
  if [[ -n "$DISPLAY" ]]; then
    return
  fi

  pid=$(pgrep -U$UID -x awesome)
  if [[ -z "$pid" ]]; then
    echo >&2 "awesome not running?"
    exit 1
  fi

  display=$(tr '\0' '\n' < /proc/"$pid"/environ | grep -oP '(?<=^DISPLAY=).+')
  if [[ -z "$display" ]]; then
    echo >&2 "can't get DISPLAY of awesome (pid $pid)"
    exit 2
  fi

  export DISPLAY=$display
}

get_display

if github_contributed; then
  s='true'
else
  s='false'
fi

echo "update_github($s)" | awesome-client

GitHub calender 目前是个 SVG 图片,位于https://github.com/users/用户名/contributions

awesome-client 需要设置正确的DISPLAY环境变量才可以使用。这里使用pgrep取当前用户的 awesome 进程里的DISPLAY变量值。ps命令不太好用,不能同时指定多个条件。

万事俱备,只需要拿 cron 或者 systemd.timer 定时跑跑这个脚本就可以啦~


2015年3月14日更新:update_github脚本改用 Python 实现了,更好的错误处理(不会因为网络问题而认为今天没有贡献了),也改用当前日期而非 GitHub calender 的最后一个方块。更新后的脚本在 GitHub 上

2
26
2015
0

Pieces

I want to be a Big Fish, but the lake is so small. I want to live in sea, but I have no way there. And they say, you aren't suitable for salty water.

To do it, or not to do it, it is wrong. This reminds me of my father.

I know about too many things, but none of them is good enough. 韩寒, I knew you were right, now I'm proof of your option.

It's so nice to meet you, CloudFlare. Really nice, not only your service, but your blog. You present me a larger world I'm looking forward to, a world I can only dream of, but fear that I will never reach. Even a piece of it.

There are 1724 days left. I've used more than a third now.

Category: 未分类 | Tags:
2
19
2015
17

过年

经过十二小时的旅程,转了五次车,又回到了这个熟悉的地方。因为年又来了。

依旧是简陋的陈设,依旧只有微弱的 3G 信号。可我还是回来了。所幸,今年除夕,据说是有规定,所以极近的地方并没有燃灯鞭炮,整夜只有远方并不觉得吵的连绵不断的噪音传来,正好和大雨声一样,屏蔽掉了夜里的杂音,让我第一次在除夕夜睡了个好觉。

春节一整天,却是阴沉沉的,因为外边在不间断地下着小雨。屋内灯光不甚明亮,在这种时候聊胜于无罢了。好在我有哆啦A梦的陪伴。也好在我把在北京都很少穿的毛衣带回来了。薄薄的,却抵得上小时候厚厚的两件。

回顾这一年。离开了那浑浑噩噩中选择的南京的初创公司。本来打算回家,再次为自己做一个负责的选择,却困于休息不好、压力山大,几个月过去了,尝试过几家公司,但没有成功。最后无奈之下,再次随意决定,重来到北京,继续自己的生活。

这家公司是在朝阳而不是海淀,不知道这到底算幸还是不幸。重访北京我最害怕的事情没有发生,可也发现,好多技术活动,我要花一个多小时的路程才能抵达。我是不独自坐出租车的,至少不能给差评的不会再坐了。而 Uber,它在向我要姓名,这使我很犹豫。

后来新的问题出现了。公司资金出了问题,拖欠了好几个月的工资。有段时间,我经常看到自己账户上还剩下多少银两,甚至想过罢工然后寻找新的工作。因为我很害怕很害怕。有些事情,人是永远不会想经历第二次的。我看过一部电影叫《时间规划局》(In Time)。在那个真正的「时间就是金钱」的世界中,当一个人的时间耗尽,生命也就终止了。来自社会底层的主人公意外获得了大量时间之后,飞奔着回家,要转给时间已所剩无几的母亲。他和他的母亲在路上看到了对方,飞奔着扑向对方,可是只晚了一秒钟,主人公拥抱在怀中的,已是时间归零的尸体。

还好,在我犹豫着要不要启动紧急计划的时候,工资终于到了一部分。警报解除,终于可以重新安心地生活了。

是的,属于自己的生活。不再是父母老师期望中的「好孩子」「好学生」,也不再是难得安宁地忍受网吧一样的环境,不再只是生存下去了。虽然依旧孤单,但灰色的画卷已经开始涂上的明亮的色彩。做自己喜欢的事情,做自己喜欢的自己,真好。这个世界没有我曾经历的那样充满恶意,也没有像我曾害怕的那样不能包容。虽然父母这边仍然是个麻烦。

事情在向好的方向发展。可是我依旧不知道是否还来得及,实现我那最初的梦想。上次是我自己不好,把事情搞砸了。花了很多时间去思考,去请教,去学习,可终究时间有限,大量的时间都花费在了计算机上。你们都说每一个人都值得获得那份幸福,希望对于除了编程和管理服务器之外什么都还不会的我依旧适用。

未来,我依旧有些许的迷茫和不确定。毕竟,这样的工作对于我来说太无趣了,而这样的队友也太难合作了。表达不清楚事情也就算了,我可以一点点慢慢确认;相关部分技术不懂也就算了,我可以引导你;可你丫的动不动闹情绪算个什么事!对不懂行的人有说有笑、对指出你的问题的人发脾气,能解决问题么?

本来想建立一个生活博客的,但是拖延症唉,新的一年里再努力吧!这一篇,就放在现在的博客上好了。

浓浓迷雾中,终于透出点点光亮。似乎还很远,但我知道,那是灯塔的方向。

Category: 未分类 | Tags:

| Theme: Aeros 2.0 by TheBuckmaker.com