窗外

避讳诸法

中国古人讲究避讳,遇到君王或尊长的名字,要回避以示尊敬。《礼记》中有“入境而问禁,入国而问俗,入家而问讳”之说,意思是到一个地方先要问清楚该地的禁忌,到一个国家先问清楚其国的习俗,到一户人家先问清楚人家的名讳,这样就不会一不小心犯了人家的忌讳,而失礼了。可见避讳这事,在中国已经几千年了。就像哈利波特和他的小伙伴们,对伏地魔不敢直呼其名,而要称之为you know who一样,古人对君王和尊长不但不能直呼其名,而且要想方设法回避用其名中之字,否则可能会犯下不敬之罪。唐朝有个诗人李贺,他父亲的名字叫“晋肃”。李贺要考进士,有人就说,李贺应该避他父亲的名讳,不能考进士。这说法惹恼了韩愈,他专门做了篇《讳辩》,来批驳这些人。但在这篇文章里,韩愈也不敢说不需要避讳,而只是辩解说,李贺考进士,并不触犯“二名律”和“嫌名律”,“父名晋肃,子不得举进士,若父名仁,子不得为人乎?”。可见避讳这件事对古人来说,还是兹事体大的。

为了避免犯罪,古人想出各种方法来避讳,比如最常见的方法就有,改字,空字和缺笔等。

改字法,就是遇到要避的字时,用另一个字代替。陆游在他的书里讲过一个故事说,一个叫田登的人去当州官,命令他的下属要避他的讳,否则就要责罚。于是该州为了避讳,就将灯(与登同音)这个字,用火字代替。到了上元节放灯的日子,州吏贴出告示说,“本州照例放火三日”。这个“只许州官放火,不许百姓点灯”的典故,就是用改字法避讳,闹出来的。

讳不只是人要避,动物也要避;不只是普通人要避,神仙也要避。野鸡这种动物,原来不叫野鸡的,人家原名是雉。只是汉代为了避吕后的讳,才改叫了野鸡,这比人家原来的名字听着土多了有没有。据说嫦娥原名叫做姮娥,为了避汉文帝刘恒的讳,才改名叫嫦娥的。这都属于用改字法避讳。

空字法,就是遇到要避的字时,不写这个字,而是空一格,画个方框或是注个讳字。比如唐初的徐懋功,本名叫徐世勣。唐高祖李渊赐他姓李,于是改名李世勣。到了唐太宗时,为了避李世民的讳,将世字去掉,改叫李勣。当皇帝的这么搞到是玩的开心,可你们有计算过徐懋功他爸爸的心理阴影面积吗?

最牛的空字避讳,大概要数观音菩萨了。传说观音菩萨法力无边,之前一直被尊称为观世音菩萨,到了唐太宗时,为了避讳,只得把世字去掉,改名叫观音菩萨了。也不知是真是假。

缺笔法,是将要避的字的笔画去掉一两笔,变成另外一个字,一般是去掉最后一笔。《康熙字典》里,就将康熙的名字,玄烨,个去掉了最后一笔的点和竖,变成了键盘上敲不出来的两个字。

想起避讳这件事,是因为最近我的两个答案,因为避讳不当,一个被删除,一个被政治敏感了。

中国在清朝之后,理论上就不再需要避讳了。可现实中,由于无法言说的原因,中国人还是需要不断地避讳的。实际上,我答题的时候就已经用改字法避讳了,比如使用庙号和英文来取代原来的字,可看起来改字法并好使。由于输入法的限制,缺笔法根本没法用。看起来唯一有效的方法,是空字法,即要么用方框(比如这个答案),要么彻底删除或避免提到那些讳字。

随着历史的车轮不断向前,中国人要避的讳字也会越来越多,避讳的方法也需要与时俱进才行啊。

[1]同步发在知乎专栏

Dockerfile实践

