December 10, 2017 / macOS, customization, tool, alfred

在使用Mac时,不知你是否有过这样的想法? 让应用窗口占据半个屏幕,比如一半屏幕是浏览器,另一半屏幕是命令行终端,边看文档边部署服务 外接显示器时,让窗口在屏幕之间移动 加入前东家猿辅导后,平时开发主要使用macOS,在这之前,工作和个人使用主要是用Arch Linux,使用的窗口管理器是i3,它是一个平铺式窗口管理器。使用过iTerm的读者可能知道一个iTerm窗口可以开多个Tab,每个Tab可以水平或垂直切分成多个面板。类似地,i3使用Workspace(如同Desktop)来聚合窗口,每个Workspace可以通过水平或垂直切分成多个窗口。 将多个窗口平铺在一个屏幕上可以减少应用切换和增强多任务工作体验,我个人比较喜欢这种方式,将macOS作为主要操作系统之后,习惯性地去搜罗窗口管理应用。目前macOS上的窗口管理应用不少,参考iCHAIT/awesome-macOS和jaywcjlove/awesome-mac推荐一些: Amethyst: 平铺式窗口管理 BetterSnapTool: €3.49 chunkwm: 平铺式窗口管理 Divvy: $13.99 Hammerspoon: 强大的macOS自动化工具 Magnet: $0.99 Moom: $10 Phoenix ShiftIt Slate: 试图替换Divvy/SizeUp/ShiftIt,需要配置 Spectacle Stay: $15 SizeUp: $12.99 我曾经尝试过上面的列表的差不多一半应用,最后选择了Hammerspoon:一是因为我个人偏好高度可配置的应用,Hammerspoon配置是用Lua语言编写,有编程经验的读者学习Lua相信会很快,可参考Learn X in Y minutes ;二是 Hammerspoon背后是Lua脚本引擎,可以做的事情远不止窗口管理。没有编程经验或不想折腾的读者也可以从上述列表找一个无需配置开箱即用的应用。 安装与配置 从 https://github.com/Hammerspoon/hammerspoon/releases/latest 下载Hammerspoon-x.x.x.zip,解压缩后将Hammerspoon移动到Applications,安装就完成了。 我目前使用的配置可见jeoygin/awesome-hammerspoon,在ashfinal/awesome-hammerspoon的基础上做了如下修改: 增加Main Mode,通过Main Mode进入其它Mode 增加切换到特定应用的快捷键 支持循环切换同个应用的不同窗口,比如打开了三个Chrome窗口,可以在这三个窗口循环切换 执行以下命令下载配置: 重新加载配置之后,在桌面上可以看到Hammerspoon显示的日历。 快捷键 目前已支持以下的快捷键: ⌘ +⌃ +⇧ +R: 重新加载Hammerspoon配置 ⌘ +⌃ +⇧ +1: 将当前窗口移动到第一个显示器

read more »
December 3, 2017 / HTTPS