最近在玩OpenCV,顺手build了一个OpenCV 3.2.0的Docker image。这个image是基于Ubuntu 16.04和OpenCV 3.2.0的source code build的,顺带也build进了Python3的绑定。这个image比较适合用来作为开发和测试基于OpenCV的服务端程序环境的base image。由于包含了几乎全部的OpenCV组件,build的过程还是比较费时的,image的尺寸也比较
大,所以我将它push到了Docker Hub里。需要的话,可以用
docker pull chunliu/docker-opencv

把它拉下来使用。如果要精简组件,或build别的版本的OpenCV,可以修改Dockerfile,重新build。

实际上我以前并没有怎么用过Docker,只在虚机中安装过,顺着Docker官方的tutorial做过,并简单看过官方的几篇doc,仅此而已。大概明白Dockerfile是怎么回事,但没有写过很完整复杂的Dockerfile。事实证明,事非经过不知难,写这个Dockerfile还是有一些坑的。

首先,要写好这个Dockerfile,只靠记事本比较困难,使用辅助工具会容易一些。我用的是VS Code + Docker support,它能提供关键字着色和IntelliSense,也仅此而已。如果有工具能做语法检查就更好了,比如检查行尾是否少了一个续行符之类的。我开始几次都是跑build失败才发现,是某一行少了一个续行符。

另外,我没发现有什么好的方法,来debug和测试Dockfile。最开始,我是修改了Dockfile之后,就跑build,失败再找原因。但是这个build比较费时,这样不是很有效率。后来,我开始在一个container里,逐条跑Dockerfile里的命令,保证每条命令都没问题,再跑build。这样做的问题是,所有命令在一个bash session里跑成功了,并不能保证它们用RUN组织到Dockfile以后,build还能成功。

这就牵扯到Docker是怎么执行这个RUN的问题了。Docker的文档说,每一个RUN会是一个新的layer。我起初不太明白layer的含义,做过之后发现,所谓layer,就是一个中间状态的container。RUN后面的代码是在这个container里跑,跑完之后这个container被commit到image里,然后这个container被删除。后面的RUN,会基于新commit的image,起一个新的container。

所以,如果两段代码需要在一个bash session里跑的话,就需要在一个RUN里面才行。一个例子,比如build OpenCV的时候,会用下面的方式来make:

mkdir build
cd build
cmake ......
make ......

如果将cd,cmake和make分开到不同的RUN中,那cmake和make就有问题了,因为工作路径不对。实际上,RUN的工作目录是由WORKDIR设定的,每个RUN开始时都会使用它上面最靠近它的WORKDIR作为工作目录。所以如果非要将上面的代码分开到不同的RUN,也可以在RUN之间插入WORKDIR来指定路径,不过路径跳来跳去的,比较混乱。

细读Docker的两篇官方文档,对规避Dockerfile里的一些坑,是很有帮助的。

Reference

你好,2017

2016年就这么过去了。

回顾这一年,似乎和往年没有什么不同,依旧是在忙忙碌碌和似乎总也做不完的项目中度过。收获也有一些,但似乎又没有什么大书特书的必要。年初的new year resolution完成的七七八八,其中最重要的减肥目标,没能达成。这一年的体重状态,是不断的起伏。年初开始减,到6月去了趟台湾,被台湾的美食给打回了原型。下半年接着减,结果因为年底去澳洲旅行,又半途而废了。减肥这件事,看来是会继续留在2017年的new year resolution里了。除了坚持,谁知道旅行中有什么好方法控制体重?