Let’s Encrypt是一个免费、自动化和开放的权威机构,它是由非盈利组织Internet Security Research Group (ISRG,互联网安全研究小组)提供的一个服务。为了创建一个更加安全和保护隐私的网络,它向人们免费提供HTTPS(SSL/TLS)所需要的数字证书。Let’s Encrypt受到了Mozilla、Chrome、Akamai和CISCO等的支持。 本文使用一个开源工具acme.sh来申请证书,acme.sh是一个用Shell脚本编写的ACME(Automatic Certificate Management Environment,自动化证书管理环境)协议客户端,Let’s Encrypt正是使用ACME协议进行证书签发。 安装 安装OpenSSL: 安装acme.sh 签发证书 Let’s Encrypt需要验证域名,因此需要先修改Nginx配置,增加中间的 location ^~ .well-known/acme-challenge 部分。如果有多个域名的话,记得对每个域名都做修改。 listen 80; server_name jeoygin.org; location ^~ /.well-known/acme-challenge/ { root /var/www/challenges/; try_files $uri =404; } location / { return 301 https://$host$request_uri; } } 重新加载Nginx配置,然后执行acme.sh签发证书: sudo mkdir -m 774 /var/www/challenges sudo chown www-data:www-data /var/www/challenges sudo nginx

read more »
December 2, 2017 / macOS, customization, tool, alfred

如果说只能推荐一个Mac应用的话,Alfred会是笔者的选择,它是笔者使用最频繁也是最喜欢的应用,相信大多用户使用后也可以提高效率、节省时间。 Alfred vs. Spotlight 很多读者朋友可能会觉得Alfred的功能不就是应用启动和本地/web搜索,然后可能会问既然macOS已经有Spotlight了,为什么还要使用Alfred,那笔者就先来对比下这两者。Spotlight可以帮助我们快速搜索计算机上的应用和文件和显示互联网、iTunes、App Store等的搜索结果,在笔者看来,Spotlight的主要功能是搜索(应用启动也可以算是一种搜索)。 相信每位读者朋友都有自己喜欢的启动/切换应用方式,笔者在几年前使用Arch Linux的时候或更多年前使用Windows就习惯于使用Application Launcher来启动/切换应用,可以减少鼠标的操作,所以使用Mac的时候很自然就用上了Spotlight。但由于搜索来源较多,所以要等几秒Spotlight才会显示搜索结果(可能笔者的MacBook Pro比较老了,性能下降了),虽然切换应用不需要等,但笔者有点强迫症,很快就通过搜索引擎找到了拥有强大定制能力的Alfred,当时免费版已经能够满足最初的需求了。 PS: Spotlight在过去几年不断改进,变得更加好用了,虽然搜索响应慢,但在搜索结果中可以浏览结果条目,这是个不错的feature. 从上图可看出,除了File Search和Web Search,Alfred还提供了其它的功能。为了提高效率,Alfred通过关键字、快捷键和文本扩展来定制对应的功能,避免执行不必要的操作增加响应时间。比如在唤出Alfred搜索框后,可以通过如下默认关键字进行文件搜索: open: 打开文件 find: 在Finder中显示文件 in: 查找包含搜索词的文件 tags: 查找加上给定tag的文件 既然用Alfred相对更高效,那么可以关闭Spotlight吗?Alfred依赖Spotlight的索引信息,如果关闭Spotlight的索引,Alfred将不能搜索本地的文件,所以Alfred不能完全取代Spotlight。 免费版 vs. Powerpack Alfred免费版已经提供了不错的功能如文件搜索、Web搜索、计算器、词典和体统命令等,一般公司内部各种工具如wiki、问答或代码仓库等会提供搜索功能,找到对应的搜索URL并添加一个Alfred自定义搜索,就可以快速搜索,比如Google搜索的URL是 http://www.google.com/search?q={query}. 如果想解锁额外的功能,需要购买Powerpack许可证,其为用户提供了灵活强大的集成和定制能力,单用户的v3许可证是19英镑,按目前汇率算大致是170RMB,不便宜,可视经济情况决定购买,毕竟免费版也可以满足日常使用了。笔者在挖掘Powerpack的高度定制能力后,发现其物超所值(笔者偏爱可高度定制的工具),而且Alfred有很好的社区和很多强有力的workflow,如果没找到满足特定需求的workflow,创建一个新的workflow也不难。 上图是笔者最近一个月一台MacBook上Alfred的使用情况,Hotkeys使用频率最高,其次是Clipboard。Clipboard是一个好用的功能,可以自动保存复制的文本、图片或文件,方便从剪贴板历史搜索需要的内容。笔者设置在剪贴板历史的顶部显示“All Snippets”,可以粘贴一些常用的文本片段。 Workflows 通过Alfred的Powerpack和workflow,用户能够扩展并以自己的方式完成事情。以workflow替代重复的任务,从而提高效率。普通用户可以从如下链接寻找想要的workflow: https://www.alfredapp.com/workflows/ http://www.packal.org/ https://github.com/zenorocha/alfred-workflows https://github.com/derimagia/awesome-alfred-workflows https://github.com/willfarrell/alfred-workflows https://github.com/learn-anything/alfred-workflows https://www.alfredforum.com/ 所谓的workflow就是工作流,通过创建一个个动作并以有向无环图的形式组织起来,提供一个输入,Alfred会完成对应工作流上的所有动作。拥有编程能力的用户可以通过编写脚本来完成其中的某些动作,支持bash、zsh、php、ruby、python、perl和osascript等语言,通过Alfred作为入口,可以完成大部分事情。从Writing Alfred Workflows in Go这篇文章可以看出用Go语言也是可以编写workflow的,以此类推,其它语言也是可以做到的。 为了方便切换浏览器tab,最近笔者安装了一个workflow rapid-browser-tabs-for-alfred,优点是可以在多个浏览器之间切换tab,不足是响应没有浏览器内部安装的扩展程序切换顺畅。可见下图。 也有workflow可以切换iTerm tab: alfred-tty。 https://i.imgur.com/A9rrl36.png 同步 激活Alfred Powerpack后可以使用同步功能,可以在多台Mac同步设置、主题、Workflows和Snippets等。 设置同步的步骤如下: 打开Alfred Preferences并进入Advanced tab 在右下角可以看到Syncing设置,点击“Set

read more »
November 19, 2017 / macOS, customization, tool

博客有将近五年停止更新了,只在Wiki记录些笔记,最近想为博客注入新的生命力,但一直也没想好要写点什么。工作后这几年陆陆续续在尝试一些工具,通过定制来满足笔者的需求以及简化和自动化工作流,想先写一个序列介绍笔者是如何通过组合各种APP和命令行工具《打造个性化的macOS》,也是对现状做个总结。虽然是针对macOS,但用到的有些工具是跨平台的,其它很多工具在其它操作系统(比如Linux和Windows)也可以找到对等物。两三年前笔者就想写一篇《打造个性化的ArchLinux》,但两年前换工作后渐渐发现用macOS可以少点折腾,于是就没怎么用Arch Linux了。 第一篇先来讲讲这篇文章是如何诞生,具体用到的工具后续文章再作详细介绍。 使用Hakyll生成博客 Hakyll是一个用于生成静态网站的Haskell库,与Pandoc集成使其可支持markdown、TeX和Emacs org-mode等多种格式。一年前想用org-mode格式来写博客,很幸运找到了Hakyll,也发现了支持org-mode格式的Wiki程序gitit。 最近发现一年前找的Hakyll博客模板hakyll-blog编译有问题,昨天花点时间更新了最新模板,并对必要的地方做了修改。为方便日后更新,在Dannysu的hakyll-blog本地git仓库上建立一个新的分支并提交所做的修改。 笔者博客的git仓库是https://github.com/jeoygin/hakyll-blog,进入hakyll-blog本地仓库后,生成博客只需要执行一条命令: 编写文章时可以启动本地服务器,有内容变更时会自动生成博客: 部署生成的博客到服务器也很简单: Emacs编写文章 用Emacs org-mode记笔记或写文章很方便,除了用Hakyll生成,当然也是可以用org-mode强大的导出功能,本文源码可见2017-11-19-customize-macOS-0.org。 源码以文章的元信息开始,这部分是用YAS snippet自动完成,输入 \hph+TAB 即可。而源码块是输入 <s+TAB 自动完成,org-mode的Babel默认支持。 传送门 macOS wiki P.S. 工欲善其事,必先利其器,工具是为解决问题、做好事情服务,勿为了工具而使用工具。

read more »
January 28, 2013 / 2012, 总结, 找工作, 改变, 英语

这几天年会、婚礼轮轴转,这会终于能闲下心来写点东西,总结一下过去一年的点滴! 此刻是2013-01-27 21:33,以我目前的写作水平,我不知道此文最后会是什么样子,只能先来头脑风暴一下2012的关键词。 学英语、找工作、改变、记录、忙里偷闲这几个词可以总结我的2012年。 学英语 英语一直是我的硬伤,听说读写样样烂,尽管我认为去狂补也无济于事,但为了找工作,只能放手一搏,企求屌丝能够逆袭。 学习英语音标,背单词,背常用短语,学习语法,听VOA Special,做听写,写日记(这个后来实在写不下去了,因为每天的日记都千篇一律)。 背过几遍托福单词,由VOA Special过渡到VOA Standard,后来听老托福听力,慢慢有了点信心。 万事开头难,遇到不熟悉的事情,总会担心无法搞定,但我们只要克服心中的畏惧,使劲搞,可能就会离成功越来越近。 后来把国内的某个考试通过了,成绩尚可,但我还是觉得英语比较差,到了一个更高的瓶颈,而且发现我的中文也有同样的问题:写不通顺、说不流畅、读下句忘前句、听话只记当前句。 语言是我一个很头疼的问题,未来可能会给我带来不少麻烦,必须想办法去完善,书读得少、话说得少、少与人交流是导致这个问题的几个重要原因。 还是多看点书、多背点文章、学唱几首歌、多和人说话吧! 找工作 这是人生的几件大事之一,是2012年的头等大事,给予了足够的重视,却未做好充分的准备。 6月份才正式开始准备找工作,看书、复习算法,先后看了《深入理解计算机系统》、《编程之美》、《编程珠玑》、《程序员面试宝典》、《深入理解Java虚拟机》、《Cracking the Coding Interview》等书,复习了线性代数、概率与统计、组合数学等知识,陆陆续续也在网上看了一些面试题,从8月底开始面试,一直到11月底结束战斗。 先来说一些好的。首先,简历还算漂亮,之前玩过一些技术,也做过一些有趣的项目,还是有比较实在的内容。其次,大部分笔试做得还行,有几个笔试应该算是挺不错的。最后,很多公司前几轮的技术面试基本能通过,主要考查内容是写代码或问一些比较细节的技术问题。 不足的是中后期的面试几乎都挂在最后一轮,在谈人生谈理想中谈挂了,最后自己总结的一个原因是:害怕说话,面试前就觉得面试可能会不成功结果怎么可能理想。没有野心,没有魄力,没有信心,不知道最想做的事情是什么,不知道喜欢什么,对未来没做好规划,交流能力欠缺,不会表达自己……这些导致了一次次的面试失败。 周围的同学经过一些面试后总结出经验,一个个都练成了面霸,而我依然还是新手,跟面试官谈话容易找不到头绪,时不时还会紧张,特别是谈人生谈理想时,简直被同学们完爆好几条街。 众多公司的面试当中,Google给人的体验最好的,很遗憾的是在9月底时就和Google、Microsoft和Hulu这些公司说再见,以至于我后面失去了信心和斗志,我真得还需要去好好锤炼。 求职过程中的几多辛酸能有几人理解,现在差不多已成定局,虽然不是最期盼的,但也比较满意,应该是离下一步的目标最接近。这几个月中想明白了一些问题,这对个人的成长来说非常重要。 单就找工作历程就可以另开一篇文章来写了,这个有时间再来构思吧。 改变 有一天,上帝突然对我说:“你不能再做一个木讷呆板的码农,你要改变!”于是,我开始尝试改变自己。 其实,在很久很久以前,我曾以为只要技术做得足够好就行了,但现在才发现原来光有技术是不够的,身体状况、精神状态、交际能力等可能会阻碍我在技术领域走得更远。于是,我必须做出改变。 心想着要干牛逼的事情,但我自知不是一个牛逼的人,只是个听话的学生、孩子,而不是聪明的学生,对于给予的任务,会想尽办法做到最好,却很少去想为什么要做那样的事情、去想为什么要接受那样的任务、去想做那样的事情后对自己有何提高,一直在做很多各式各样的事情,很杂很泛,没有重心,没有积累,没有提高,而且过得比较累。有时眼高手低,不愿做一些不起眼的事情,有些事情不愿意做第二次,其实如果能把基本的事情做牛逼了也是一件了不起的事情,任何事情都能让一个人成长,只有自己看得不够远安于现状时才会原地踏步。因此,我不能什么都想做,否则我会一直是个半吊子,我必须找到一个喜欢做的事情,深入去学习去探索,以期成为某个方面的专家。 什么都能接受意味着什么都不想接受,要以挑剔的眼光看世界,能分清是非黑白,有喜好与厌恶,在尘世中保持一颗平凡而真诚的心。 多看书、多看电影,并在其中学习琢磨作者、导演、人物的思想、情绪以及感情等。 多说话,改变一贯沉默不语的风格,不过目前还未改变彻底,或许,我天生就是个观察者和行动者,话不多。 多与人交往,扩大交际圈子,通过交流来学习一些课本上没有东西,在生活中学习。 多运动,打羽毛球,游泳,健身,保持一个强健的体魄,才有精力学习与工作。羽毛球水平一般,游泳刚学会自由泳,动作不是很规范,游得很慢且比较吃力。 开始吃以前不吃的葱、姜、蒜、芹菜等。 记录 主要是记录了一年完整的简短日志和财政收支。 我也没想到我能完成上面的任务。但目前的日志还存在一些问题,比如信息不够详细:没有时间、地点、人物及重要事件。 在年初做的财政计划就是每月将收入的30%存起来,有几个月支出比较大,超出了收入,虽然整年支出比较多,最后算下来还是攒了一笔小钱。 忙里偷闲 忙学习、忙项目、忙找工作、忙毕设,但劳逸结合可能效率会更佳,特别是看到各种程序员猝死的消息,更不敢像以前那样拼命了,本来体质就没别人好,容易把命都拼没了,因此大胆做出了改变,每周抽出点时间看看电影或出去玩玩,积极参与各种活动。 春游、夏游、上海两日游、骑行、海边游泳等各种活动还不少,后来又萌发学习摄影的念头,要以摄影师的眼光看世界,记录生活的点滴,于是买了个单反,但现在手中利器还不太会使用,各种摄影技术还不知晓,路还很长,慢慢学习。 某天,好像发神经似的想学习笛子,于是就在京东买了一把G调竹笛和一本笛子教程,学习笛子的初衷是为了练气,因为平时说话老感觉气不顺,于是要练习呼吸,这个理由似乎有点无哩头。买完也没花太多时间去练,目前还不会。 现在又觉得我想做的事情太多了,需要砍掉一些,不能太贪心了,专心搞好一个就好了。 ================================================================= 华丽的分界线下就要来看看去年所做的2012年计划的完成情况以及做2013年计划。 去年所做的新年计划如下:

    工作:年后把一切杂事处理完,开始新的工作; Java:继续学习,最好能脱离IDE; 找工作:可能去外企?互联网公司?一切皆是未知数,不想花太多时间在准备找工作上,找一个喜欢的、成长空间较大的职位就好; 英语:加强口语、写作,希望能达到与外国人简单交流、写paper的程度,如果能过六级或托福考试那更好; Hadoop:学习MapReduce、熟悉外围系统、学习源码; 练说话之道:能清楚地表达思想,与人流畅沟通,变得自信; 读好书,2012年书单:http//book.douban.com/doulist/1432612/;

    read more »
December 31, 2012 / 学习, 工作, 生活, 研究生

岁末年初,现正拖着2012的尾巴走向2013,在这跨年夜(我已记不起从什么时候起,12.29这一晚上多了点跨年的味道),身边几个同学在看跨年晚会,本也想凑个热闹,无奈我的Archlinux不给力呀,怎么整都播不了mms协议,只能另找乐子。本想写篇2012年的总结,但我习惯等回家时静下心来好好梳理一年发生的事,想起这么一篇小记被落下了,赶紧收拾心情,写下一点笨拙而苍白的文字。 小记: 准备某个英语考试,并以不错的成绩通过了,但我不能明说,了解我的亲们你们懂的,这是我多年心中的痛,英语依然还是我的痛处,写12年总结时会再细细道来。 参加阿里巴巴的一些活动,为找工作准备。 学习Linux驱动,不过项目上的事情进展不是很顺,后来就没有然后了。 参加几个活动,听师兄师姐介绍找工作经验,对后来找工作很有帮助,感谢你们无私地把一些宝贵经验倾囊相授。 崔皓组织北理工的同学去蟹岛游乐场,玩得很high,有些高空项目还有有点惧。见到了不少生人,但是我不是那种初次见面就能成为朋友的人,与很多人仅仅是一面之缘,在为人处事方面还是要多多改善。 看《深入理解计算机系统》、《编程之美》、《编程珠玑》、《Linux设备驱动》、《如何阅读一本书》、《Java程序员面试宝典》、《其实你不懂广东人》、《美语发音13秘诀》。 写中英文简历。 参加Hulu Open Day,被Hulu的高品质、快节奏工作所感染,希望能进入到这样的团队中,可惜自己还不够优秀。比较幸运,得到一个奖品——Hulu挎包。 搬回了青年公寓,离开科一招那一刻心中对科一招的不舍之心喷涌而出,平时看起来冷漠,关键时刻却几多伤感。 两个好友相继结婚,身边的人一个个开始组建家庭,不知什么时候我才能认真考虑这个问题。 回家,这几年很少回家,也很少往家里打电话,面对家人真不知说什么好,总不能说技术吧,在这方面,我真的是很不孝,趁现在回家还方便,有时间就多回家看看,探望日益年长的父母。 研读“结构之法算法之道”、“何海涛博客”等网站的算法题及文章 看公开课《Algorithms Part I》 实验室北戴河夏游,大一时去过一次,因此并不是很期待,不过比较喜欢参加集体活动,所以报名了,最后大家对这一次出游评价都不是太好。 开始找工作内推,阿里巴巴一二面,阿里巴巴所有也就两轮面试,这是最早拿到的offer。 这一篇继续以流水帐的形式记录我在6、7、8月份的一些经历和体会,或许这会是记研究生系列的最后一篇,最近三个月发生的事我会在年终的总结中详细说,未来半年最重要的事情是毕设,比较单调。回头看这两年,能坚持每个季度写一篇小结对我个人来说已很不容易,虽然已在这个世界活了二十五年有余,但我写过的文字、说过的话少得可怜,看过的书也是屈指可数,导致在语言组织与人际交往等方面的能力很弱,我因此在求职过程中吃了很大的亏。于是,我现在会鼓励多去尝试一些新鲜的事物,不要因为不熟悉就退避三舍,不会可以学习,多接触一些人和事有利于自己的成长。要有眼光和远见,不要局限于当下所拥有和掌握的东西,要明确自己的目标,做好一切准备去争取自己想要的东西,持续学习,不断积累,厚积薄发。 完结。。。

read more »
December 14, 2012 / benchmark, Example, Hadoop, HiBench, Test

测试对于验证系统的正确性、分析系统的性能来说非常重要,但往往容易被我们所忽视。为了能对系统有更全面的了解、能找到系统的瓶颈所在、能对系统性能做更好的改进,打算先从测试入手,学习Hadoop几种主要的测试手段。本文将分成两部分:第一部分记录如何使用Hadoop自带的测试工具进行测试;第二部分记录Intel开放的Hadoop Benchmark Suit: HiBench的安装及使用。 1. Hadoop基准测试 Hadoop自带了几个基准测试,被打包在几个jar包中,如hadoop-test.jar和hadoop-examples.jar,在Hadoop环境中可以很方便地运行测试。本文测试使用的Hadoop版本是cloudera的hadoop-0.20.2-cdh3u3。 在测试前,先设置好环境变量: $ export $PATH=$PATH:$HADOOP_HOME/bin 使用以下命令就可以调用jar包中的类: (1). Hadoop Test 当不带参数调用hadoop-test-0.20.2-cdh3u3.jar时,会列出所有的测试程序: An example program must be given as the first argument. Valid program names are: DFSCIOTest: Distributed i/o benchmark of libhdfs. DistributedFSCheck: Distributed checkup of the file system consistency. MRReliabilityTest: A program that tests the reliability of the MR framework by injecting faults/failures TestDFSIO:

read more »
September 20, 2012 / ArchLinux, Chinese, filename, messy, utorrent

晚上看师弟机器上的新版utorrent的界面看起来比我机器上的友好,于是用yaourt utorrent安装了新版的utorrent(aur/utserver 27079-1),安装很顺利,安装完成后修改/etc/conf.d/utserver文件中的以下内容: 将utserver换成我的用户名,然后运行以下命令启动utserver: 然后在浏览器输入地址http://127.0.0.1:8080/gui/,很正常,修改下载目录和临时目录。找了几个种子进行试验,界面能显示中文信息,也能正常下载,下载完成后,发现问题来了:文件名中的中文字符全成了问号(???)?好像很久很久之前也遇到这个问题,但忘了怎么解决,只悔当时没做笔记。 接着,逐步排查问题,先看看utserver的日志文件/var/log/utserver/utserver.log,发现第一行如下所示: 这样原因就很明确了,locale没设置正确,utserver启动后,我期望能看到的第一条日志是下面这样: 有目标就好办了,首先,我尝试在命令行运行utserver,我所期待的结果出现了,进一步确定是运行后台daemon时locale没设置正确,与该问题相关的是/etc/rc.conf配置文件中的两个环境变量: DAEMON_LOCALE="yes" 如果DAEMON_LOCALE设置为“yes”,那么运行daemon时使用LOCALELOCALE为空,使用locale C;如果DAEMON_LOCALE设置为“no”,使用locale C。但是我的/etc/rc.conf配置文件没有问题。 接着我想是不是应该在运行utserver时设置环境变量LANG,于是在/etc/conf.d/utserver文件中添加以下内容: 发现不奏效,最后只能去看/etc/rc.d/utserver这个脚本里的内容,内容不多, 很快就将目标锁定到下面这条命令: 这条命令的作用是切换到$UTSERVER_USER这个用户,利用/bin/sh来运行utserver,那问题就应该出在切换用户后locale没正确设置,于是我将命令改为: su -l -s /bin/sh -c “export LANG=en_US.UTF-8; /usr/bin/utserver $UTSERVER_ARGS >/dev/null 2>&1” $UTSERVER_USER 重新启动utserver,我所期待的结果出现了,至此,问题解决了。 在Linux系统上,出现各种问题是很正常的现象,在这种情况下不要慌,先查看日志,寻找解决之道,也可以上Google搜索已观察到的现象,看看别人是如何解决我们所遇到的问题。

read more »

前提 Hadoop版本:hadoop-0.20.2 概述 在上一篇文章中HDFS源码分析(9):DFSClient初步介绍了HDFS客户端的相关内容,但由于篇幅关系,没有对HDFS的输入/输出流进行介绍,而这正是本文的重点。数据的读取和写入是客户端最重要的功能,也是最主要的逻辑,本文将分成输入和输出两部分对HDFS的文件流进行分析。主要的类位于org.apache.hadoop.hdfs.DFSClient类中。 DFSInputStream DFSInputStream的主要功能是向namenode获取块信息,并且从datanode读取数据,但涉及到的问题也不少:一个文件被分割成多个块,每个块可能存储在不同的datanode;如果一个datanode挂了,要尝试另一个datanode;文件损坏了……因此,我们必须仔细地进行分析,那么,当要在客户端添加或修改功能时才不至于无从下手。 先来看看类图,从总体上把握类之间的关系,由于类比较多,所以略去了不少类,只剩下一些重要的类,因此下面的类图并不完整: DataChecksum这个类的说明可见HDFS源码分析(5):datanode数据块的读与写。 1. FSInputChecker FSInputChecker是一个通用的输入流,继承FSInputStream,用于在返回数据给用户之前校验数据checksum。关键的属性有如下这些: file:读取的数据所在的文件 buf:数据缓冲区 checkum:checksum缓冲区 pos:数据缓冲区的当前位置 count:数据缓冲区中数据的长度 chunkPos:输入流的位置 为了做得更通用,有两个与具体的实现细节相关的抽象方法将由子类去实现: readChunk: 从文件中读取一个chunk放到数据缓冲区,并把该chunk的checksum放到checksum缓冲区 getChunkPosition:得到包含位置pos的chunk的起始位置 剩下的比较重要的操作有read、skip和seek。 read操作有两种方式:一种是一次只读取一个字节,只需要从缓冲区中读出一个字节即可,如果缓冲区空了,就从输入流中读取一批数据到缓冲区;一种是一次读取多个字节,并把数据存到用户缓冲区,会重复调用更底层的读取方法来读取尽可能多的数据。 无论是使用哪种方式的read方法,都会调用readChecksumChunk这个方法。readChecksumChunk方法又会进一步调用readChunk来从输入流中读出chunk和checksum,如果需要,可以对checksum进行验证,如果读数据失败,可以尝试另一副本,重新读取数据。 skip操作会从输入流中跳过和忽略指定数量的字节,在实现上调用了seek操作。 如果seek的位置所在的chunk在当前缓冲区内,那么只要修改当前的位置pos即可;否则需要重新计算chunkPos,并跳过从chunk起始位置到指定位置之间的数据。 2. BlockReader BlockReader继承FSInputChecker,封装了Client和Datanode之间的连接,知道块的checksum、offset等信息。关键的属性有如下这些: in:数据输入流 checksum: lastChunkOffset:最后一个读取的chunk的偏移量 lastChunkLen:最后一个读取的chunk的长度 lastSeqNo:最后一个packet的编号 startOffset:欲读取数据在块中的偏移量 firstChunkOffset:读取的第一个chunk在块中的偏移量 bytesPerChecksum:chunk的大小 checksumSize:checksum的大小 isLastPacket:是否是最后一个packet BlockReader覆盖了父类的很多方法,但不支持seekToNewSource、seek、getChunkPosition及读取单个字节。 首先,我们来看看如何创建一个新的BlockReader实例,所做的事情其实很简单,只是向datanode请求一个OP_READ_BLOCK操作,如果操作成功,那么创建一个数据输入流并根据返回的数据创建一个DataChecksum实例。 read方法只比FSInputChecker多了一些检查。在读取第一个chunk时,可能需要跳过startOffset之前的一些字节。如果到了块的结尾并且需要验证checksum,要向datanode发送OP_STATUS_CHECKSUM_OK,以确认块未损坏。 skip方法通过读取当前位置到目标位置之间的字节来路过这些数据,而不是调用seek。 好了,只剩下最重要的readChunk方法: 如果到达块结尾,将startOffset置为-1,返回-1 计算新chunk的偏移量 如果前一个包的数据已读取完毕,读取下一个packet的头部及checksum 从输入流中读取一个chunk,多缓冲区中读出该chunk的checksum 如果当前packet是最后一个并且当前packet的数据已全部读完,将gotEOS置为true,标志着到达块结尾 3. DFSInputStream 经过前面的预热,我们可以正式进入输入流的主题,DFSInputStream从文件中读取数据,在必要时与namenode和不同的datanode协商。关键的属性有如下这些: closed:流是否已关闭 src:文件 prefetchSize:从namenode预取数据的大小,默认是10个块,可以通过配置项dfs.read.prefetch.size来设置 blockReader:用于读取块的数据 verifyChecksum:是否验证数据的checksum locatedBlocks:存储块的信息 currentNode:当前读取数据的datanode

read more »
July 26, 2012 / DFSClient, Hadoop, HDFS

前提 Hadoop版本:hadoop-0.20.2 概述 在上一篇文章中HDFS源码分析(8):FileSystem已对Hadoop的文件系统接口进行了简单的介绍,相信读者也能猜到HDFS会对外提供什么样的接口。为了让读者对HDFS有个总体的把握,本文将对DistributedFileSystem和DFSClient进行分析,这两个类都位于包org.apache.hadoop.hdfs下。 好了,废话不多说,真奔主题吧。 DistributedFileSystem DistributedFileSystem是用于DFS系统的抽象文件系统的实现,继承自FileSystem,用户在使用HDFS时,所使用的文件系统就是该实现。但是DistributedFileSystem的实现并不复杂,没有过多的逻辑,大部分方法会间接调用DFSClient的方法,使DFSClient能兼容Hadoop的FileSystem接口,从而能在Hadoop系统中工作,这不就是设计模式中的Adapter(适配器)模式吗? 我们先来看看与DistributedFileSystem相关的类图,由于涉及到的类繁多,因此只列出关键类的属性和方法,其它的类只有类名: 从上图可以看出依赖或关联的类基本是HDFS中通用的类和org.apache.hadoop.fs包下的与文件系统相关的类,DistributedFileSystem的大部分方法会调用DFSClien对应的方法,待下方分析DFSClient时再进行介绍。 先来看看类的初始,在静态初始化块中加载了hdfs-default.xml和hdfs-site.xml配置文件,其中包含了namenode的信息以及一些与HDFS相关的参数;在初始化对象时,从uri中得到namenode地址,设置默认工作目录为用户目录。 有三个方法频繁被其它方法调用: checkPath,检查路径的scheme、port和authority,允许显式指定默认端口的路径; makeQualified,归一化显式指定默认端口的路径; getPathName,检查路径的合法性,并将相对路径转换成绝对路径。 DFSClient DFSClient是一个真正实现了客户端功能的类,它能够连接到一个Hadoop文件系统并执行基本的文件任务。它使用ClientProtocol来和NameNode通信,并且使用Socket直接连接到DataNode来完成块数据的读/写。Hadoop 用户应该得到一个DistributedFileSystem实例,该实现使用了DFSClient来处理文件系统任务,而不是直接使用DFSClient。 我们先来看看与DFSClient相关的类图,由于涉及到的类繁多,因此只列出关键类的属性和方法,其它的类只有类名: 看着上图这么多类,一下子就没有头绪,先来看看DFSClient一些重要的属性: MAX_BLOCK_ACQUIRE_FAILURES:块最大请求失败次数,值为3 TCP_WINDOW_SIZE:TCP窗口的大小,值为128KB,在seek操作中会用到,假如目标位置在当前块内及在当前位置之后,并且与当前位置的距离不超过TCP_WINDOW_SIZE,那么这些数据很可能在TCP缓冲区中,只需要通过读取操作来跳过这些数据 rpcNamenode:通过建立一个RPC代理来和namenode通信 namenode:在rcpNamenode基础上封装了一个Retry代理,添加了一些RetryPolicy leasechecker:租约管理,用于管理正被写入的文件输出流 defaultBlockSize:块大小,默认是64MB defaultReplication:副本数,默认是3 socketTimeout:socket超时时间,默认是60秒 datanodeWriteTimeout:datanode写超时时间,默认是480秒 writePacketSize:写数据时,一个packet的大小,默认是64KB maxBlockAcquireFailures:块最大请求失败次数,默认是3,主要用于向datanode请求块时,失败了可以重试 DSClient的属性主要是在初始化对象时设置,其中涉及到几个参数,如下所示: dfs.socket.timeout:读超时 dfs.datanode.socket.write.timeout:写超时 dfs.write.packet.size:一个的packet大小 dfs.client.max.block.acquire.failures:块最大请求失败次数 mapred.task.id:map reduce的ID,如果不为空,clientName设置为“DFSClient_”,否则clientName设置为“DFSClient_” dfs.block.size:块大小 dfs.replication:副本数 接下来,可以来看看DFSClient的方法,笔者发现很多方法是通过RPC调namenode的方法,这些方法不需赘述了,相信读者都能看出要实现什么操作,下面着重说一下部分方法: checkOpen:这个方法被频繁调用,但过程很简单,只是检查一下clientRunning的值 getBlockLocations:由于从namenode得到的所有块以LocatedBlocks来描述,那么需要从LocatedBlocks从提取出每个块及拥有该块的datanode信息,并以BlockLocation来描述每个块,最后返回的是BlockLocation数组 getFileChecksum:得到文件的checksum,过程稍微复杂了一点 得到文件所有块的位置 对于每个块,向datanode请求checksum信息,返回的信息中包括块的所有checksum的MD5摘要,如果向一个datanode请求失败,会向另一datanode请求 将所有块的MD5合并,并计算这些内容的MD5摘要 bestNode:挑选一个不在deadNodes中的节点 HftpFileSystem HftpFileSystem是一种用于通过HTTP方式访问文件系统的协议实现,该实现提供了一个有限的、只读的文件系统接口。 实现时,HftpFileSystem通过打开一个到namenode的HTTP连接来读取数据和元信息,主要支持三种操作: open:向namenode发出http请求,地址是/data/path/to/file,并带有查询串,形式如query1=val1&query2=val2,相信了解http协议的GET方法肯定不觉得陌生 listStatus和getFileStatus:都是向namenode发出http请求,地址是/listPaths/path/to/file getFileChecksum:向namdenode发现http请求,地址是/fileChecksum/path/to/file HftpFileSystem的工作目录是根目录,不能设置根目录,不支持append、create、rename、delete、mkdirs等操作。 还有一个HsftpFileSystem类,继承自HftpFileSystem,通过https与namenode连接,需要建立ssl。 类图如下: 后记 关于文件的输入流和输出流,敬请关注下一篇文章。 文中若有错误或疏漏之处,烦请批评指正。

read more »

 
Older Entries »