进入2017年,我希望自己能将下面几件事情坚持做好做下去:

  • 跑步。从10月重新开始跑之后,目前坚持的不错。
  • 阅读。过去的一年里,我似乎只看完了两本书,其他时间都花在了网络上。2017年先定个小目标,希望自己能每月读完一本书。
  • 分享。“我的知乎2016”显示,我有200多天登录了知乎,不过只写了3个答案,Blog的更新频率也不高。只能自嘲,闲逛也是一种成就。其实我的草稿箱里,到是躺着许多未完成的答案,皆是因为懒,而没有完成的。希望在2017年里,能坚持分享和写作。
  • 增强执行力。程序员界有句名言,”Talk is cheap, show me the code.” 过去的一年中,我也遇到了许多好的不好的idea,但由于执行力不够,都没能实现出来。希望新的一年里,能够改善。其实,如果把这里列的事情做好了,执行力说不定就改善了呢。

你好,2017!

[1]: 题图来自 Unsplash, Annie Spratt

这个疯狂的世界

特朗普刚刚当选了美国总统。

直到今天早上计票开始,所有专业民调,主流媒体和政治专家的预测,都是希拉里当选,只是赢多赢少的问题。舆论甚至认为,希拉里必须大胜,因为赢得不够多的话,特朗普有可能不会接受失败。

可是刚刚的竞选结果,真是跌破所有专家和舆论的眼镜。特朗普不但赢了,而且是大胜。希拉里阵营本来还要争取重新计票,等到明天才看结果的,没想到特朗普赢的太多,只好认输了。

forecast

这世界真是太疯狂了!

希拉里的背后,是华盛顿的政治精英,主流媒体和华尔街财团,而特朗普几乎就是个one man army,一个人在战斗。他没有获得美国政治精英的支持,没有主流媒体的背书,更没有希拉里的筹款能力。阿桑奇也说,这些势力不支持特朗普,他应该没什么机会的。到底是什么,让他赢得了这场选举?有人说,特朗普当选是白人至上主义复辟;是人民寻求改变饥不择食。也有人说,是美国民主伟大的纠错能力起效,腐败的政治精英要被扫荡了。是这样吗?我不知道,不过我想本届大选,只能在疯子和骗子中间选一个状况,至少说明了民主的某种不足。

特朗普的当选,至少使得新加坡的位置,颇为尴尬。李显龙在Facebook上的一段贴文,足以说明新加坡的心情。

It has been a contentious, ugly election season, that has exposed a bitter divide in the American people. Many will celebrate this result, while others will understandably be surprised and disappointed. But like the Brexit referendum in June, Mr Trump’s victory is part of a broader pattern in developed countries – reflecting a deep frustration with the way things are, and a strong wish to reassert a sense of identity, and somehow to change the status quo.

前一段时间,李显龙高调访美,为奥巴马的亚太再平衡背书,呼吁各方遵守南海仲裁,以及呼吁美国国会通过TPP。这些举动不惜得罪中国,我想新加坡那时可能料定,希拉里会当选,美国的政策会延续。现在的结果,新加坡必然会surprised and disappointed。共和党控制参众两院,特朗普上台,TPP自不必说,已经game over了。亚太再平衡的政策是否会延续,也成问题。前两天有报道指,特朗普把新加坡也列为偷走美国人工作的国家之一,俨然和中国是一伙的。这就尴尬了,中国认为新加坡和美国是一伙的,特朗普认为新加坡和中国是一伙的,新加坡这下里外不是人,如何在这个两个大国间,最大化自己的利益呢?

特朗普当总统的美国和世界,到底会是什么样,我们马上就能见到了,拭目以待吧。

重新起跑

我前天跑去买了块Garmin Forerunner 235,打算重新开始跑步。先给自己定了个小目标,每天坚持跑3公里,跑两个礼拜再说。

说起来,我也算是Garmin Forerunner的老用户了。2009年那会儿,我就买过一块Garmin的表,具体型号记不得了,不过那块表应该没有被我丢掉,而是在某个盒子里吃灰呢。那时候的心率还是靠绑在胸前的ANT+带子,不像235,已经是靠手腕上的心率传感器了。那时候的Garmin Connect也很土,同步数据需要把一个USB接收器插在电脑上。Garmin Connect的功能也不如现在多,我就记得有个统计,和调用Google Maps的轨迹,方便炫耀。相比之下,现在的Forerunner 235和Garmin Connect已经进化太多了。235除了运动功能之外,也能够记录睡眠,体重等等健康相关的数据,能够和智能手机同步,再也不用电脑了。完全就是一块智能手表。Garmin Connect不但能统计,还能分析运动和健康数据,功能比几年前强大多了。

就在我买235那天,传出消息说,Microsoft Band可能要被微软砍掉了。去年我去美国的时候,在微软商店里买了一个一代的Microsoft Band。说实话,不怎么好用。主要是带着不怎么舒服,而且挺丑的,手腕上带这么个玩意出门,总让人觉的挺奇怪的。Microsoft Band的GPS感觉也有点慢,出门去跑步的话,得等几分钟让它找着GPS信号,感觉有点傻。我带了几天就扔那了。当时我就想,微软为什么要把那么多传感器塞在这么个带子里?做成手表不挺好吗?

现在也好,专业的事情还是交给专业厂商去做比较好,比如运动手表这类产品,还是让Garmin做好了。唯一可惜的是Microsoft Health和HealthVault服务,没了Microsoft Band,不知道还有没有人会用它们来管理自己的运动和健康数据。毕竟,健康管理可是未来的一个大产业,没有数据,微软想要分这个蛋糕的话,就有点难了。

或者微软可以想想,怎么让Garmin的数据,能同步到HealthVault里面?

Open Live Writer

早年间Blog还流行的时候,微软出的Windows Live Writer是非常流行的一款离线写blog的工具。WLW我用过很久,一开始是和MSN Messenger一起的装的,主要是支持MSN Spaces。后来微软不支持Spaces了,但WLW还留着,因为它也支持Wordpress。又后来MSN Messenger被淘汰了,还是会通过Live Essential Tools安装里面的WLW。直到后来WLW2012之后,这个工具我还是用了很久,直到开发和支持都停止了。

WLW之后,我就再没用过桌面编辑器写blog了。主要是blog写的也少了,偶尔写一篇,就在浏览器里解决了。再者也没发现顺手的工具。直到今天在讨论组里看到有人提起,原来WLW有了开源的版本,而且还发布到了Windows Store里面。赶紧下了一个来试试。新的OLW界面和WLW一致,看起来不是UWP应用,像是通过Desktop Bridge包装了一下。OLW是.NET Foundation支持的,官网是http://openlivewriter.org/,代码开源在Github上。我已经fork了一份。它的readme还介绍了一段OLW的历史,蛮有趣的。

我以前用WLW的时候,给它写过插件。当时就想,有些功能它是怎么实现的。现在开源了,而且这么怀旧的玩具,有空的时候真要好好玩玩。

Ubuntu 16.04

前两天收到通知,说是我host在Azure上的这台VM,可以升级到Ubuntu 16.04了。趁着有空,就将它升了上去。

说起来,这台VM也经历好几次版本升级了。最初的时候,OS是Ubuntu 13.04。后来升级到13.10,再后来是14.04。每次升级都或多或少会遇到一些问题,要花些时间troubleshooting。因为怕麻烦,升到14.04之后就没继续折腾15.10,呆在14.04有两年多了。

因为之前升级的时候遇到过问题,我在今天升级之前还专门搜了搜,果然还是有不少人在升级16.04的时候遇到问题。为了以防万一,我觉着还是先做个备份比较保险。这时候就显出用Azure的好处了。Azure里有一个VMBackup服务,大大简化了云端虚拟机的备份和恢复操作,这个服务也支持Hybrid模式,可以将本地VM备份到云端。考虑到云存储非常便宜,这确实是个不错的功能。我之前就建了一个备份策略来保护这台VM,所以只要跑一下已经定义好的Job,备份就完成了。万一升级出了问题,恢复的话也是一个按钮的事。

备份好之后,我就开始跑升级。没想到还挺顺利的,除了mysql升级失败之外,没有遇到什么会导致升级失败的错误。查log之后发现,mysql之所以失败,是因为apparmor保护了一些路径。因为升级的过程中,我选择保留所有的旧的配置文件,这导致mysql需要访问的一些新的文件路径是被apparmor保护的。改了apparmor的设置,问题就解决了。fail2ban也遇到一样的问题,我在旧版里修改的jail rule有一个bug,但旧版忽略了,新版就出错无法启动。修了这个bug之后就好了。其他的服务都没有遇到问题,升级之后就立即可用了。

总之这次升级还蛮顺利的,一个上午就搞定了,我本来还打算搞一天的。

Crazyflie

Crazyflie 2.0
My Crazyflie 2.0

Azure Marketplace搞了一个叫做Super Human的推广活动,推广Azure Marketplace里的各种服务。这个活动推出了一些virtual labs,你如果正好对这些服务感兴趣,通过这些virtual labs,可以学习怎么在Azure中使用它们。

其实virtual labs不是我想说的重点。重点是,如果你成功做出了某个virtual lab的结果,会得到一个奖励。你可以选择得到一个为期3个月的Azure Pass,或者一个Crazyflie 2.0无人机。3个月的Azure Pass也许不错,可是我想大家应该都会选无人机吧?

所以,这个无人机才是我想说的重点,因为我做出了其中一个lab,并且拿到了无人机。这个活动的奖品只能寄到美国的地址,我辗转托了两个朋友才弄回新加坡。这个官网售价180美金的无人机,需要自己动手组装,上面的照片,就是组装好之后的样子,非常小巧。昨天装好之后,我拿去公园的空地上试了试,让无人机飞起来到没问题,只是操控还不是很熟悉,结果一个螺旋桨的塑料支架被我摔裂了。不过还好,包装里每个配件都提供多一个备用件,很好更换。

台湾的美食

在台湾旅行的一大感受是,吃的东西实在太丰富了。街头巷尾随处可见各种小店和摊贩,食物便宜又好吃。走在台北车站的地下街,感受尤其强烈,各种糕点小吃琳琅满目,诱惑的你挪不动步子。

我们在台湾的时候,就曾讨论过,台湾的饮食之所以对我们的胃口,让我们觉得好吃,多半是因为49年后迁台的外省人们,将大陆大江南北的美食统统带到台湾来,并融入到台湾本地的饮食中了。作为对比,在新加坡吃饭也很方便,食阁,咖啡店和熟食中心遍地都是。可是新加坡的中餐比起台湾的来,就少了几分江浙菜的精工细作,豆浆油条大饼包子这样的北方饮食成分就更少了。

端传媒上的这篇文章,讲的是两蒋和台湾饮食的风景。确实,台湾的美食也算是两蒋留给台湾的宝贵遗产了。希望这些不会被台湾,在继续去中国化的过程里,给统统丢掉了。

在台湾一路吃了不少好吃的,小吃,甜点,咖啡这些就不提了,说说我们在台湾吃过的几家馆子。

1.

吃饭食堂的煎猪肝和卤肉饭

吃饭食堂是永康街巷子里的一家小店,味道不错,价钱也便宜,貌似许多台北人也光顾。台北街头有许多这样便宜又好吃的馆子,像是我们住的一家酒店旁边的二马饮食。我们到台北第一晚,到酒店天有点晚了,坐飞机折腾的有点累。我们想着附近随便吃点,就进了二马饮食。店很小人很多,我们点了几样简单的小菜和饭,没想到味道超出我们的预期,一下子提高了我们对台湾美食的期待。

2.

永康牛肉面

永康牛肉面大名在外,不用多说了。牛肉和汤头都不错,只是从陕西人的角度,面普通了点。

3.

高记的生煎包

高记的生煎包是小锅煎的,包子不大,皮薄馅大,味道不错,比小杨生煎精致些。店员介绍,高记在上海也开了分号。我们真的是离开上海很久了。

4.

台铁便当

坐台铁的时候,在车站买好,带到车上吃的。车上也是有卖,但大家怕车上的卖完了,都是先在车站买好。一大块猪排加卤蛋,只要80新台币。

5.

佘家孔雀蛤

淡水的孔雀蛤,攻略上看到的。

6.

度小月的担仔面

度小月也在永康街,台南的担仔面,相对就不如江浙菜细致了。想来也是,担仔面是挑着胆子贩卖的街头食物,自然比不了老蒋和宋美龄的家宴和国宴的讲究。

7.

花莲公正包子

花莲的公正包子,新台币5元一个,50元一笼,非常便宜。这种发面蒸的,北方口味的包子,在新加坡不多见。味道让我想起小学时候,学校旁边的小笼包和蛋花汤。花莲的另一样眷村美食,是扁食,也就是大个馄饨。据说蒋经国当年来花莲,必吃的就是扁食。花莲的包子店不卖扁食,而扁食店就只卖扁食。

Build a SharePoint Server 2016 Hybrid Lab

SharePoint Server 2016 has been out there for a while. One big feature of it is the hybrid configuration with Office 365. To understand how it works, I built a lab environment based on Azure VMs and a trial subscription of Office 365. Here is how I did it.

Prerequisites

To build a lab environment for hybrid solutions, you need the following components in place.

  • An Office 365 subscription. A trial is fine.
  • A public domain name. The default <yourcompany>.onmicrosoft.com domain that you get from the O365 subscription won’t work in hybrid scenarios. You have to register a public domain if you don’t have one.

Configure Office 365

In order to configure the hybrid environment, you must register a public domain with your O365 subscription. The process is like you go to your O365 subscription and kick start a setup process. O365 will generate a TXT value. You need to create a TXT record in the DNS of your domain vendor with that value, and then ask O365 to verify it. Once the domain is verified, the domain is register with your O365 subscription successfully. More details can be found here.

You don’t need to create those DNS records for mail exchange such as MX etc. if you just want to test SharePoint hybrid scenarios. You only need to create them if you also want to test the mailbox features.

The next step is to configuration AD sync between your on-premise AD and the Azure AD created with your O365 subscription. You can configure the Azure AD Connect tool to do it. And for a lab environment, AD sync with password sync is good enough. You can also try AD sync SSO if you have an AD FS to play with.

Before kicking start the AD sync, you might have to do some cleaning on AD attributes. I changed the following:

  • Add a valid and unique email address in the proxyAddresses attribute.
  • Ensure that each user who will be assigned Office 365 service offerings has a valid and unique value for the userPrincipalName attribute in the user’s user object.

With the cleaning done, you can start to sync the AD. You should be able to see users account in the O365 admin center after syncing.

Configure SharePoint Server 2016

Deploy the SharePoint Server 2016 farm. You can try the MinRole deployment if you have multiple servers. In my lab, I just deployed a single server.

The following service applications are required for the hybrid scenarios.

  • Managed Metadata Service
  • User Profile Service with user profile sync and MySite host.
  • App Management Service
  • Subscription Settings Service
  • Search Service for hybrid search scenario

The user profile properties need to have the following mapping:

  • User Principal Name property is mapped to userPrincipalName attribute.
  • Work email property is mapped to mail attribute.

Configure Hybrid

Once you have the O365 and SharePoint Server 2016 ready, you can start to configure the hybrid. It is fairly simple with the help of Hybrid Picker of SharePoint Online. You just need to go to SharePoint admin center of O365, click configure hybrid and pickup a hybrid solution, follow the wizard. If everything is ok, you will get the hybrid configured. Browse to an on-premise site, and you should see the app picker like the screenshot below.

Next Step

Next thing to try is to configure the server to server trust and the cloud hybrid search. Stay tuned.