├── .gitignore ├── .travis.yml ├── .travis ├── Dockerfile ├── nginx.conf └── travis.enc ├── Dockerfile ├── Makefile ├── README.md ├── _config.yml ├── package.json ├── scaffolds ├── draft.md ├── page.md ├── photo.md └── post.md ├── source ├── .nojekyll ├── 404.md ├── CNAME ├── _posts │ ├── 12-citizens.md │ ├── a-repair-of-the-retina.md │ ├── a-speech-from-mr-zhao.md │ ├── a-world-full-of-malice.md │ ├── annotate-the-web-with-hypothesis.md │ ├── arc-touch-my-new-toy.md │ ├── babun-the-shell.md │ ├── become-creator.md │ ├── better-blogger-worse-product-manager.md │ ├── black-may.md │ ├── bloging-the-docker-way.md │ ├── books-and-movies.md │ ├── buy-from-overseas.md │ ├── capture-linux-login-screen.md │ ├── capture-perf-data-with-aop.md │ ├── ci-your-hexo-blog.md │ ├── deploy-wekan-with-docker.md │ ├── dns-with-os-x.md │ ├── do-not-forget-to-indicate-the-source.md │ ├── docker-on-the-cloud.md │ ├── donate-nice-try.md │ ├── everyone-dies-alone.md │ ├── fastest-first-load-balancer-for-nginx-with-lua.md │ ├── font-of-intellij.md │ ├── free-as-in-freedom.md │ ├── github-and-gitcafe-pages.md │ ├── goodbye-duoshuo.md │ ├── grand-theft-auto-v-a-new-world.md │ ├── guava-basic-utilities-1.md │ ├── guava-basic-utilities-2.md │ ├── guava-basic-utilities-3.md │ ├── guava-basic-utilities-4.md │ ├── guava-functional-programing-1.md │ ├── guava-functional-programing-2.md │ ├── guava-functional-programing-3.md │ ├── ha-deployment-for-blog.md │ ├── handling-301-from-upstream.md │ ├── hexo-filter-asset-inline.md │ ├── hexo-in-the-docker.md │ ├── hexo-ruby-character.md │ ├── i-just-wanna-healthy-life.md │ ├── its-easily-to-be-mouldy-in-lonely-days.md │ ├── load-css-asynchronously.md │ ├── look-back-2014.md │ ├── look-back-2015.md │ ├── loss-of-precision.md │ ├── luit-with-tmux.md │ ├── minimalist-lifestyle.md │ ├── missuse-of-cache.md │ ├── movies-during-national-day.md │ ├── mvn-incremental-compilation.md │ ├── mysql-select-from-update.md │ ├── mysterious-bug-of-hexo.md │ ├── oh-my-giant-atx-777.md │ ├── oh-my-programmer-back.md │ ├── oldman-needs-my-view-of-the-internet.md │ ├── one-year-in-ali.md │ ├── oom-killer-down.md │ ├── ops-with-ssh-batch.md │ ├── oreilly-free-books.md │ ├── oreilly-free-ebooks.md │ ├── own-your-own-shit.md │ ├── paste-without-format.md │ ├── personal-wiki-sucks.md │ ├── play-seo-with-jianshu.md │ ├── poker-ii-and-kindle.md │ ├── polling-and-callback.md │ ├── popular-book-and-banned-book.md │ ├── presentation-with-revealjs.md │ ├── proxy-with-ssh-proxy.md │ ├── pyiconv.md │ ├── recruiting-on-blog.md │ ├── redirect-with-js.md │ ├── remote-debug-python-with-vscode.md │ ├── remote-debug-your-python-code.md │ ├── restore-files-modification-time-in-git.md │ ├── run-ptvsd-as-python-debug-server-with-ease.md │ ├── say-something-before-1111.md │ ├── scalability-and-cost.md │ ├── scoped-css-and-hexo-github.md │ ├── semantic-correct-is-far-more-enough.md │ ├── seven-concurrency-models-threads-and-lock.md │ ├── several-things-during-2016-spring-festical.md │ ├── short-rest-in-70th-anniversary-of-WW2.md │ ├── show-your-favorites-collection-in-hexo.md │ ├── single-dogs-day.md │ ├── smart-crop-another-pdf-crop-tool.md │ ├── smart-crop-how-i-implemented-it.md │ ├── spring-of-artificial-intelligence-again.md │ ├── struggle-at-work.md │ ├── surge-is-a-developer-tool.md │ ├── svn-http-timeout.md │ ├── the-blogs-migration.md │ ├── the-duoshuo-migrator.md │ ├── the-jump-guide.md │ ├── the-national-days-of-2015.md │ ├── the-return-of-the-emacs.md │ ├── time-is-money-friend.md │ ├── timestamp-the-light-app.md │ ├── tmux-static-compile.md │ ├── tools-help-write-blogs-in-english.md │ ├── traffic-shaping-with-token-bucket.md │ ├── trick-of-paging-query.md │ ├── two-years-in-alibaba-xixi-campus.md │ ├── union-find.md │ ├── upgrade-to-el-capitan.md │ ├── url-encoding.md │ ├── velocity-beijing-2015-1.md │ ├── when-i-talk-about-mac.md │ ├── wiki-with-gzip.md │ └── you-are-not-a-real-expert.md ├── about │ └── index.md ├── asset │ └── surge │ │ ├── nat.conf │ │ └── ss.module ├── categories │ └── index.md ├── en │ └── resume │ │ └── index.md ├── favorite │ └── index.md ├── flea │ └── index.md ├── googleb04e35886a5dda4b.html ├── nonsense │ └── index.md ├── resume │ └── index.md ├── slides │ ├── dependency-injection-and-cli-develop-in-java │ │ └── index.html │ ├── index.html │ └── share-your-knowledge-by-blogging │ │ └── index.html ├── tags │ └── index.md └── timeline │ └── index.md └── themes ├── icarus ├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── _config.yml ├── _config.yml.example ├── _config.yml.site.example ├── _source │ ├── categories │ │ └── index.md │ └── tags │ │ └── index.md ├── languages │ ├── en.yml │ ├── id.yml │ └── zh-CN.yml ├── layout │ ├── _partial │ │ ├── after-footer.ejs │ │ ├── archive-post.ejs │ │ ├── archive.ejs │ │ ├── article.ejs │ │ ├── cnzz.ejs │ │ ├── comment.ejs │ │ ├── footer.ejs │ │ ├── github-corner.ejs │ │ ├── google-ads.ejs │ │ ├── google-analytics.ejs │ │ ├── head.ejs │ │ ├── header.ejs │ │ ├── post │ │ │ ├── author.ejs │ │ │ ├── banner.ejs │ │ │ ├── category.ejs │ │ │ ├── cc.ejs │ │ │ ├── comment.ejs │ │ │ ├── date.ejs │ │ │ ├── eof.ejs │ │ │ ├── gallery.ejs │ │ │ ├── highlight.ejs │ │ │ ├── math.ejs │ │ │ ├── nav.ejs │ │ │ ├── pv.ejs │ │ │ ├── source.ejs │ │ │ ├── tag.ejs │ │ │ ├── thumbnail.ejs │ │ │ ├── title.ejs │ │ │ └── wechatpp.ejs │ │ ├── profile.ejs │ │ └── sidebar.ejs │ ├── _widget │ │ ├── announce.ejs │ │ ├── archive.ejs │ │ ├── category.ejs │ │ ├── google-ads.ejs │ │ ├── links.ejs │ │ ├── recent_posts.ejs │ │ ├── tag.ejs │ │ └── tagcloud.ejs │ ├── archive.ejs │ ├── categories.ejs │ ├── category.ejs │ ├── index.ejs │ ├── layout.ejs │ ├── page.ejs │ ├── post.ejs │ ├── tag.ejs │ └── tags.ejs ├── package.json ├── scripts │ ├── fancybox.js │ ├── image-stream.js │ ├── moegirl-template.js │ ├── recruit.js │ └── timeline.js └── source │ ├── css │ ├── _extend.styl │ ├── _partial │ │ ├── archive.styl │ │ ├── article.styl │ │ ├── comment.styl │ │ ├── footer.styl │ │ ├── header.styl │ │ ├── highlight.styl │ │ ├── mobile.styl │ │ ├── profile.styl │ │ └── sidebar.styl │ ├── _util │ │ ├── grid.styl │ │ └── mixin.styl │ ├── _variables.styl │ ├── custom.styl │ ├── images │ │ ├── avatar.png │ │ ├── logo.png │ │ └── thumb-default-small.png │ └── style.styl │ ├── icons │ ├── android-chrome-192x192.png │ ├── apple-touch-icon-114x114.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-144x144.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-57x57.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-72x72.png │ ├── apple-touch-icon-76x76.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── largetile.png │ ├── mediumtile.png │ ├── smalltile.png │ └── widetile.png │ └── js │ └── script.js └── mewpassant ├── _config.yml ├── layout ├── _partial │ ├── after_footer.swig │ ├── article.swig │ ├── custom │ │ ├── footer.swig │ │ └── navigation.swig │ ├── footer.swig │ ├── head.swig │ └── header.swig ├── default.swig ├── index.swig ├── page.swig └── post.swig ├── scripts ├── fancybox.js ├── image-stream.js ├── moegirl-template.js └── timeline.js └── source └── stylesheets └── screen.scss /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | db.json 3 | public 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.12" 4 | 5 | sudo: required 6 | 7 | services: 8 | - docker 9 | 10 | env: 11 | global: 12 | - IMAGE_NAME: jamespan/blog 13 | 14 | branches: 15 | only: 16 | - master 17 | 18 | addons: 19 | ssh_known_hosts: 20 | - github.com 21 | 22 | before_install: 23 | - export TZ=Asia/Shanghai 24 | - openssl aes-256-cbc -K $encrypted_3ba5678e770b_key -iv $encrypted_3ba5678e770b_iv -in .travis/travis.enc -out ~/.ssh/id_rsa -d 25 | - chmod 600 ~/.ssh/id_rsa 26 | - eval $(ssh-agent) 27 | - ssh-add ~/.ssh/id_rsa 28 | - git config --global user.name "panjiabang" 29 | - git config --global user.email panjiabang@gmail.com 30 | 31 | install: 32 | - npm install --production 33 | 34 | script: 35 | - git ls-files | while read file; do touch -d $(git log --date=local -1 --format="@%ct" "$file") "$file"; done 36 | - ./node_modules/hexo/bin/hexo g 37 | - ./node_modules/hexo/bin/hexo d 38 | # - cp .travis/Dockerfile ./Dockerfile 39 | # - cp .travis/nginx.conf ./nginx.conf 40 | # - docker build -t $IMAGE_NAME:latest . 41 | # - docker tag $IMAGE_NAME:latest $IMAGE_NAME:$(date +%Y%m%d%H%M%S) 42 | # - docker images 43 | 44 | # after_success: 45 | # - docker login -e="$DOCKER_EMAIL" -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" 46 | # - docker push $IMAGE_NAME 47 | -------------------------------------------------------------------------------- /.travis/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jamespan/alpine-nginx:latest 2 | 3 | MAINTAINER Pan Jiabang 4 | 5 | # Copy blog content 6 | 7 | COPY ./nginx.conf /etc/nginx/nginx.conf 8 | COPY ./public /usr/share/nginx/html 9 | 10 | EXPOSE 80 11 | 12 | CMD ["nginx", "-g", "daemon off;"] 13 | -------------------------------------------------------------------------------- /.travis/nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes 1; 2 | 3 | events { 4 | worker_connections 1024; 5 | } 6 | 7 | 8 | http { 9 | include mime.types; 10 | default_type application/octet-stream; 11 | 12 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 13 | '$status $body_bytes_sent "$http_referer" ' 14 | '"$http_user_agent" "$http_x_forwarded_for"'; 15 | 16 | access_log /var/log/nginx/access.log main; 17 | 18 | sendfile on; 19 | tcp_nopush on; 20 | tcp_nodelay on; 21 | 22 | keepalive_timeout 65; 23 | 24 | gzip_vary on; 25 | gzip_proxied any; 26 | gzip_comp_level 9; 27 | gzip_buffers 16 8k; 28 | gzip_http_version 1.1; 29 | gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 30 | 31 | 32 | proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=static-page:8m max_size=1000m inactive=600m; 33 | proxy_temp_path off; 34 | 35 | server { 36 | listen 80; 37 | 38 | location / { 39 | root html; 40 | index index.html index.htm; 41 | 42 | proxy_cache static-page; 43 | proxy_cache_valid 24h; 44 | } 45 | 46 | error_page 404 /404.html; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /.travis/travis.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/.travis/travis.enc -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.2 2 | 3 | MAINTAINER Pan Jiabang 4 | 5 | COPY ./package.json /tmp/ 6 | WORKDIR /tmp/ 7 | 8 | # Install Nginx and Node.js env 9 | RUN apk update && \ 10 | apk add nginx && \ 11 | apk add nodejs python make g++ && \ 12 | npm install hexo -g && \ 13 | npm install && \ 14 | apk del make g++ python && \ 15 | rm -rf /var/cache/apk/* && \ 16 | echo "Done" 17 | 18 | # Copy blog source 19 | 20 | COPY ./ /tmp 21 | 22 | RUN hexo generate && \ 23 | cp -a /tmp/public/* /usr/share/nginx/html && \ 24 | #rm -rf ./* && \ 25 | ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log && \ 26 | echo "Done" 27 | 28 | RUN npm un hexo -g && apk del nodejs 29 | RUN rm -rf /tmp/* 30 | 31 | EXPOSE 80 32 | 33 | CMD ["nginx", "-g", "daemon off;"] 34 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | server: 2 | hexo server --draft 3 | 4 | clean: 5 | hexo clean 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/README.md -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hexo-site", 3 | "version": "0.0.0", 4 | "private": true, 5 | "hexo": { 6 | "version": "3.1.1" 7 | }, 8 | "dependencies": { 9 | "hexo": "^3.1.0", 10 | "hexo-deployer-git": "0.0.4", 11 | "hexo-generator-archive": "^0.1.2", 12 | "hexo-generator-category": "^0.1.2", 13 | "hexo-generator-feed": "~1.0.2", 14 | "hexo-generator-index": "^0.1.2", 15 | "hexo-generator-sitemap": "~1.0.1", 16 | "hexo-generator-tag": "^0.1.1", 17 | "hexo-github": "~1.0.1", 18 | "hexo-renderer-ejs": "^0.1.0", 19 | "hexo-renderer-markdown-it": "~3.3.1", 20 | "hexo-renderer-stylus": "^0.2.0", 21 | "hexo-ruby-character": "^1.0.6", 22 | "hexo-filter-indicate-the-source": "1.0.2", 23 | "hexo-server": "^0.1.2" 24 | }, 25 | "devDependencies": { 26 | "hexo-browsersync": "^0.2.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scaffolds/draft.md: -------------------------------------------------------------------------------- 1 | title: {{ title }} 2 | tags: 3 | - Tool 4 | categories: 5 | - Study 6 | 7 | cc: false 8 | comments: false 9 | 10 | --- 11 | -------------------------------------------------------------------------------- /scaffolds/page.md: -------------------------------------------------------------------------------- 1 | title: {{ title }} 2 | date: {{ date }} 3 | --- 4 | -------------------------------------------------------------------------------- /scaffolds/photo.md: -------------------------------------------------------------------------------- 1 | layout: {{ layout }} 2 | title: {{ title }} 3 | date: {{ date }} 4 | tags: 5 | --- 6 | -------------------------------------------------------------------------------- /scaffolds/post.md: -------------------------------------------------------------------------------- 1 | title: {{ title }} 2 | date: {{ date }} 3 | --- 4 | -------------------------------------------------------------------------------- /source/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/source/.nojekyll -------------------------------------------------------------------------------- /source/404.md: -------------------------------------------------------------------------------- 1 | title: "页面消失在了次元的彼岸" 2 | #date: 2015-05-15 10:46:03 3 | meta: false 4 | --- 5 | 6 | ![](//i.imgur.com/EVO3yni.jpg) 7 | -------------------------------------------------------------------------------- /source/CNAME: -------------------------------------------------------------------------------- 1 | blog-archive.jamespan.me 2 | -------------------------------------------------------------------------------- /source/_posts/12-citizens.md: -------------------------------------------------------------------------------- 1 | title: 由「十二公民」引发的思考 2 | tags: 3 | - Thinking 4 | - Movie 5 | categories: 6 | - Life 7 | thumbnail: 'https://ws4.sinaimg.cn/small/e724cbefgw1ewp5guc21sj20rs0ijta9.jpg' 8 | cc: true 9 | comments: true 10 | date: 2015-10-04 15:48:57 11 | --- 12 | 13 | 昨天我看了一部电影,「十二公民」。这部电影折射了中国当下的社会现实,以及部分国民(说的就是我)对于公民素养的缺失,是二十多年来唯一一让我看得无地自容的电影。 14 | 15 | 最近几年,我们从各个渠道渐渐也了解到欧美法中大名鼎鼎的「陪审团」制度,并认为这是民主法治的外在体现。因为中国现阶段并不存在类似英美法的「陪审团」,影片虚构了一个所谓的「家长陪审团」,并且背景是法律大学的英美法补考。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | 补考,一个让人五味杂陈的词!可怜的是我本科四年,挂了许多科,却连补考的机会都没有,直接重修。2015 年 10 月 3 日,是天津大学 120 周年校庆的日子,我作为一个被遗弃的学渣,身处荒山野岭,遥祝天大安好,早日实现「培养卓越工程师」的远大理想。 22 | 23 | 假如当下的中国真的实施了类似于英美法的陪审团,会不会成为一场灾难? 24 | 25 | 在我的印象中,陪审团团员在参与陪审之前,必须对案情毫无知情,不能接受来自媒体等各个渠道的关于案件的信息,只能根据控辩双方的陈词以及证物做出推断。这种做法似乎是为了避免先入为主的思维陷阱。而在「十二公民」中,「陪审团成员」各个都深受媒体舆论的影响,也许正是这个原因,成就了一开场就 11:1 要投死富二代的局面。 26 | 27 | 成为陪审团成员,似乎也是公民义务之一,如果成为那个被选中的孩子,又在没有合理解释的情况下缺席陪审,是要被关小黑屋的[^1]。不过这个义务似乎是个苦差事,不少人会尽力逃避这个义务[^2],如果一开始被选中后来又成功逃脱了,同事们还会弹冠相庆。 28 | 29 | [^1]: [我在洛杉矶被选中当陪审员的经历][2] 30 | [^2]: [逃避美国的陪审团义务][1] 31 | 32 | 当然能最终进入陪审团的人,不会像电影里面这样三教九流,控辩双方的律师都会为了自己的诉讼与声誉,精心挑选那些合适的陪审成员。整个过程仿佛 Dota CaptainMode 里面的 Bans,把那些可能威胁到自己诉讼的家伙踢出陪审团,却不能选那些对自己有帮助的陪审团员,只能 Random 一个。因为就算选了一个能帮到自己的,也会马上被对方踢掉。 33 | 34 | 经过这样一轮一轮的踢人,最后得到一个控辩双方都认可的陪审团。经过这样的挑选,「十二公民」中的「家长陪审团」,还能剩下几个?有偏见(种族歧视、地域歧视、仇富)、没有主见的全都被踢出去,有着检察官背景的 8 号先生也会被踢出去,只剩下地产商、医生,然后全剧终😂。 35 | 36 | 吐槽完电影假设的不合理,我们看看电影讽刺了哪些社会现象。 37 | 38 | 1. 财富原罪假设。一个农民,十年,十亿,这些条件就能得出「干了违法乱纪的事」。我相信衡量一个人的价值的标准之一,是看他合法创造了多少社会财富。 39 | 40 | 2. 外来人口歧视。大城市的土著看不起外来人口,开口闭口「某地的二道贩子」。把城市发展阵痛的锅强行甩给外来人口。 41 | 42 | 3. 血统论。龙生龙,凤生凤,封建遗毒。老子英雄儿好汉,老子反动儿混蛋,文革遗毒。长者曾说,「一个人的命运啊,当然要靠自我奋斗,但是也要考虑到历史的行程」。血统论不过是一个开历史倒车的,无视个人的主观能动性的,注定被刻在耻辱柱上的过气论点罢了。 43 | 44 | 4. 群众对「刑事诉讼举证责任」缺乏了解,思维还停留在那种「官老爷说你有罪,如果你拿不出强有力的证明自己无罪的证据,你就有罪」的那种野蛮残酷的封建时代。现代中国的法律是「谁主张,谁举证」,控方(检察院)声称某人有罪,需要提供证据,如果证据不完备则败诉[^3]。辩方拿出证据证明自己无罪,不是法律义务,而是辩护权利。 45 | 46 | [^3]: [李汉昌, 刘田玉. 统一的诉讼举证责任[J]. 法学研究, 2005, 2.][3] 47 | 48 | 5. 家庭成员关系,特别是长辈与晚辈的关系。晚辈尊敬长辈,而不是敬畏长辈。尊敬也不是无条件的,长辈应该作为晚辈的楷模而被尊敬,用的是人格魅力而非暴力,倚老卖老的人不会得到尊敬。 49 | 50 | 6. 为了孩子。多少家长把为了孩子挂在嘴边,好让孩子产生愧疚,进而控制孩子的选择。为了孩子,一切为了孩子,恐怕是一个又一个悲剧的开始。 51 | 52 | 7. 不会就事论事讨论,擅长人身攻击,外厉内荏地试图占据道德制高点。 53 | 54 | 当然电影中各种各样的讽刺太多了,远远不止上面列举的几条,边回顾影片边写文字都让我有一中不胜枚举的感觉,只好放弃了。 55 | 56 | 看电影的时候,面对影片中一个个丑恶的嘴脸,不由得反思自己在生活中,是不是也像这些丑恶的人一样,让人生厌。 57 | 58 | 「可恨之人,必有可怜之处」,这是大多数电影在刻画坏人的时候的常用手段,「十二公民」也不例外。在快结束的时候,通过人物自白来为 3 号先生强行洗白,手法是俗套的「可怜天下父母心」。或许这能戳中许多人的泪点,但是戳中泪点又如何呢? 59 | 60 | 使用错误的教育方式,很可能就会导致意外的教育结果,盲目遵循上一辈的教育方式,就会在日新月异的时代里不合时宜,在这种教育环境下成长起来的孩子,很可能在新的社会环境中寸步难行。在教育上不使用科学的方法,食古不化,盲从祖训,孩子长大之后的各种疏远,各种所谓的叛逆,只不过是自食其果罢了,这不是一句「可怜天下父母心」能够解的开的结。 61 | 62 | 总的来说,这是一部好电影,虽然故事背景的设定有些牵强,最后的强行洗白十分无趣,但是我认为这是一部好电影,能够让人自我批评,然后变得更好的电影。 63 | 64 | [1]: http://zh.wikihow.com/逃避美国的陪审团义务 65 | [2]: http://www.sinotimes.com/480/up_art/p21.htm 66 | [3]: http://jpkc.znufe.edu.cn/2006/fxy/msssfx/images/%CD%B3%D2%BB%B5%C4%CB%DF%CB%CF%BE%D9%D6%A4%D4%F0%C8%CE.pdf 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /source/_posts/a-speech-from-mr-zhao.md: -------------------------------------------------------------------------------- 1 | title: "赵海平分享小记——关于 Facebook,关于 Alibaba" 2 | date: 2015-04-19 23:19:11 3 | tags: 4 | - Speech 5 | categories: 6 | - Work 7 | cc: true 8 | comments: true 9 | --- 10 | 11 | 2015 年 4 月 7 日晚上,离开 Facebook 加入 Alibaba 的赵海平先生,在阿里巴巴的总部,进行了一次题为《我眼中的 Facebook 技术演进》分享,关于 Facebook 的技术演进。 12 | 13 | 分享原定 6:30 开始,内网上报名参加的人数接近 1500,害怕报告厅装不下如此多人,我和同事 6:15 便到了会场,挑选了前排位置坐下。 14 | 15 | 16 | 17 | {% recruit %} 18 | 19 | 一开始,大概在 2004 年,Facebook 就是一个单纯的 LAMP 架构的小网站,用户信息保存在一张名为 info 的表里面。 20 | 21 | 后来随着用户数量的增加,单库单表没法满足存储的需求,大约在 2006 年,Facebook 开始按照学校或者用户 id 把用户的数据路由到不同的数据库去存储,那时候大家都用一个 id2db 函数去获取从 用户到数据库的映射。 22 | 23 | 久而久之这个函数就变得复杂无比,难以维护。主程序是用 PHP 写的,其他语言又没法直接调用 PHP 的函数,赵海平先生当时使用的是 C++,只好自己实现了一遍,当 PHP 的函数有变化时,其他语言版本的 id2db 只能人肉跟进。 24 | 25 | 再后来数据库抗不住了,连接数超出了 MySQL 的承受范围,于是 Memcached 出场了,直接把 MySQL 从应用服务器手上救了下来。Memcached 的查询非常快,大概 0.5ms 就能返回查询结果,从此网络进入毫秒时代。 26 | 27 | 接下来的几年,同步 IO 劣势凸显,异步 IO 大展宏图,以 libevent 为首的异步处理,将网络程序带入了异步时代。从那时起,Facebook 中越来越多的新代码使用 libevent 做异步 IO,老代码也渐渐被重构。和线程模型相比,libevent 所代表的事件驱动模型,更加适合互联网环境下高 IO 的场景。 28 | 29 | 大约在 2007 年,Facebook 搞了个开放平台,弄了一套 FBML、FBCSS 和 FBJS。一开始的时候,这三样东西是用 PHP 实现的,结果运行效率成了大问题,几乎不可用。赵海平先生直接用 C++ 重写,速度提高几十倍。 30 | 31 | 那时候赵海平先生还顺便弄了 XHProfLive,一个实时收集、剖析 PHP 程序的运行状况、速度、消耗等等。他认为功能、测试和监控是程序开发的三套车,大部分的开发人员写功能很厉害,单元测试写的也还行,到了监控上就基本不怎么样了。 32 | 33 | 为了让网页响应更快,Facebook 把一些和渲染网页无关的工作异步化了,在 PHP 语言中增加了一些黑科技,比如 “Post-Send Processing”,在页面返回之后处理一些发消息、cleanUp 等任务,还有 “Async Tier” 用于做 PHP 的函数延迟、重试、多机化等等。 34 | 35 | 到了 2008 年,Facebook 的机器开始出现 CPU 负载较高的问题,这种已经是 PHP 语言层面的问题了,那时候赵海平先生开始做 HipHop 的相关工作,就是把 PHP 翻译成 C++,然后编译执行。 36 | 37 | 那时候它不是吃定了这个项目,有一个同事在和他竞争,那个同事借助商业软件,把 PHP 翻译成 Java。最终竞争的结果是赵海平胜出了。 38 | 39 | 2011 年,Hadoop 进入 Facebook 的技术栈,大数据处理开始火热,Facebook 把它的日志全都记录在了 Hadoop 上,因为 Hadoop 天生擅长处理大量的顺序写。 40 | 41 | 2014 年,Facebook 搞出了著名的 HHVM,一个 PHP 的 JIT 虚拟机,用于取代之前的 HipHop。然而 HHVM 并没有带来比 HipHop 高出许多的性能提升,原因是 GCC 本身的代码优化已经足够强大了,能够把 HipHop 生成的不优化的 C++ 代码优化成高效的机器码,JIT 也不是万能药,不是用了它代码效率就能飞跃。 42 | 43 | 当然 HHVM 的好处也是有很多的,最大的好处是部署。之前使用 HipHop 编译出来的可执行文件有两个 G,部署都成了大问题。用了 HHVM 之后可以直接部署源文件。 44 | 45 | 最后,赵海平先生提出一个设想:互联网应用的执行过程,无非是从这个地方获取一些数据,从那个地方获取一些数据,对数据稍作加工生成新的数据。这个获取数据的过程以及数据之间的依赖关系可以用一颗树来表达,如果我们能优化这棵树,让能并行的任务并行,尽量少的去获取数据,我们的应用跑的就更快。 46 | 47 | 分享结束之后是问答环节,赵海平先生在这里展示了它的机智和风趣。 48 | 49 | 开始的时候,赵海平先生分享了他为什么加入 Alibaba。到了提问环节,有同事问他什么时候打算离开。赵海平先生机智的说了 Alibaba 目前在技术上的各种不足,然后说,你问我什么时候离开,其实就是再问我解决这些问题要用多长时间。 50 | 51 | 有同事问他对高级技术人员很少写代码的看法,他说他早上才提交了许多代码,整个会场顿时掌声雷动。 52 | 53 | 在他看来,高级技术人员需要为项目负责,最好是能够在项目一开始亲自上阵,为整个项目打下一个良好的框架,其他人在框架上添砖加瓦,这样子整个项目才不会失控。 54 | 55 | 比如 Facebook 在的 HTML5 上遭遇的滑铁卢,就是因为高级技术人员一开始没有亲自上阵,然后 PR 又对外公布了消息,于是大家只好硬着头皮做。如果一开始就有高级人员参与,亲自做个 Demo,谁都能发现 HTML 5 在当时的设备上,没法提供和 Native 接近的体验(似乎到现在都还不行),也就不会选择一种不合适的技术。 56 | 57 | 还有同事问了他那个传说中的 “The Greatest Computer Scientist” 头衔,赵海平先生当即表示他被国内的科技媒体坑惨了。那个根本不是什么头衔,而是他工牌上的字,每个 Facebook 员工都有类似的对自己的期许。 58 | 59 | 还有许多同事问了各种各样的问题,好多我都不记得了。 60 | 61 | 赵海平先生是那种天赋比你高的人比你还努力的典型例子,像我这种天赋平庸的家伙,更要努力才行呀! 62 | 63 | -------------------------------------------------------------------------------- /source/_posts/a-world-full-of-malice.md: -------------------------------------------------------------------------------- 1 | title: 这是一个充满恶意的世界 2 | tags: 3 | - Sketch 4 | categories: [Life, Essay] 5 | cc: true 6 | comments: true 7 | date: 2015-03-28 14:15:25 8 | thumbnail: https://ws4.sinaimg.cn/small/e724cbefgw1et29me8y80j21kw0vxwoq.jpg 9 | --- 10 | 11 | 不知从什么时候开始,起床之后的第一件事就是打开知乎日报看瞎扯。常在河边走,哪有不湿鞋。就在这周三,我一起床就遭遇了强烈的精神攻击,整个人都不好了。 12 | 13 | 14 | ![知乎瞎扯](https://ws1.sinaimg.cn/large/e724cbefgw1et29lq1ighj20hs0eqgn0.jpg) 15 | 16 | 17 | 18 | {% recruit %} 19 | 20 | 尼玛,这是什么鬼啊!我顿时感觉到了来自世界的满满恶意。然后我就想起了不久前在 B 站看过的一个一本正经胡说八道的视频。 21 | 22 |
23 | 24 |
25 | 26 | 作为一个宅男 + 程序员 + 单身狗 + 处女座,我发现我身上集合了各种被黑的元素。黑码农的风潮已经过去,处女座刚被黑完没多久,现在是黑单身狗风头最盛的时候。 27 | 28 | 不知道是不是真的,我反而比较享受现在的状态,能够全身心的投入去做自己喜欢的事情。 29 | 30 | 虽然工作上大多数时候免不了缺少挑战,但是有些时候还是有点意思,用自己的能力让一个能工作却包含各种 ugly hack 的系统一点一点变得更好,不正是能让自诩为软件工程师的码农们感受到自身价值的事情之一么。 31 | 32 | 作为一个宅男,除了写代码之外的娱乐活动就是去哔哩哔哩看看动漫,最近的几部动漫都挺不错的,《[路人女主的养成方法][1]》也刚刚完结。 33 | 34 | ![毁灭吧现充](https://ws4.sinaimg.cn/large/e724cbefgw1et29me8y80j21kw0vxwoq.jpg) 35 | 36 | 集腹黑、黑长直等萌属性于一身的诗羽学姐,有着教科书式的傲娇的英梨梨,还有存在感薄弱的吐槽役加藤惠,都是很萌很萌的女主角。 37 | 38 | ![宅的全力](https://ws4.sinaimg.cn/large/e724cbefgw1et29muwurlj21kw0vu0yz.jpg) 39 | 40 | 路人女主完结了,还是有许多不舍,无论如何,至少失去了每个周五看更新的喜悦。不知道下一次出现这么有趣的新番是什么时候了,未来总是充满了不确定性。 41 | 42 | 不知道从什么时候起,我总是把我看过的觉得不错的动漫和电影下载下来存归档。我有一个 3T 的硬盘,除了用来作为时光机的备份,就是放我各种收集的美剧、电影和动漫。让一个自诩为互联网人士的码农对互联网服务不信任到这种地步,真是不敢想象。 43 | 44 | 前段时间跟一个女同学聊天的时候说到我现在越来越忙,工作的事做完不算,自己还有好多事要做,光是写书写博客就已经把我的业余时间全部占用了,简直就是注孤生的节奏。 45 | 46 | 不知道是真心还是社交辞令,这位同学跟我说,没时间不会注孤生,没本事才会注孤生。也算是让我得到一些安慰吧。 47 | 48 | 前不久我才怂恿她买了一根号称“最好的触控笔”的 [Jot Script][2],然后过了不久,我大四上学期购买的 KEYCOOL 青轴渐渐不能满足我各种姿势写代码的需求了,于是我就买了一个 Filco 的蓝牙键盘,从此我在公司可以后仰到椅子里写代码,在家可以用更加懒散的姿势。 49 | 50 | 不知道是不是我的错觉,我感到 Filco 的键帽手感比 KEYCOOL 的好很多,打字的时候如丝般顺滑。 51 | 52 | ![新玩具](https://ws3.sinaimg.cn/large/e724cbefgw1et29nazl9nj20hs0no41u.jpg) 53 | 54 | 也许就像大部分人没法理解宅男花了许多钱买手办一样,我们这些追求极致编码体验的码农,在电脑和键盘上花了许多钱,外人也是很难理解的。哈哈,该被黑的时候还是被黑,该自嘲的时候就去自嘲,不足为外人道也。 55 | 56 | 写了几个月的博客,现在写博文的速度也是越来越快了,真的是熟能生巧的缘故? 57 | 58 | [1]: http://www.bilibili.com/sp/路人女主的养成方法 59 | [2]: http://www.adonit.net/jot/script/ 60 | 61 | -------------------------------------------------------------------------------- /source/_posts/annotate-the-web-with-hypothesis.md: -------------------------------------------------------------------------------- 1 | title: 用 Hypothes.is 为你喜欢的文字添加评论 2 | tags: 3 | - JavaScript 4 | - Tool 5 | categories: 6 | - Study 7 | cc: true 8 | hljs: true 9 | math: true 10 | comments: true 11 | date: 2015-03-16 02:59:20 12 | --- 13 | 14 | 2015 年 3 月 15 日深夜,我刚从公司回到宿舍。不是加班,是去蹭饭。整整花了一个周末,我才把书的提纲写出来发给编辑。 15 | 16 | 坐在床边落寞的刷着人人,发现网友[@邵成=undefined](http://www.renren.com/480812352/)分享了一个链接,。 17 | 18 | 点进去一看,发现这个果然是一个高贵冷艳的第三方评论系统,可以对网页内容做圈点,对圈点的内容做点评,界面和功能一样的狂拽酷炫。 19 | 20 | 21 | 22 | {% recruit %} 23 | 24 | ![](https://ws4.sinaimg.cn/large/e724cbefgw1eq6zbr8tnlj20yr0l4gpw.jpg) 25 | 26 | Hypothes.is 不同于一般的评论系统。我的博客已经使用了一个叫 “多说” 的第三方评论系统,多说虽然做的不错,但是没有跳出常见的评论系统的桎浩,只能在网页的最下方,正文之后做评论。Hypothes.is 的做法相当于给网页添加了一个图层,用户可以在这个图层上对网页做评论,这样子就把一个平面的网页给立体化起来了。 27 | 28 | 下面这个是一个介绍的动画。 29 | 30 | 31 | 32 | 35 | 36 | 然后是创始人在传教。 37 | 38 |
39 |

Hypothes.is Intro from Hypothes.is on Vimeo.

40 |
41 | 42 | 我们可以轻易地将 Hypothes.is 集成到网站中,只要将下面一段 js 引用添加到页面就好了。 43 | 44 | ```html 45 | 46 | ``` 47 | 48 | Hypothes.is 的效果是显而易见的,网页的右边界出现了一个浮层,点击浮层可以展开评论框。 49 | 50 | 如果你选中一段文字,文字末尾会弹出一个钢笔小图标,点击小图标就会进入 “引用并评论” 模式。 51 | 52 | Hypothes.is 的评论系统做的很不错,支持 Markdown,支持 $\LaTeX{}$ 公式标记,简直不能更赞! 53 | 54 | 对于那些没有使用 Hypothes.is 的网站,我们也是可以添加评论的!Chrome 用户可以下载 Hypothes.is 的浏览器插件,其他浏览器的用户把下面这段代码添加为书签,打开想要评论的网页之后,点击一下书签执行其中的脚本,就可以尽情的评论了。 55 | 56 | ```js 57 | javascript:(function(){window.hypothesisConfig=function(){return{showHighlights:true};};var%20d=document,s=d.createElement('script');s.setAttribute('src','https://hypothes.is/app/embed.js');d.body.appendChild(s)})(); 58 | ``` 59 | 60 | 需要注意的是,用 Hypothes.is “引用并评论” 的地方,会给那段被选中的文字加上 span 标签。对于设计良好的网站,这是没有问题的,要是碰上那些给 span 加了样式的网站,就有可能出现样式崩坏。 61 | 62 | 63 | 最后,祝大家评 (tŭ) 论 (cáo)愉快~ 64 | 65 | -------------------------------------------------------------------------------- /source/_posts/arc-touch-my-new-toy.md: -------------------------------------------------------------------------------- 1 | title: Arc Touch BlueTooth,我的新玩具 2 | tags: 3 | - Device 4 | - OS X 5 | categories: 6 | - Life 7 | thumbnail: 'https://ws4.sinaimg.cn/small/e724cbefgw1ev3ft15d9cj20qo0hr7b9.jpg' 8 | cc: true 9 | comments: true 10 | date: 2015-08-15 18:08:02 11 | --- 12 | 13 | 14 | 一直想要拥有一枚蓝牙鼠标,特别是在我拥有了一台蓝牙机械键盘之后。 15 | 16 | 考虑到我是 Mac 用户,在蓝牙鼠标的选择上,默认选项应该是 Apple Magic Mouse。这款鼠标不仅血统纯正,而且逼格之高简直突破天际。然而我有更多的考虑。 17 | 18 | 19 | 20 | {% recruit %} 21 | 22 | 首先是实际的使用体验。触摸鼠标、多指触控等等优秀的体验,对于大多数人来说,使用的时候爽得飞起,但是对于一小群手心手指容易出汗的人来说,使用体验简直就是灾难。也正因为如此,当年我使用 Android 手机的时候,一个必不可少的条件就是支持“湿手触摸”。 23 | 24 | 出于对自身缺陷的考虑,我还是决定对 Magic Mouse 敬而远之。一番搜索之后,找到了 M$ 出品的一款鼠标,[Arc Touch Bluetooth][1]。 25 | 26 | 我对微软的鼠标是早有切身体会,从早期的经典之作 IE 3.0,到后来的折叠鼠标 Arc Mouse,我都有用过或者试用过,只是后来着了灯厂的道,才在大学之后基本一直在用雷蛇的鼠标。 27 | 28 | 虽然 Arc Touch Bluetooth 表面上写着仅支持 M$ Windows 8.1 之类的系统,但是网上其他文章表明,这款鼠标是可以连接 Mac 使用的[^1]。于是我在京东下单来一发,第二天就到了。 29 | 30 | [^1]: [张弛有度 — 微软 Arc Touch 蓝牙鼠标][2] 31 | 32 | 33 | 值得一提的是,下班之后回家之前,我更新了操作系统,升级到 OS X 10.10.5。 34 | 35 | 第二天拿到鼠标之后,有些小激动。 36 | 37 | ![鼠标外包装](https://ws3.sinaimg.cn/mw1024/e724cbefgw1ev3cfyt58tj21kw1kwwyo.jpg) 38 | 39 | 打开包装之后,里面的鼠标和想象中的一模一样,对我来说,no surprise 就是坠吼的。 40 | 41 | ![鼠标开箱](https://ws4.sinaimg.cn/mw1024/e724cbefgw1ev3cp4awizj21kw1kw4k3.jpg) 42 | 43 | 鼠标的使用过程当然不会是一帆风顺,在蓝牙配对上就遇到了困难。 44 | 45 | 按照说明书的步骤开始配对之后,不知道是不是鼠标的存在感太薄弱,电脑一直无法发现它的存在。各种折腾无果之后,开始向 Google 求助,发现 Apple 的论坛上似乎有相关内容[^2]。 46 | 47 | [^2]:[Since upgrading to Yosemite my Apple Bluetooth Mouse ...][3] 48 | 49 | 然并卵,按照帖子里的操作流程甚至后面给出的链接里面的操作把 Bluetooth PAN 删除之后并重启,也没法在附件的蓝牙设备中发现鼠标。 50 | 51 | 各种尝试无果之后,我开始考虑是应该退货,还是留着等待奇迹,或许机缘巧合之下我也有能在 Mac 上用上它的一天。 52 | 53 | 没想到的是,这一天来得这么快。 54 | 55 | 我拿起刚才一直没有开启的蓝牙键盘,准备写点东西,惊奇地发现电脑没法识别键盘的输入了。从蓝牙设备列表中删除了键盘之后,再次开启配对也没法找到键盘,这场景多么的熟悉,刚才配对鼠标的时候不就是这样么。这时候的心情,既开心又担心,开心的是或许我可以不用把鼠标退回去了,担心的是系统升级引入了 bug,让我连键盘都用不了。 56 | 57 | 再次求助于 Google 之后发现,我不是一个人!有人遇到了类似的问题[^3],然后在 MacX 的论坛提问了。 58 | 59 | [^3]: [10.10.5 系统更新后蓝牙不能使用了][4] 60 | 61 | 最终解决问题的过程也是异常的简单,关机,然后在启动的同时按住 Command-Option-P-R 来还原 NVRAM/参数 RAM 设置,然后就可以完成蓝牙设备的配对了。 62 | 63 | 知乎上面有关于这个组合键的讨论[^4],看得我云里雾里的。虽然不知道为什么,但是至少把蓝牙给弄好了~ 64 | 65 | [^4]: [Mac开机时按住Command+Option+P+R 键,重置Pram和Nvram...][5] 66 | 67 | 总体来说呢,Arc Touch Bluetooth 这款鼠标在手感和灵敏度精确度等等指标上,跟灯厂的鼠标那是相差了十万八千里,但是作为一款便携的蓝牙鼠标,那是相当的赞,也十分贴合它移动办公的定位。 68 | 69 | 这款鼠标很有意思,能屈能伸的,掰弯开机,掰直关机,想必会深受腐女们的喜爱~ 70 | 71 | Arc Touch Bluetooth,你值得拥有! 72 | 73 | [1]: https://www.microsoft.com/hardware/zh-cn/p/arc-touch-bluetooth-mouse 74 | [2]: http://www.dgtle.com/article-8346-1.html 75 | [3]: https://discussions.apple.com/thread/6778301 76 | [4]: http://www.macx.cn/thread-2168754-1-1.html 77 | [5]: http://www.zhihu.com/question/20401972 78 | -------------------------------------------------------------------------------- /source/_posts/become-creator.md: -------------------------------------------------------------------------------- 1 | title: "欢迎来到创作者的世界,安艺伦也君" 2 | date: 2015-04-26 00:38:58 3 | tags: 4 | - Sketch 5 | categories: [Life, Record] 6 | cc: true 7 | comments: true 8 | thumbnail: https://ws3.sinaimg.cn/small/e724cbefgw1eri9t9fhemj20uq0ha0v5.jpg 9 | --- 10 | 11 | 12 | 今天终于把约稿合同给策划大大寄回去了,拖了整整三周。 13 | 14 | 一开始我收到合同的时候,迟迟不敢签约。那段时间状态突然变得很差,感觉工作都做不好了,整整用了两个星期才调整回来。 15 | 16 | 在状态不好的那两个周末,我看完了《[樱花庄的宠物女孩][1]》,然后又一遍一遍地看《[路人女主的养成方法][2]》。 17 | 18 | 19 | 20 | {% recruit %} 21 | 22 | ![](https://ws3.sinaimg.cn/large/e724cbefgw1eri9t9fhemj20uq0ha0v5.jpg) 23 | 24 | 诗羽学姐的那句“欢迎来到创作者的世界,安艺伦也君”,当初追新番第一次看到的时候就让我迷の感动,直到现在,这句话还一直萦绕在我的脑海。 25 | 26 | ![](https://ws2.sinaimg.cn/large/e724cbefgw1eri9tnbghcj20uq0hadhl.jpg) 27 | 28 | 在第 3 话《[高潮部分要重拍][3]》中,伦也在企划书上毫无进展的时候,诗羽学姐和安艺伦也之间展开了一段关于创作者和消费猪的对话,挺有意思的。 29 | 30 | 47 | 48 | 接下来的大半年时间,对我而言可能就像进入了修罗场。入职快一年了,工作能力有了长足的进步,年度绩效也算是很不错,接下来的一年会承担更多的责任。业余时间估计会全部奉献给书籍写作,不再像现在写博客一样自由自在随意挥洒,博客更新也许会陷入停滞。 49 | 50 | 说到写作这件事,其实我是不自信的。不过既然签了合同,就尽力做好吧,虽然说不能按时交付原稿的话,代价不小,但还是可以承受的,要是违约金再高一些的话我还真不敢签了。 51 | 52 | 同样是宅男,同样是博主,我却不像伦也那么幸运能有诗羽学姐在身边。我只能自己对自己说,欢迎加入创作者的世界! 53 | 54 | 55 | [1]: http://www.bilibili.com/sp/樱花庄的宠物女孩 56 | [2]: http://www.bilibili.com/sp/路人女主的养成方法 57 | [3]: http://www.bilibili.com/video/av1938297/ 58 | -------------------------------------------------------------------------------- /source/_posts/better-blogger-worse-product-manager.md: -------------------------------------------------------------------------------- 1 | title: 提防那些 Blog 写得好的产品经理 2 | tags: 3 | - Thinking 4 | categories: 5 | - Life 6 | math: true 7 | thumbnail: //i.imgur.com/6V8npB7.jpg 8 | cc: true 9 | comments: true 10 | date: 2016-01-30 11:43:25 11 | --- 12 | 13 | {% blockquote @Fenng http://weibo.com/1577826897/DflYM05Vo %} 14 | 小龙哥饭否语录一出,天下产品经理从此歇笔不再写 Blog… 15 | {% endblockquote %} 16 | 17 | 最近张小龙再次火了起来,一开始是微信公开课上,张小龙分享了它的产品理念,后来是他多年之前的饭否被挖了出来,被捧为为产品经理箴言。 18 | 19 | 20 | 21 | {% recruit %} 22 | 23 | 前日深夜,一位任职产品经理的朋友从微信给我转发了一张截图,大意是说,博客写得好的产品经理都不靠谱。 24 | 25 | ![](//i.imgur.com/7sGmMQb.png) 26 | 27 | 昨晚我未能免俗,注册了饭否,连夜完整翻阅了 [@gzallen][1] 的 2351 条消息。 28 | 29 | ![](//i.imgur.com/5zakMOR.png) 30 | 31 | 就是这条饭否消息,让天下产品经理从此歇笔不再写 Blog!哈哈大笑之余,总感觉有点怪怪的,一定是哪里出了问题。 32 | 33 | 于是我尝试把这个推论翻译成谓词逻辑。 34 | 35 | 在 Blog 上花的时间越多,在产品上花的时间就越少,无一例外。在产品上花时间越少的产品经理越要被提防。 36 | 37 | $$ 38 | \forall pm (SpendMuchTime(pm, Blog) \rightarrow SpendLessTime(pm, Product)) 39 | \\\\ 40 | \forall pm (SpendLessTime(pm, Product) \rightarrow BetterBeBewareOf(pm)) 41 | $$ 42 | 43 | 当初在人工智能课程上,跟随教授重温逻辑的时候,他就告诫我们说不要把逻辑学应用在生活中,因为大部分的人其实是没有逻辑的。跟没逻辑的人讲逻辑是自讨没趣。 44 | 45 | 我终于还是忍不住破戒了。 46 | 47 | 说得好像在 Blog 上少花时间,就会在 Product 上多花时间似的。在任何非 Product 上多花时间,都会导致在 Product 上少花时间,所以不仅仅是 Blog 写得好的产品经理需要被提防,那些照片拍得好、喜欢旅游、喜欢画画,在产品之外有其他爱好的产品经理都要被提防,他们在业余爱好上花的时间越多,在产品上花的时间就越少。 48 | 49 | $$ 50 | \forall pm (SpendMuchTime(pm, \neg Product) \rightarrow SpendLessTime(pm, Product)) 51 | \\\\ 52 | \forall pm (SpendLessTime(pm, Product) \rightarrow BetterBeBewareOf(pm)) 53 | $$ 54 | 55 | 至于那些从这段话演绎出「靠谱的产品经理不写博客」、「为了不让别人以为我是不靠谱的产品经理我还是不要写博客了」的家伙,他们开脑洞的方式,没逻辑的方式,挺可爱的。 56 | 57 | --- 58 | 59 | 不知何故微信浏览器总是对我的博文做自动重排,严重影响阅读体验。我因为只有个人公众号没法申请认证,也就没法通过配置业务域名来绕过重排,只好在此向各位求助避免微信浏览器对页面做重排版的技术方案,求分享! 60 | 61 | [1]: http://fanfou.com/~RLhcIDBjZAM 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /source/_posts/black-may.md: -------------------------------------------------------------------------------- 1 | title: "中国互联网的黑色五月" 2 | date: 2015-05-30 11:50:10 3 | categories: 4 | - Work 5 | cc: true 6 | comments: true 7 | --- 8 | 9 | 每次看我几个月之前写的代码,都觉得当初写的不是代码而是是一坨翔。一直觉得我迟早要被我刚入职那会写的代码坑到,最近还真的被坑了。 10 | 11 | 一个软件写的是否健壮,不能光看正常流程,还得看看异常流程有没有处理好,容错有没有做好。这一次我就坑在了没有把容错做到位,甚至连 HTML 提供的容错机制都没用上。我为博客里每张图片的 alt 属性添加了内容,偏偏在自己维护的系统的页面上没有做到。 12 | 13 | 14 | 15 | {% recruit %} 16 | 17 | # 五月病 # 18 | 19 | 也许五月病真的存在,天朝的互联网在这个五月,故障频发。先是网易机房的骨干网路被 DDoS 然后直接宕机 5 小时[^1],然后是支付宝机房的电信光纤被挖断然后系统瘫痪了一个半小时[^2],再然后是携程那长达 12 小时的宕机[^3]。 20 | 21 | [^1]: [网易骨干网宕机5小时][1] 22 | [^2]: [局部“宕机”90分钟:支付宝称“光纤被挖断”][2] 23 | [^3]: [携程:网络故障由员工错误操作导致][3] 24 | 25 | 有了这次自己挖坑自己跳的经历,我负责的系统也算是加入“五月俱乐部”了,虽然现在系统体量还不是太大,而且系统主要通过接口提供服务,一次几个小时的页面故障不会引发广泛关注,我还是要吸取前车之鉴。 26 | 27 | # 痛定思痛 # 28 | 29 | 网易宕机之后,互联网上的技术圈子有一些讨论,然后阿里系的工程师们似乎都认为,异地多活一定要做。 30 | 31 | 支付宝故障之后,我一度以为我们引以为豪的异地多活没有生效。后来才知道金融系统和一般的互联网服务不太一样,流量切换的时候会更加谨慎。 32 | 33 | 关于携程,虽然官方的说法是员工错误操作导致,具体原因是人为意外删除了生产服务器上的执行代码[^4],我却不太相信这套说辞。 34 | 35 | [^4]: [携程瘫痪事件确认系员工误操作所致][4] 36 | 37 | 至于我,当然是要把页面的容错做好,把当年挖的坑填上。 38 | 39 | ![神秘的程序员们-9 http://blog.xiqiao.info/2009/12/16/611](https://ws4.sinaimg.cn/large/e724cbefgw1esm3nrwqw5j20fa07f3zz.jpg) 40 | 41 | # 技术与流程 # 42 | 43 | 之前我旁听过一些严重故障的回 (sī) 顾 (bī) 会 (dà) 议 (zhàn),也听过赵海平先生在一次分享中说到的 Facebook 处理故障的方式。最近耗子的一条微博让我想明白了一些事情。 44 | 45 | {% blockquote @左耳朵耗子 http://weibo.com/1401880315/CjZfa1ms4 %} 46 | 技术上出故障是必然的。能否体现一个公司是技术公司,重要看这几点:1)故障的恢复是否有技术含量,2)公司对故障的处理方式,如果是通过加更多的流程,或是通过加更多的权限管控,或是通过处罚犯错误的人,或是上升到员工意识形态上,而不是去用更好的技术来解决,那么这个公司不会是个技术公司。 47 | {% endblockquote %} 48 | 49 | 其实之前我也手黑弄出过几次故障,有大有小。但是我们在思考如何避免问题再次发生的时候,总是倾向于使用管理的手段,添加更多的流程,用更多的人力来试图避免问题。 50 | 51 | 52 | 53 | 这是最好的方式,也是最坏的方式。添加流程确实能减少故障发生的次数,而且立竿见影,但是这也是一种杀敌八百,自损一千的方式。我们做技术的人,都希望能够用技术改变人们做事情的方式,然而大部分时候,却是被流程改变了我们做技术的方式。 54 | 55 | 56 | 57 | 也许我们能做得更好。 58 | 59 | 技术企业的核心价值应该不会是一大堆的流程,而是技术,能够帮助人们提高生产力的技术,或者让人们活的更舒服的技术,或者帮助人们减少 human error 的技术。 60 | 61 | [1]: http://www.chuapp.com/2015/05/12/157529.html 62 | [2]: http://news.xinhuanet.com/fortune/2015-05/27/c_1115430242.htm 63 | [3]: http://tech.163.com/15/0529/07/AQP3OEPD000915BF.html 64 | [4]: http://tech.sina.com.cn/i/2015-05-29/doc-iavxeafs8277124.shtml 65 | -------------------------------------------------------------------------------- /source/_posts/buy-from-overseas.md: -------------------------------------------------------------------------------- 1 | title: Amazon「海外购」初体验 2 | tags: 3 | - Shopping 4 | categories: 5 | - Life 6 | cc: true 7 | thumbnail: //i.imgur.com/x4EuJxRb.jpg 8 | comments: true 9 | date: 2015-11-02 21:39:00 10 | --- 11 | 12 | 13 | 上个月我在卓越亚马逊买了一个运动水壶。最近我只要有时间就会想要去健身房运动,虽然晚上下班回到家健身房都关门了,但是周末两天还是可以去吭哧吭哧几个小时。 14 | 15 | 突然发现自己需要一个水壶,于是我就开始在网上搜寻。已经许久不在淘系电商上购物了,我直接去 Amazon 上找目标,然后被它的「海外购」的条幅广告吸引了。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | 淘系电商一直在尝试各种海淘模式,但是个人感觉其目标群体是女性用户,主要是美妆、奶粉之类的东西,让我毫无兴趣。Amazon 的海外购的类目还是比较广泛的,在里面直接搜索「运动水壶」,就找到了让我心仪的目标,一个 Nike 的[运动水壶][1] 22 | 。 23 | 24 | 价格也还好,于是我决定尝试一下,拓宽一下人生经历😂 25 | 26 | 下单之后几天后,收到一封来自 ECMS EXPRESS 的邮件,说是包裹到海关了,让我填身份证之类的东西用于清关,邮件居然还是中英对照的。 27 | 28 | ![](//i.imgur.com/xHF4WB7l.png) 29 | 30 | 然后我就把这件事情忘记了。直到昨天下午,报告才送到了收货地。不知道我是不是发现了 Amazon 的一个 bug,送达时间是在北京时间 11 月 1 日,也就是美国时间 11 月 10 日。但是我在北京时间 11 月 2 日登陆页面查询的时候,美国时间 11 月 1 日,由于时区没处理好,显示了「已于今日送达」而不是昨日。 31 | 32 | ![](//i.imgur.com/hFWfo6Ll.png) 33 | 34 | 想想也是,时区这个东西,当一个系统的业务没有扩展到全球范围的时候,谁会去考虑呢?当一个系统真的面向全球用户服务的时候,谁会真的在意区区物流的时间是否正确处理了时区呢? 35 | 36 | 我目前在菜鸟网络做的项目是[电子面单][2],出于职业敏感,我关注到了 Amazon 包裹上张贴的电子面单,国外物流商的电子面单。 37 | 38 | ![](//i.imgur.com/inJl48Yl.jpg) 39 | 40 | 来一个包裹的照片。 41 | 42 | ![](//i.imgur.com/x4EuJxRl.jpg) 43 | 44 | 水壶到手之后,洗了洗烫了烫,就跟着我一起跑步健身去了~感觉自己萌萌哒😇 45 | 46 | 边运动边听「内核恐慌」还是有点意思的~愿我的背疼早日康复! 47 | 48 | By the way,我前几天我买了 MUJI 的床罩和被套,虽然触感不错,但是尺寸有点大,我的被子是 150×200 的,但是 MUJI 只有 170×200 的,不知道是我的床和被子的尺寸不科学,还是 MUJI 的床上用品的尺寸就是比较特殊。 49 | 50 | [1]: http://www.amazon.cn/Nike-耐克有挂牌的运动水壶-Anthracite-黑色-20-Ounce/dp/B00BW5M5FK/ 51 | [2]: https://bbs.taobao.com/catalog/thread/567766-267238055.htm 52 | 53 | -------------------------------------------------------------------------------- /source/_posts/capture-linux-login-screen.md: -------------------------------------------------------------------------------- 1 | title: 捕获 Linux 图形化登陆界面的截图 2 | tags: 3 | - Linux 4 | categories: 5 | - Study 6 | thumbnail: 'https://ws1.sinaimg.cn/large/e724cbefgw1ewng5svd8sj20b604rgm2.jpg' 7 | hljs: true 8 | cc: true 9 | comments: true 10 | date: 2015-10-03 04:28:06 11 | --- 12 | 13 | 14 | 在上一篇博客「[重返 Linux 世界][1]」中,我说 Linux Mint 17.2 的登陆界面比之前的要好看不少。作为佐证,我贴了一张 Linux Mint 登陆界面的截图。 15 | 16 | 在日常使用中,我们的截图操作都是在登陆系统之后进行的,比如捕获一个窗口,捕获指定区域,或者捕获整个网页。要给登陆界面截图,那是在登陆之前就要做的操作,这可难倒我了。 17 | 18 | 19 | 20 | {% recruit %} 21 | 22 | 之前没有这样的截图需求,这次不妨各种手段都拿来尝试一下。 23 | 24 | 首先想到的是延时截图,比如在 kscreenshot 设置 10s 之后截图,然后在截图之前完成切换用户并进入登陆界面的操作。结果是残酷的,截出来的图是黑屏。 25 | 26 | GUI 的截图解决方案不可用,我只好求助于 CLI。scrot 是一个大名鼎鼎的命令行截图工具,支持延时截图。我将延时截图故伎重演,结果依然黑屏。 27 | 28 | 常规武器已然用尽,敌人却依旧活蹦乱跳,这让我情何以堪。 29 | 30 | 一番 Google 之后,发现一些线索,这个问题老早就有人提问了[^1]。 31 | 32 | [^1]: [How can I take a screenshot of the login screen?][2] 33 | 34 | 我参考的是 Parto 的[回答][3],然后他的回答又是参考的别人家的博客[^2]。 35 | 36 | [^2]: [How To Take Screenshot Of Login Screen In Ubuntu 14.04][4] 37 | 38 | 本来应该轻而易举就搞定的,结果却因为手残,脚本中少写了一些东西而折腾了半天。最终在 root 权限下面用这些命令捕获了登录界面的截图。 39 | 40 | ```bash 41 | chvt 8 42 | sleep 5 43 | DISPLAY=:0.0 XAUTHORITY=/var/lib/mdm/:0.Xauth xwd -root > /tmp/shot.xwd 44 | convert /tmp/shot.xwd /tmp/ss.png 45 | ``` 46 | 47 | 这些命令最关键的地方,是第三行的 `XAUTHORITY=/var/lib/mdm/`。不同的发行版,默认会使用不同的登录管理器,比如 Ubuntu 用的是 lightdm,Kubuntu 用的是 kdm,Linux Mint 用的是 mdm,以 Gnome 为桌面环境的发行版用的是 gdm。 48 | 49 | 不同的登录管理器,对应的 XAUTHORITY 也就不一样。所以网上找到的资料中,有的是 `XAUTHORITY=/var/run/lightdm/root/`,有的是 `XAUTHORITY=/var/lib/gdm/`。那么问题来了,我们该如何确定当前的系统用的到底是哪个登录管理器? 50 | 51 | 当然不能拍脑袋,要有理有据。一开始的时候我习惯性的以为我在用的 dm 是 kdm,结果就掉到坑里了。 52 | 53 | ![](https://ws2.sinaimg.cn/large/e724cbefgw1ewng2bql7tj20ro0dk76x.jpg) 54 | 55 | 其实很简单,只需要把名字中包含 dm 的进程捞出来看一眼,就能确定命令该怎么写了。 56 | 57 | 最后,美图共赏~ 58 | 59 | ![](https://ws1.sinaimg.cn/mw1024/e724cbefgw1ewnb8odazkj211y0lcdz0.jpg) 60 | 61 | [1]: http://blog.jamespan.me/2015/10/03/free-as-in-freedom/ 62 | [2]: http://askubuntu.com/questions/43458/how-can-i-take-a-screenshot-of-the-login-screen 63 | [3]: http://askubuntu.com/a/607095 64 | [4]: http://itsfoss.com/screenshot-login-screen-ubuntu-linux/ 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /source/_posts/dns-with-os-x.md: -------------------------------------------------------------------------------- 1 | title: 在 OS X 10.10.4 上设置 DNS 2 | tags: 3 | - OS X 4 | categories: 5 | - Study 6 | cc: true 7 | hljs: true 8 | comments: true 9 | date: 2015-08-03 23:08:36 10 | --- 11 | 12 | 13 | ```bash 14 | sudo networksetup -setdnsservers [dns2] [...] 15 | sudo networksetup -setdnsservers empty 16 | ``` 17 | 18 | 大概有大半年的时间了,连上公司的 VPN 之后,就没法使用 HSF 等等一系列中间件,于是一切的开发、测试都没法做了。一开始的时候忍忍算了,大不了跑去公司写呗,顺便在食堂解决伙食问题。 19 | 20 | 最近天气炎热,实在不想出门,被逼无奈只好开始分析问题。 21 | 22 | 23 | 24 | {% recruit %} 25 | 26 | 上周查看异常堆栈的时候发现,最开始抛出的异常是 java.net.UnknownHostException,于是当时我怀疑问题出在 DNS 上,但是没有继续深究,而是在内网发了一个状态,想碰碰运气看一下有没有同事曾经遇到并解决了类似的问题。 27 | 28 | ![内网求助状态](https://ws2.sinaimg.cn/large/e724cbefgw1eupszi6qbcj20h905qabc.jpg) 29 | 30 | 有个同事回复了一下,然后就没有然后了。一个星期过去了,又到了周末,问题依旧。 31 | 32 | 观止巨巨眼看我又要跑去公司,问我咋不用 VPN,我跟他描述了情况,他建议我绑定 DNS 试试。 33 | 34 | 一般来说电脑连上路由器之后,路由器会充当 DNS 的角色,为了解决这个问题,我可能需要绑定办公网的 DNS。然而,我不知道办公网的 DNS 是什么,在内网各种搜索也没有结果。 35 | 36 | 无奈之下,只好又跑公司去了。 37 | 38 | 联网之后记下办公网的 DNS,吭哧吭哧写了几个小时代码之后回家。 39 | 40 | 晚上吃完饭回来,我还惦记着 DNS 的事情。连上 VPN 之后,跑一个用了 HSF 的测试用例,不出意料地挂了。确认办公网 DNS 能 ping 通,然后配置好 DNS 之后,测试用例!通!过!了! 41 | 42 | 这个世界上的事情,没有那么简单的。连上 VPN,设置了 DNS,HSF 是能用了,那么断开 VPN 之后呢?因为 DNS 设置还在,而此时 DNS 已经连不上了,于是域名解析瘫痪,上不了网了。 43 | 44 | 虽然我很想吐槽公司的 VPN 软件,很想给他们提需求,但是自己动手解决问题还是最省事的。虽然我没法把连接 VPN 和设置 DNS 两件事自动化起来,但是我至少可以把事情简化一点,不用总是拿鼠标点啊点的。 45 | 46 | 不得不说,我对 OS X 下面的一系列系统管理工具不是很熟悉,每次都只能 Google 一下。这次可算是有意外收获,不但找到了介绍如何用命令行设置 DNS[^1],还发现了 [OS X Daily][2] 这个有意思的网站。 47 | 48 | [^1]: [How to Change DNS from Command Line of Mac OS X][1] 49 | 50 | 51 | 需要注意的一点,清除 DNS 设置的命令是 52 | 53 | ```bash 54 | sudo networksetup -setdnsservers Wi-Fi empty 55 | ``` 56 | 57 | 而不是 58 | 59 | ```bash 60 | sudo networksetup -setdnsservers Wi-Fi 61 | ``` 62 | 63 | 64 | [1]: http://osxdaily.com/2015/06/02/change-dns-command-line-mac-os-x/ 65 | [2]: http://osxdaily.com 66 | 67 | -------------------------------------------------------------------------------- /source/_posts/donate-nice-try.md: -------------------------------------------------------------------------------- 1 | title: 想要捐赠?想得美! 2 | tags: 3 | - Sketch 4 | categories: [Life, Essay] 5 | cc: true 6 | hljs: true 7 | comments: true 8 | date: 2015-03-18 01:48:26 9 | --- 10 | 11 | 前些日子,我在浏览简书上的文字的时候,注意到了文章的最下方,有一个可以让读者点赞的地方。比如垠神新作[对的人](http://www.jianshu.com/p/8f9a5be17499),短短几个小时,收获了 61 个喜欢。 12 | 13 | ![王垠-对的人](https://ws3.sinaimg.cn/large/e724cbefgw1exdxplrrk0j20h908r3yv.jpg) 14 | 15 | 16 | 17 | {% recruit %} 18 | 19 | 简书是我觉得很赞的一个内容分享社区。从“找回文字的力量”,到“交流故事,沟通想法”,虽然格调日趋下降,但是也因为用户基数的增加,这个社区变得愈发的丰富多彩。 20 | 21 | 我也曾经在简书写过一篇文章,关于我毕业时候的感想,对不堪回首的本科四年说再见,顺便吐槽所谓的“国之大学”。 22 | 23 | 后来,为了维护码农博客的高冷,我买了域名搭建了独立博客。其实我是嫌弃简书把我的文章变成了 URL 中一串由散列算法生成的毫无意义的字符串。 24 | 25 | 至于那些博客园、CSDN,我更是敬而远之,博客园上那个曾经被我用来发 ICPC 算法题解的博客,已经消失在了次元的彼岸。 26 | 27 | 后来,我在微博文章的最后看到了一个大大的“赏”字。 28 | 29 | ![微博打赏](https://ws3.sinaimg.cn/large/e724cbefgw1exdxpwrcxlj20go041t8l.jpg) 30 | 31 | 我开始思考,是否我也能在我的博客弄一个类似的点赞、打赏的东西,让我在写博客之余收获一些虚无的成就感? 32 | 33 | 考虑到点赞的功能多说已经帮我做好了,我只需要弄一个打赏的功能。 34 | 35 | 首先想到的是支付宝的付款链接。令人头疼的是,支付宝的付款链接功能已经下线,我只能另辟蹊径。 36 | 37 | 最终做出来的效果是这样的。 38 | 39 | ![捐赠](https://ws1.sinaimg.cn/large/e724cbefgw1exdxq749oaj20n1027dg1.jpg) 40 | 41 | 如果有读者点击了绿色按钮,会在新标签页中打开支付宝的转账页面。为了能够知道是我的哪篇文字让读者产生了鼓 (juān) 励 (zèng)我的冲动,我在备注里写上了文章标题。 42 | 43 | ![转账](https://ws4.sinaimg.cn/large/e724cbefgw1exdxqhl1kej20f308pwf2.jpg) 44 | 45 | 这个捐赠按钮的实现很简单,就是向支付宝的转账页面 POST 一个表单而已。 46 | 47 | ```html 48 |
49 | 50 | 51 | 52 | 53 | 54 |
55 | ``` 56 | 值得一提的是,为了弄这个捐赠表单,我还专门注册了个支付宝小号。假如我就这么大摇大摆的把常用支付宝帐号贴在页面上,谁知道会发生什么事情,哪怕是被无聊的人暴力登录到锁账户,也够你恶心一壶的了。 57 | 58 | 其实我不是真的求爷爷告奶奶要来自读者的捐赠,这么十块八块的钱我也不缺,就是想看看我的博文到底价值几何。 59 | 60 | 然后我想明白了,就凭现在的我,即使博文里写出花来,也是收不到捐赠的。 61 | 62 | 正所谓“藏诸名山,传之其人”,倾注了心血和时间的作品,如此轻易的出卖,岂不可惜? 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /source/_posts/everyone-dies-alone.md: -------------------------------------------------------------------------------- 1 | title: 我们都会在孤独中离开 2 | categories: 3 | - Life 4 | thumbnail: 'https://i.imgur.com/yEy5y1um.png' 5 | cc: true 6 | comments: true 7 | date: 2016-06-25 01:06:31 8 | --- 9 | 10 | 11 | > Everyone dies alone. But if you mean something to someone, if you help someone or love someone, if even a single person remembers you. Then maybe, you never really die at all. 12 | 13 | Person Of Interest, aka 疑犯追踪,在经历了整整五季之后,终于迎来了一个并不十分 Happy 的 Ending。 14 | 15 | 令我没有想到的是,在大结局的 S05E13,POI 为我们熬了一锅浓浓的鸡汤,就是我在文章开头引用的那段英文。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | 是的,我们每个人都会在孤独中离开。但是如果你帮助过什么人,爱过什么人,如果有人还记得你,或许你就没有真正离开。 22 | 23 | 什么是生命的意义? 24 | 25 | 也许在失意的时候,也许在被现实生活弄得疲惫不堪的时候,我们曾经问过自己,活着,究竟是为了什么?或者问自己更加现实的问题,每天这么辛苦,为了什么?每天加班到深夜,图什么? 26 | 27 | Finch 和 Reese 每天等着机器用奇怪的方式吐出一串无关人士的社保号,然后出生入死,为了什么? 28 | 29 | 就为了领个可怜的工资然后吃顿好的? 30 | 31 | 就为了可以突突突坏人的膝盖? 32 | 33 | 想必都不是。来自外部的激励是很难让人长期坚持做自己不喜欢的事情的。长期的坚持,必然是有发自内心的喜欢,发自内心的渴望,渴望将自己喜欢的事情做得更好一点,更好一点。 34 | 35 | Be a better man, help others. 36 | 37 | 在 S04E20,Reese 和想象中的 Carter 在车里谈人生,或许是一个伏笔,if even a single person remembers you, you never really die at all. 38 | 39 | ![](https://i.imgur.com/UYxRIhk.png) 40 | 41 | 在 S05E10,人见人爱花见花开的 Root 撒手人寰。 42 | 43 | ![](https://i.imgur.com/TcS5Ke4.png) 44 | 45 | 本以为就这样香消玉殒,却出乎意料地在机器中获得了永生。伊人已逝音犹在,教人如何不断肠。 46 | 47 | ![](https://i.imgur.com/M8XgH7k.png) 48 | 49 | 在看 S05E13 之前,我冒着被打死的风险,在微信朋友圈留下了这样的文字: 50 | 51 | > POI 完结什么的,已经无所谓了,因为已经不再有人,可以接受没有 Root 的 POI 了 52 | 53 | 然后很快就看到朋友的留言,「迷恋 Root 歪头杀」。 54 | 55 | ![](https://i.imgur.com/hsZor0t.png) 56 | 57 | Root 让我们迷恋的,又何止歪头杀! 58 | 59 | S01E13,Root Cause,Root 首次登场,只留下一个酷酷的背影,和一场让 Finch 措手不及的攻击。谁会想到这个邪恶的黑客,竟会是日后让无数粉丝追捧的颜值担当和智力担当?没想到你是这样的 Root。 60 | 61 | ![](https://i.imgur.com/t1vavSA.png) 62 | 63 | Root 正式登场,身份是心理医生 Ms. Turing。 64 | 65 | ![](https://i.imgur.com/BS8Xln5.png) 66 | 67 | Reese 本以为他要保护的是一个柔弱的心理医生,却没想到这枚看似弱不禁风的女子具有不输 Finch 的智商和媲美 Reese 的战斗力,还有让人迷恋的……歪头杀。 68 | 69 | ![](https://i.imgur.com/1UmndsZ.png) 70 | 71 | 被 Samaritan 满世界通缉之后,Root 开始了她的 cosplay 生涯。 72 | 73 | ![](https://i.imgur.com/2bKDSjg.png) 74 | 75 | ![](https://i.imgur.com/FzI1amF.png) 76 | 77 | ![](https://i.imgur.com/a5ntlT5.png) 78 | 79 | Root 终于和 Shaw 共度良宵了,虽然是在 Shaw 的模拟中,但也让广大肖根党一本满足。百合无限好! 80 | 81 | ![](https://i.imgur.com/jkGPfxu.png) 82 | 83 | ![](https://i.imgur.com/BqEjGKP.png) 84 | 85 | ![](https://i.imgur.com/3Ww3Jns.png) 86 | 87 | ![](https://i.imgur.com/6c3RykE.png) 88 | 89 | ![](https://i.imgur.com/nGyg7Ci.png) 90 | 91 | Root 我喜欢你啊! 92 | -------------------------------------------------------------------------------- /source/_posts/font-of-intellij.md: -------------------------------------------------------------------------------- 1 | title: 修复 IntelliJ IDEA 14 的字体渲染 2 | tags: 3 | - Tool 4 | - OS X 5 | categories: 6 | - Work 7 | cc: true 8 | comments: true 9 | date: 2015-01-16 12:39:24 10 | thumbnail: https://ws2.sinaimg.cn/small/e724cbefgw1et29qkfz7lj20b408cjsn.jpg 11 | --- 12 | 13 | # 背景 14 | 15 | 我现在使用 [IntelliJ IDEA][1] 在 Mac 下进行 Java 开发。之前一直都是从官网下载的 IDEA,用的 14.0,今天突然想换成使用 [Homebrew Cask][2] 来管理。于是我就用 `brew cask` 安装了一个 14.0.2。 16 | 17 | # 疑团 18 | 19 | 安装完成之后运行,感觉界面怪怪的,和之前从官网下载的不一样。 20 | 21 | 仔细一看,是字体渲染的问题。联想起之前在 Stack Overflow 看到过[讨论][3]说 Mac 下只有 Apple 维护的 [JDK 6][4] 才能比较好的在 Retina 分辨率下渲染程序界面。其实我之前从官网下载的 IDEA 用的就是 Apple 的 JDK 6,界面渲染的好好的,为什么从 Cask 下载的 IDEA 出了渲染问题? 22 | 23 | 24 | 25 | {% recruit %} 26 | 27 | # 尝试 28 | 29 | 一定是我打开的方式不对。先看看 Cask 版 IDEA 运行时用的哪个 JDK 。打开 About IntelliJ IDEA 瞅瞅,果然都是 JDK 7 惹的祸。 30 | 31 | ![IDEA with JDK 7](https://ws2.sinaimg.cn/large/e724cbefgw1et29qkfz7lj20b408cjsn.jpg) 32 | 33 | 那么问题来了,为什么官网的 IDEA 用的是 JDK 6,从 Cask 下载的用的却是 JDK 7 ?明明 Cask 也是从官网下载的。 34 | 35 | 于是我打算对比两个版本的 IDEA 的 plist 文件。plist 文件可以认为是 OS X 下 GUI 程序的参数配置,相当于 CLI 程序的配置文件,比如 bash 的 .bashrc,zsh 的 .zshrc。 36 | 37 | # 解决 38 | 39 | 这两个版本之间的 plist 文件差异好大,但是我发现了一个值得注意的地方。 40 | 41 | 14.0 版本中,`JVMVersion` 这个键,对应的值为 `1.6*`,到了14.0.2 版本中,却变成了 `1.6+`。 42 | 43 | 莫非这就是问题的关键?修改试试。 44 | 45 | 修改之后启动 IDEA,看起来问题解决了! 46 | 47 | ![IDEA with JDK 6](https://ws1.sinaimg.cn/large/e724cbefgw1et29ry1qd2j20b408c75w.jpg) 48 | 49 | 打开代码一看,字体渲染又和之前的一样,萌!萌!哒! 50 | 51 | 52 | [1]: https://www.jetbrains.com/idea/ 53 | [2]: http://caskroom.io/ 54 | [3]: http://stackoverflow.com/questions/15181079/apple-retina-display-support-in-java-jdk-1-7-for-awt-swing 55 | [4]: http://support.apple.com/kb/DL1572 56 | -------------------------------------------------------------------------------- /source/_posts/goodbye-duoshuo.md: -------------------------------------------------------------------------------- 1 | title: "告别多说,拥抱 Disqus" 2 | date: 2015-04-18 16:47:06 3 | tags: 4 | - Blogging 5 | - Python 6 | - Tool 7 | categories: 8 | - Study 9 | cc: true 10 | comments: true 11 | --- 12 | 13 | # 背景 # 14 | 15 | 一开始搭建博客的时候,直接套用了 Pacman 主题,它自带了多说评论插件,所以我就注册了一个帐号,然后就这么用着。 16 | 17 | 这两天我把博客环境升级到 Hexo 3.0 之后,由于一些 API 的不兼容,导致我生成的文章唯一标识符和之前的不一致了,然后好多文章的评论就显示不出来。 18 | 19 | 我尝试着去 hack 这些有变化的 API,把文章唯一标识符恢复成原来的样子,结果在新的标识符下的评论,又没法显示了。按下葫芦又起瓢,简直不能忍,只好去多说后台做修改。 20 | 21 | 多说后台有一个严重的问题,文章管理界面始终没法翻页,不管我有多少篇文章,页面上只给我显示一页的内容,后面的全部截断抛弃。当我在页面上删除了一篇文章,实际上它并没有被删除,假如我添加一篇一样的文章,使用一样的文章唯一标识符,它会阻止我继续操作。 22 | 23 | 24 | 25 | {% recruit %} 26 | 27 | 之前我一直将就用着,今天终于给多说这个充满漏洞的评论系统跪了,除了支持新浪微博,找不出半点好。可见一个应用哪怕再烂,只要“接地气”,多弄一些天朝特色,还是能让用户将就这用的。 28 | 29 | 我决定把评论系统切换到 [Disqus][1],即使可能会丢失全部的评论数据,我还是决定和多说一刀两断。 30 | 31 | # 切换 # 32 | 33 | 整个切换过程其实很简单,在 Disqus 注册,然后在 [Settings/Admin][3] 中新建站点,接下来就是一步一步跟着向导程序走下去,把 Disqus 提供的 脚本放在指定的位置即可。 34 | 35 | 为了拥有更好评论一致性,建议直接使用第二步中提供的 JavaScript 脚本,为每篇文章指定唯一的 identifier,固定的 title 和 url。 36 | 37 | 为了更好的显示效果,我们还需要为 Disqus 的评论框添加样式,我直接参考了 [Morris' Blog][4] 博文《[解決 Hexo Comment !][3]》。 38 | 39 | 到此为止,博客已经可以很好的显示评论了。考虑到国内注册 Disqus 的人没有注册微博的那么多,我调整了设置,允许访客留言。不过我还是希望读者能够花几分钟注册,毕竟这个是全球最大的评论社区,加入社区怎么看都是有好处的(虽然是一个以英文为主的社区,但是我们作为开发者,如果连这种程度的英文都头疼的话,恐怕离天花板也不远了)。 40 | 41 | # 迁移 # 42 | 43 | 人是一种不懂得满足的生物。用上 Disqus 之后,我得寸进尺的想要把之前在多说的评论也迁移过来。 44 | 45 | 多说提供了导出的功能,能够把整个站点的文章列表和评论列表导出来,以 JSON 格式存储[^1]。 46 | 47 | [^1]: [多说导出的评论文件说明][5] 48 | 49 | 然而 Disqus 的导入功能,支持的是 WordPress 导出的 XML 格式的文件[^2]。 50 | 51 | [^2]: [Custom XML Import Format][6] 52 | 53 | 两种格式之间的转换,似乎只有从 Disqus 到多说的转换,我想要的转换没有现成的轮子可以使用,只好亲自动手。 54 | 55 | 整个转换的过程无非就是加载 JSON 文件,解析成哈希表,然后遍历哈希表生成“文章-评论”这样的一对多的组合关系,最后遍历这样的关系生成目标格式的文件。 56 | 57 | 解析 JSON 直接使用标准库即可,多说导出的 JSON 还是比较标准的,没有语法错误。整个过程也就输出到 XML 的时候麻烦一些。之前只用过 [lxml][7] 解析 XML,生成 XML 还是头一回。 58 | 59 | 在[官方文档][8]的帮助下,我顺利的把轮子造出来了。 60 | 61 | 多说导出的评论比较混乱,有些文章的链接居然还是指向的 localhost 或者其他的内网 ip,也是醉了。转换了格式不算,还得人工审查,幸好现在博文还不是太多,要是有几百篇博文非得被玩坏不可。 62 | 63 | 如果我有时间把这次写的脚本整理成一个命令行程序,就单独再写一篇博客分享出来。 64 | 65 | 这次写的脚本在《{% post_link the-duoshuo-migrator %}》有详 (jiăn) 细 (lüè) 的介绍,欢迎使用~ 66 | 67 | [1]: https://disqus.com 68 | [2]: https://disqus.com/admin/ 69 | [3]: http://morris821028.github.io/2014/04/12/web/hexo-comment/ 70 | [4]: http://morris821028.github.io 71 | [5]: http://dev.duoshuo.com/docs/500fc3cdb17b12d24b00000a 72 | [6]: https://help.disqus.com/customer/portal/articles/472150-custom-xml-import-format 73 | [7]: http://lxml.de/index.html 74 | [8]: http://lxml.de/tutorial.html 75 | -------------------------------------------------------------------------------- /source/_posts/grand-theft-auto-v-a-new-world.md: -------------------------------------------------------------------------------- 1 | title: 打开了新世界的大门——GTA 5 初体验 2 | tags: 3 | - Gaming 4 | categories: 5 | - Life 6 | thumbnail: https://ws4.sinaimg.cn/bmiddle/006tKfTcgw1f6un344x0hj30dd0godix.jpg 7 | cc: true 8 | comments: true 9 | date: 2016-08-18 22:57:45 10 | --- 11 | 12 | 最近在室友的安利下,接触了一款经久不衰的游戏,侠盗猎车手,也被简称为 GTA。其实我在多年之前就听说过这款大名鼎鼎的游戏,但因为各种原因一直没能入坑。没想到最后还是在室友的 PS4 上体验了一把,增长了人生的经验。 13 | 14 | 其实我玩过的电子游戏并不多,抛开手机上林林种种的休闲游戏和 Windows 自带的纸牌扫雷不谈,我最早玩的游戏应该是大富翁。那时还是在小学的电脑课上,完成了键盘打字练习之后的欢乐时光。后来便是被称为「打飞机」的雷电 3,以及仙剑奇侠传、反恐精英、魔兽争霸之类的经典游戏。 15 | 16 | 17 | 18 | {% recruit %} 19 | 20 | 第一次接触主机游戏是在初中。那时放学后自己骑车回家,便有机会有时间去干些坏事。曾经有一段时间被和同学一起在放学后溜到学校附近的商场,一头扎进电玩铺,花上几块钱问老板要张游戏碟开始在三国无双、极品飞车、FIFA、实况等等至今依旧火爆的游戏里厮杀搏斗个一两小时。可惜那时的我始终没能在游戏中占据上风,渐渐地也就失去了在主机上和同学一较高下的兴致。 21 | 22 | 初中那会,文曲星风靡全国,伴随着文曲星一起发布的游戏「英雄坛说」更是在学生中间遍地开花,多少人书包里开着文曲星打坐练功。那时许多同学都以学习英语为理由,问家长买了一部文曲星,而我有一个深谙套路的父亲,为了学习英语这一套说辞是万万行不通的,我也因此从未拥有过一部属于我的电子词典。天无绝人之路,没有文曲星的我,以把作业给同学抄作为交换,得到了在学校上课的时间里玩文曲星的机会。 23 | 24 | 学习成绩在高中之前一直不错的我,从小就擅长利用自己在学习上的优势来换取我从父亲那得不到的资源。小学时候家里对我的零用钱管的很严,我便通过卖作业赚取外快,拿我的作业去抄的,根据作业量收五毛到一块,代写作业的价格自然要更高一些。到了初中,交换目标便从零花钱变成了游戏、文曲星、小说等等。 25 | 26 | 到了高中,电脑课的内容自然是没人会听的,大家都在忙着下电影、打魔兽。学校的图书馆里有机房,放学后我也是经常去机房里下电影,偷偷玩着游戏。学校图书馆是禁止游戏的,为了愉快的玩耍,我们学会了干掉网管系统在电脑上的客户端,还学会了一边玩游戏一边关注幽灵般飘忽不定的网管。当然网管是不喜欢学生叫她做网管的,当面得叫一声「老师」。 27 | 28 | 大学之后有了自己的电脑,也曾经和本科室友一起开黑玩 Dota。当我用我最喜欢的英雄,恶魔巫师,始终无法战胜简单的电脑,并在天梯上将英雄积分玩到 1 分之后,我决定面对我没有能力将 Dota 玩好这个事实。于是不久之后我把电脑完全格盘装了 Linux 开始了以写代码为玩游戏的日子。虽然现在的 Linux 系统上也能安装 Steam 也能玩游戏了,但是我念大学那会,将 Linux 作为日常使用的操作系统还真是一场苦修。 29 | 30 | 言归正传。GTA 5 是我接触的第一个沙盒游戏,整个游戏的开放程度,让我大开眼界。我也对我奇葩的玩点无可奈何。 31 | 32 | 我会开着个抢来的老爷车,跟在一个陌生车辆后面,在城里晃悠。 33 | 34 | ![](https://ws3.sinaimg.cn/mw1024/801b780agw1f6y9n138byj21hc0u0wo4.jpg) 35 | 36 | 还会去抢一辆救护车,然后开上绕城高速去和警车玩生死时速。 37 | 38 | ![](https://ws1.sinaimg.cn/mw1024/801b780agw1f6y9qjn47gj21hc0u0wse.jpg) 39 | 40 | 体验过这种把警察晃掉的快感之后,我深陷其中无法自拔,开始抢警察的摩托车。 41 | 42 | ![](https://ws4.sinaimg.cn/mw1024/801b780agw1f6y9tln6hzj21hc0u0qa1.jpg) 43 | 44 | 抢警用巡逻车,然而等到我甩开了警察的围追堵截,巡逻车已经撞得稀烂。 45 | 46 | ![](https://ws1.sinaimg.cn/mw1024/801b780agw1f6y9vh0jpxj21hc0u0n9m.jpg) 47 | 48 | 甚至有一次还抢到了警长座驾! 49 | 50 | ![](https://ws1.sinaimg.cn/mw1024/801b780agw1f6y9wry8s0j21hc0u07az.jpg) 51 | 52 | 确切的说警长座驾不是抢来的,是捡来的。有一次我看到一辆警车开着呜啦呜啦的警报在追逐一辆吉普车,我玩心大起开始尾随这辆警车。开不多远吉普车停下,两个歹徒下车和警察交火,居然把车上两个警察都给干趴下了!等歹徒离开后,我就这样大摇大摆地把警车开走了,上了车才发现这是警长座驾。出乎意料的是,上车之后我就被通缉了,开了一会才把赶来抓我的警察甩开。 53 | 54 | 游戏中最不值钱的东西也许就是汽车了,满大街的汽车,别人的都是花血汗钱买的,就我的是随便抢来的。被抢车主的性格也是各不相同,有些人被我拖下车之后,连滚代爬跑得比谁都快,有些人不但不跑,还在后面追着,我开的慢点或者停车了, 还会把我拖下车踹几脚。 55 | 56 | ![](https://ws4.sinaimg.cn/mw1024/801b780agw1f6yaa67klxj21hc0u049d.jpg) 57 | 58 | 有一次我在绕城高速上抢了一辆超跑,这哥们那个紧追不放啊,我就慢慢开,离得远了就停下等等,离得近了就加一脚油门,就这样生生放起了风筝。真是败给了我的恶趣味。 59 | 60 | GTA 5 这种沙盒游戏最吸引我的地方,也许就是能在虚拟世界中做很多在现实世界中打死也不敢做的事情吧,释放一下现实生活中作为文明人而压抑的邪恶天性。 61 | 62 | 63 | -------------------------------------------------------------------------------- /source/_posts/handling-301-from-upstream.md: -------------------------------------------------------------------------------- 1 | title: 在 NGINX 中处理来自上游的 301 跳转 2 | tags: 3 | - NGINX 4 | categories: 5 | - Study 6 | hljs: true 7 | cc: true 8 | comments: true 9 | thumbnail: //i.imgur.com/bGls4RPl.jpg 10 | date: 2015-11-11 20:58:06 11 | --- 12 | 13 | 自从我借助 NGINX 和两台 ECS 把博客的部署结构变成高可用之后,许多意想不到的事情就陆陆续续出现了。 14 | 15 | 双十一前的最后一个下午,[不如][1]在微博上给我留言,问我的博客是不是挂了。 16 | 17 | 不不不,我的博客号称可用性 99.999%,怎么会说挂就挂呢(捂脸逃。于是问不如要了没法访问的 URL。 18 | 19 | 20 | 21 | {% recruit %} 22 | 23 | 链接是下面这个样子的,不如在他介绍「不蒜子」这个访问统计服务的博文中引用了我的博文,作为服务降级的例子。 24 | 25 | 26 | 27 | 当时我试着直接访问这个网址,然后就被重定向到了 CNPaas 提供的网址上,空气中顿时布满淡淡的忧伤。 28 | 29 | 30 | 31 | 一看就知道是哪里没弄好被 301 了。从 Chrome 开发者工具可以看出来,我的 NGINX 把 URL 完整地代理到了 CNPaaS,然后就被 CNPaaS 的 NGINX 给 301 到它自己的域名下面去了。 32 | 33 | ![](//i.imgur.com/gcAaIWa.png) 34 | 35 | 简直就是天坑。原因很明显,就是 URL 的结尾没有「/」符号(slash),然后触发了 CNPaaS 的重定向规则。之所以会让人感觉挂了,也许是因为它返回了重定向之后,浏览器再次访问的时候,服务有些不稳定吧? 36 | 37 | 知道了问题所在,于是我就面临着两个选择,一个是绕开,一个是解决。当时正值双十一之前,有点一时半会搞不定的感觉。 38 | 39 | 先说一下绕开的思路。 40 | 41 | 既然结尾没有「/」的 URL 会被 upstream 重定向,那么我干脆在入口处先自行重定向到以「/」结尾的 URL 上去,就可以绕开 upstream 的 301 了。 42 | 43 | 于是我可以在 server 中添加一个重写规则,即 [rewrite][2] 指令,先下手为强地进行重定向: 44 | 45 | ```NGINX 46 | server { 47 | listen 80; 48 | server_name blog.jamespan.me; 49 | rewrite ^([^.]*[^/])$ $1/ permanent; 50 | location / {...} 51 | } 52 | ``` 53 | 54 | 这种绕开的方式简单明了,一行配置搞定,但是有点像打补丁,今天把这个坑堵上了,没准明天还有别的重定向坑。 55 | 56 | 另外一种解决方案是使用 [proxy_redirect][3],修改返回报文中的 Location 和 Refresh 字段。 57 | 58 | ```NGINX 59 | server { 60 | listen 4002; 61 | port_in_redirect off; 62 | proxy_redirect http://$proxy_host/ http://$host/; 63 | location / { 64 | proxy_pass http://blog-panjiabang.app.cnpaas.io/; 65 | proxy_set_header X-Real-IP $remote_addr; 66 | } 67 | } 68 | ``` 69 | 70 | 这种方式处理来自 upstream 的 301 比较彻底,直接从源头把各种 upstream 的域名转换成自己的域名。 71 | 72 | 最后在 [SSH::Batch][4] 的帮助下,我在很短的时间内搞定了这个问题。或许以后用 SSH::Batch 的机会不多了,因为我已经把服务器运维工具全面转向 [Ansible][5]! 73 | 74 | 最近在开始认真学习 NGINX,先跟着 agentzh 菊苣的教程看看。之前一直是把 NGINX 配置起来用用,需要加缓存就 Google 一下,这个那个问题出现了就 Google 一下。这种面向 Google 的编程确实能帮助我解决问题,但是没法帮助我成为专家。 75 | 76 | 关于 URL 的结尾是否需要「/」,有一篇文章讲的不错,「[Why do URLs often end with a slash?][6]」。当一个 URL 以「/」结尾时,就明确告诉服务器,去访问一个目录,否则服务器会先去试图访问文件,找不到文件就通过重定向去访问目录。由于这个策略的存在,访问一个文件的时候,如果 URL 结尾带了「/」,就会因为找不到目录直接 404 了。 77 | 78 | 所以说,贴链接的时候,尽可能明确地给出要访问的资源是目录还是文件,是一种好习惯~ 79 | 80 | [1]: http://ibruce.info 81 | [2]: http://NGINX.org/en/docs/http/ngx_http_rewrite_module.html#rewrite 82 | [3]: http://NGINX.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect 83 | [4]: /2015/11/07/ops-with-ssh-batch/ 84 | [5]: http://www.ansible.com/ 85 | [6]: http://webdesign.about.com/od/beginningtutorials/f/why-urls-end-in-slash.htm 86 | -------------------------------------------------------------------------------- /source/_posts/i-just-wanna-healthy-life.md: -------------------------------------------------------------------------------- 1 | title: 我只是想健康地活下去 2 | tags: 3 | - Exercise 4 | categories: 5 | - Life 6 | cc: true 7 | comments: true 8 | date: 2015-10-06 02:03:11 9 | --- 10 | 11 | 国庆期间的户外体能恢复计划,随着一场场的秋雨,就这么泡汤了。接下来的假日,只能考虑室内运动了。曾经有一段时间,我保持着健身的习惯,那是 14 年 9 月 到 15 年 3 月这半年的时光。那时候我常去公司的健身房,还请了私人教练来指导。 12 | 13 | 那时候的健身锻炼卓有成效,我的体重也从一开始的 74kg 下降到了 65kg。3 月之后我没有再买课时,然后自己断断续续锻炼了两个月,身材和体能也还保持着。然而天有不测风云,从 4 月开始,工作上的事情就让我忙得没有时间锻炼身体了。 14 | 15 | 16 | 17 | {% recruit %} 18 | 19 | 因为工作太忙而缺乏锻炼,这种说法是会被人耻笑的吧。从来不敢想象,几个月的缺乏锻炼,能让一个人的身体虚弱到这种地步。体重也是直接回到解放前,甚至有过之而无不及,每天摸着自己的肚子上的游泳圈暗自垂泪 TnT 20 | 21 | ![](https://ws3.sinaimg.cn/large/e724cbefgw1ewqqh8itq1j20hs131787.jpg) 22 | 23 | 放假这几天,我开始给自己安排康复训练,先做一些有氧运动比如跑步什么的,把体能恢复一部分,然后开始力量训练。假期开始的假期开始的那几天,我也绕着小区跑了一会,每次跑了一两公里就跑不动了,小腿外侧绷得厉害。不过让我欣喜的是每天能跑的里程也在一点一点增加。 24 | 25 | 天公不作美,从 4 号开始,阳光明媚的好日子一去不返,我的室外有氧也被迫搁置。难道我还要去公司的健身房不成?大雨天的跑公司健身,也是蛮拼的。拿出地图搜了一下附近的健身房,原本并没抱多大希望的,这荒郊野岭的有健身房出没的概率是在不大。 26 | 27 | 但是,奇迹出现了!就在我住的小区,就有健身房!感动哭了,当时就决定第二天去看看。于是今天下午我跟着地图的指引找到了这个藏得很深的健身房。 28 | 29 | ![](https://ws1.sinaimg.cn/large/e724cbefgw1ewqqji3zivj21kw16oqnh.jpg) 30 | 31 | 这个健身房是一个叫「菲力伟」的连锁健身俱乐部,在杭州还有另外几家的样子。进去之后,前台妹纸给我倒了一杯水,然后会籍顾问出来接待并带我在健身房转转。我办了一张年卡,花了软妹币 3500+。 32 | 33 | ![](https://ws3.sinaimg.cn/large/e724cbefgw1ewqqrespnaj21kw0u5ap0.jpg) 34 | 35 | 明明公司有免费的健身房,为什么还要花几千大洋办一个健身房的年卡,脑袋被驴踢了?其实,免费的,往往是最贵的。而表面上收费的,其实比免费的要划算。 36 | 37 | 先说一下健身房的人均资源。想象一下,一个几万人的园区,健身房里面十几台跑步机,十台左右的椭圆机,一架史密斯机,一个深蹲架,几个训练胸、肩、腿的器械,非工作时段去健身房做一套有氧无氧下来得花多少时间在等器械上?在有氧运动上,女生比男生能强得太多了,随随便便跑个一小时半小时面不改色,于是跑步机椭圆机后面的队伍长长长长长,等跑步做热身都能等死。排个队有什么大不了的?这个还真的要看个人,有些人就愿意排队,反正有大把的时间,有些人就等不起,因为他们更珍惜自己的时间。 38 | 39 | 再说一下健身环境。在免费的健身房,能够使用的就只是有健身器材、浴室而已,哦,还需要排队才能使用。在付费的健身房,资源就会充足很多,至于会不会排队,还得等假期结束之后才知道。毕竟是面向社会人士的健身房,如果搞得像面向大学生的廉价健身房那样,那就真是作死了。除了比免费的健身房更为丰富的健身器材,还有按摩器材,还有定期的健身课程,以及「菲力伟翡翠城店」独有的游泳池(虽然只在 6 月到 9 月开放)。这些增值服务大部分我都没有亲身体验,以后有机会再分享~ 40 | 41 | 上面这些其实都不是最重要的,最重要的是,你花了钱,就会惦记着,要去锻炼,要去健身。大三那会,我办了「南开 365 健身房」的年卡,不多不少 365 RMB。就在那个烂的一逼的健身房里,我也坚持锻炼了大半年,虽然是自己跑步、卧推、仰卧起坐,这么瞎练下来也卓有成效,因为目标不是减脂所以没有刻意控制饮食,然后身体蛮壮的。同样的,办了一张年卡,价格是大三那会的 10 倍,你就会惦记着,下班后早点回家,少蹲在公司,去锻炼,去健身。 42 | 43 | 免费的,往往最贵,不要贪图那点明面上的小便宜,却在暗地里吃了大亏而不自知。把更多的心思放在自己身上,放在生活上,然后人生才会渐渐变得丰富多彩起来。 44 | 45 | 最后的最后,在下面和大家分享我的运动日历「[我只是想健康地活下去][1]」,自备梯子。日历异步加载,加载完成后显示。 46 | 47 | [1]: https://www.google.com/calendar/embed?src=orjo64hkpfp640ql3fdtv3qg94%40group.calendar.google.com&ctz=Asia/Shanghai 48 | 49 | 56 | 57 | 60 | -------------------------------------------------------------------------------- /source/_posts/its-easily-to-be-mouldy-in-lonely-days.md: -------------------------------------------------------------------------------- 1 | title: 宅久了,会发霉 2 | categories: 3 | - Life 4 | cc: true 5 | comments: true 6 | thumbnail: //i.imgur.com/dyaOd0Hm.png 7 | date: 2015-12-11 00:02:59 8 | --- 9 | 10 | 不久前,一位朋友尝试安利我养一只宠物,比如喵星人什么的。她说,一个人宅久了,会发霉的。我说,我连照顾自己都费劲,哪里还有精力照顾喵。 11 | 12 | 她问我,一个人不感到孤单?我说,我有电脑,不孤单。 13 | 14 | 15 | 16 | {% recruit %} 17 | 18 | 不孤单,却注孤生。 19 | 20 | 墙角数枝梅,凌寒独自开。遥知不是雪,为有暗香来。 21 | 22 | 在冬季,别人的墙角,开出了梅。在冬季,我的墙角,发起了霉。 23 | 24 | ![宅久了,会发霉](//i.imgur.com/22lHzuTl.jpg) 25 | 26 | 这是一个阴雨连绵的冬季,也是我第一次遭遇如此多雨的冬季。从小生长在海南,虽然多雨,虽然年年台风,但家里的物件也不曾发霉,更别说墙壁了。大学之后到了天津,空气更是干燥得仿佛不含水分,大学四年的宿舍虽然欠收拾,但也未曾有过如此惨烈的景象。 27 | 28 | 发霉的位置之前一直被床体遮挡,被窗帘遮挡,未能及早发现。不过如今发现了也还不算晚。虽然未曾有过处理的经验,但也不至于「被水淹没,不知所措」。 29 | 30 | 一番 Google 之后,我才发现原来房屋发霉,是江南地区的常事,特别梅雨季节更是发霉的高峰期。只不过今年冬天的降水量比起今年梅雨季节恐怕是有过之而无不及,可能我还经常开窗换气导致水气入屋,于是这墙角发霉就不值得奇怪了。 31 | 32 | 没想到墙壁发霉是会影响健康的,得赶紧搞定才是。网上找到一篇文章,说是要用牙刷用酒精用漂白粉 balabala 一顿折腾[^1],好麻烦的样子! 33 | 34 | [^1]: [房子常發霉到底該怎麼辦!!這幾招學起來,讓小霉點永遠消失在你家!!][1] 35 | 36 | 虽然麻烦,但是还是得把这些霉菌干掉才行,于是我就去淘宝看看有没有漂白粉或者漂白水卖。简单搜索了一下,想想似乎不用那么麻烦,或许淘宝上已经有人卖可以搞定墙壁发霉的东西了。于是我尝试搜索「墙壁 霉菌 清除剂」,还真被我找到了。 37 | 38 | 二话不说赶紧下单,大概 40 块钱的样子。今天终于到货,回到家把床挪开准备开搞。 39 | 40 | ![霉菌清除剂](//i.imgur.com/eZwcVtYl.jpg) 41 | 42 | 这货还分 AB 两种药剂,A 药剂负责干掉霉菌,其实就是漂白水,或者说是氯水,B 药剂负责巩固疗效,成分是啥我就懒得看了。 43 | 44 | 比较乌龙的是,一开始我糊里糊涂没看清楚,拿着 B 药剂就往墙上喷,等了老半天也没见霉菌消退。发现拿错药剂之后被自己的粗心惊到了。 45 | 46 | 用上了正确的药剂之后,效果非常明显,强氧化剂名不虚传,直接就把霉菌干趴下了。但是味道也非常明显,真个房间顿时充斥着医院的味道。 47 | 48 | ![效果拔群](//i.imgur.com/IxpljFpl.jpg) 49 | 50 | 不太喜欢氯水的味道,开着风扇吹风换气,但是空气中弥漫着的医院还是气息挥之不去。不知道今晚还有没有可能在卧室睡觉,搞不好只能睡客厅沙发了。 51 | 52 | [1]: http://www.how01.com/article_252.html 53 | 54 | 55 | -------------------------------------------------------------------------------- /source/_posts/load-css-asynchronously.md: -------------------------------------------------------------------------------- 1 | title: 异步加载非核心 CSS 2 | tags: 3 | - JavaScript 4 | categories: 5 | - Study 6 | hljs: true 7 | cc: true 8 | comments: true 9 | thumbnail: //i.imgur.com/Lj52nPzb.jpg 10 | date: 2015-11-17 03:03:46 11 | --- 12 | 13 | 14 | 昨天晚上在公司加班,和同事一起复盘双十一团队内各个系统的情况。突然收到邮件,啊哈,有人评论我的文章了~ 15 | 16 | 从手机上打开页面,发现卡的不要不要的,老半天才打开。回家后从电脑上打开一看,居然是一个 Web Font 挂了导致整个页面加载过程变得十分漫长。 17 | 18 | 为了让博客里面的代码块稍微好看一点点,我用[中科大的 Google Fonts 服务][1]加载了 Source Code Pro 这个字体。 19 | 20 | 21 | 22 | {% recruit %} 23 | 24 | 按照设定字体的惯例,我们会为字体设置 fallback,当 Source Code Pro 不可用时,自动降级为其他字体。什么叫「不可用」呢?比如找不到字体,或者加载字体超时之类的,应该算不可用吧。 25 | 26 | 然而不幸的是,在 Safari 上,加载 Web Font 这种事情,似乎是没有「超时」一说的[^1]。实际上当中科大的 Web Font 挂掉时,甚至连加载 Web Font 都走不到,请求描述 Web Font 的 CSS 就已经超时了。 27 | 28 | [^1]: [CSS Font Rendering Controls Module Level 1][2] 29 | 30 | 好吧,不管怎么说,博客服务器虽然没挂,但是在渲染上却被一个锦上添花的 CSS 给拖垮了。就在刚才我还在复盘中说「对弱依赖要做好容错、超时和自动降级,不要因为弱依赖不稳定而影响主流程」,结果现世报这就来了。 31 | 32 | 如何加强页面渲染的稳定性呢?一开始我受思维定势的影响,想要给 `` 标签增加 timeout 属性。但是,HTML 标准里面没这种东西啊。好吧,那么像 ` 45 | 46 | 47 | 50 | ``` 51 | 52 | 然后指定的 CSS 就异步加载了,即使某个 CSS 加载出来需要很长时间,也不会阻塞页面渲染,只是在 CSS 成功加载之后去重绘页面。 53 | 54 | 然后我就用这个神器把博客里能异步的 CSS 请求都给替换为异步的了~ 55 | 56 | 57 | [1]: https://servers.ustclug.org/2014/06/blog-googlefonts-speedup/ 58 | [2]: https://tabatkins.github.io/specs/css-font-display/#intro 59 | [3]: http://codepen.io/Tigt/post/async-css-without-javascript 60 | [4]: http://blog.yoav.ws/2011/10/Unblocking-blocking-stylesheets 61 | [5]: https://github.com/filamentgroup/loadCSS 62 | -------------------------------------------------------------------------------- /source/_posts/look-back-2015.md: -------------------------------------------------------------------------------- 1 | title: 纪念和博客一起成长的 2015 年 2 | tags: 3 | - Blogging 4 | categories: 5 | - Life 6 | thumbnail: https://i.imgur.com/ShjVKT5.jpg 7 | cc: true 8 | comments: true 9 | date: 2016-02-17 01:25:29 10 | --- 11 | 12 | 这几天突然发现,我认真写博客,大概有一年的时间了。除开 2014 年 8 月写的那篇介绍 pyiconv 的博文不算,2015 年 1 月 6 日 和 7 日这两天,应该是我认真写博客的开始。 13 | 14 | 可以说,去年一年里,写博客成了我生活中一个重要的活动。写到这里的时候,我无意中看了一眼页面预览,100 POSTS,57 TAGS。 15 | 16 | 17 | 18 | {% recruit %} 19 | 20 | 我知道实际上并没有这么多,因为草稿箱里还躺着三篇博文草稿,其中一篇写了一半,是关于春节期间我基于 Vert.x 框架写的一个小玩意,另外两篇只有个标题,内容却一个字都没动。 21 | 22 | {% blockquote 潘家邦 http://blog.jamespan.me/2015/03/20/recruiting-on-blog/ 谈谈在独立博客发布招聘信息那些事 %} 23 | 我希望以后回头看看我这段与时间赛跑的日子,能有一些属于我的东西留下,有一些东西能证明我的能力,不需要我多费口舌就能让别人知道我是谁。 24 | {% endblockquote %} 25 | 26 | 差不多一年前,我在一篇博文中写下上面这段话。天下熙熙,皆为利来,天下攘攘,皆为利往,那时候的我写博客不求利,但图名。于是为了让更多的同行看到我的文章,我先是把文章分享到 Startup News,然后找朋友帮顶。再后来是分享到开发者头条。 27 | 28 | 后来渐渐有了一些经常交流的读者,也因此认识了一些朋友,而我的博文写作也开始不仅仅局限于技术话题,开始有一些生活上的流水账,还有工作上的吐槽。 29 | 30 | 也许就像李如一在「IT 公论」中说的,湿的东西才容易粘住,比较出乎我的意料的是,相比起我放在 [Study][1] 分类下的技术向博文,有些读者更喜欢我放在 [Life][2] 分类下的扯淡向文章。或许正是这些湿货,让这个博客背后的我,显得更加真实。 31 | 32 | 被读者误认为是「大神」实际上却很菜的我,也会没有 Google 和 StackOverflow 就写不出代码,也会[手贱把电脑屏幕弄裂然后很心痛地花上几千大洋修好][3],[骑自行车也会摔][4],[加班多了没时间锻炼身体也会难受][5]。更重要的是,我还是一个年仅 22 岁的男孩纸,我也在学着像大多数的年轻人一样过业余生活,学着[买质量不错尺寸合身的品牌服饰而不是淘宝货][6],学着像大多数年轻人一样出去吃好吃的,学着像大多数年轻人一样出去看电影,学着夸女孩子好看而不是问类似「是不是公司要求带妆上班」的愚蠢问题。 33 | 34 | 再后来,我收到了一位远在湾区的同行的感谢邮件,这令我十分感动。那时候我才发现,最开始写博客时的功利心已经淡了,更多的是一种习惯的力量在驱使,驱使我去分享那些我觉得有价值的或者有趣的东西,或许是技术向的,或许是生活向的。或许写博客早已成为我生活的一部分了。 35 | 36 | 最开始的时候,为了寻找技术向博文的主题,我开始研读 Guava 的源码,被其优雅的设计倾倒,就有了「Guava 是个风火轮」系列博客。计划中原本是从去年 4 月开始,写一本被我称之为「Guava Magic」的书,但是天有不测风云,从那时候开始工作上突然忙的不可开交,写书的事情就耽搁了。 37 | 38 | 工作再忙也挡不住写博客的热情,下班再晚回家之后也要自己折腾几个小时。去年四月左右我开始接触 Docker,在公司里面应该勉强算是比较早的。不经意间上帝就这样悄悄为我打开一扇门,一扇通向云计算的门。后来碰上 Gitcafe 三天两头挂一次,Github Pages 国内访问不便,我就开始了博客折腾之旅。买了一台阿里云服务器玩 Docker,然后为了高可用又买了一台。 39 | 40 | 那段时期的博文围绕着折腾博客展开,一会是自动化部署,一会是高可用架构,一会是负载均衡策略,一会是资源内联插件……没有折腾就没有成长,因为折腾博客,我接触并学习了 Docker、Openresty、NGINX、Ansible、Travis CI 等等基础设施或者软件服务,还顺便学习了一点 Golang。为了给 Hexo 写插件,我还把大学时期就学习过却一直没机会实践的 Node.js 给实践了一把。 41 | 42 | 前不久我离开物流行业,进入了云计算行业,可谓得偿夙愿。当初写博客所图的名也算小有收获,求仁得仁。再后来,在琨少的推荐下入驻云栖社区,开始了写月经贴的日子,这个月的博文还没写出来呢哈哈。 43 | 44 | 接下来比较长的一段时间里,我会克制写博客分享的欲望,专心写书,把我之前承诺的「Guava Magic」完结,毕竟不能总令对我的未来有所期待的朋友失望,不是吗?理论上除了每月一篇技术向的首发于云栖社区的博文,不会再有其他博文更新。 45 | 46 | 喜欢就会放肆,但爱是克制。 47 | 48 | 今天看到一句挺有意思的话:最怕一生碌碌无为,还安慰自己平凡可贵。 49 | 50 | 愿新的一年里,有所进步。 51 | 52 | 共勉! 53 | 54 | 55 | [1]: /categories/Study/ 56 | [2]: /categories/Life/ 57 | [3]: /2015/04/03/a-repair-of-the-retina/ 58 | [4]: /2015/12/20/oh-my-giant-atx-777/ 59 | [5]: /2015/11/03/oh-my-programmer-back/ 60 | [6]: /2015/06/14/minimalist-lifestyle/ 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /source/_posts/luit-with-tmux.md: -------------------------------------------------------------------------------- 1 | title: Tmux、Luit 杂谈 2 | tags: 3 | - Linux 4 | - Encoding 5 | categories: 6 | - Study 7 | hljs: true 8 | cc: true 9 | comments: true 10 | thumbnail: https://ws1.sinaimg.cn/small/e724cbefgw1et0lz06e18j212p0nywk0.jpg 11 | date: 2015-06-12 00:13:02 12 | --- 13 | 14 | 最近有一天在半睡半醒间折腾应用的部署脚本,折腾好了天也亮了。期间顺便折腾了一下 Tmux 和 Luit,弄了一套勉强可用的 Tmux 配置出来。 15 | 16 | sdfsdTmux 一般都是安装在服务器使用才能发挥最大效用,本地使用的话,似乎只能当作一个终端复用的工具,对效率没有太明显的提升。 17 | 18 | 19 | 20 | {% recruit %} 21 | 22 | 其实我大学期间就有用过 Tmux,而且那时候我还给实验室的服务器装了个 Tmux 来用着。但是那时候我没有怎么折腾配置,就着原生的配置,切切窗口,还觉得要想复制一个东西太麻烦了。 23 | 24 | 后来工作之后,公司的服务器上面没有 Tmux,我就渐渐的越来越少接触 Tmux 了,iTerm2 太好用也是其中一个原因。 25 | 26 | 最近我看到几篇关于 Tmux 的博文[^1][^2],把 Zsh + Vim + Tmux 吹的天花乱坠,我的心里又开始长草。 27 | 28 | [^1]: [文本三巨头:zsh、tmux 和 vim][2] 29 | [^2]: [10 Killer Tmux Tips][5] 30 | 31 | 最后参考了 fooCoder 的博文《[终端环境之tmux][3]》和 Treri Liu 的 Tmux [配置][4],以 fooCoder 的配置为基础,加入了其他我觉得有意思的配置。 32 | 33 | ![Tmux 终端复用](https://ws1.sinaimg.cn/large/e724cbefgw1et0lz06e18j212p0nywk0.jpg) 34 | 35 | 由于某种不可抗力,我登录到服务器之后,总是没法避免的需要修改一下终端的文本编码,不然日志什么的都会乱码。之前我一直是手动修改,最近我终于感到厌烦,希望结束这一切重复的动作。 36 | 37 | 那么该如何做呢?我找到两种方案,各有所长。 38 | 39 | 第一种是基于 iTerm2 的编码切换方案,来自《[Mac OSX iTerm2 终端UTF-8和GBK编码自由切换][6]》。 40 | 41 | ```bash 42 | #!/bin/bash 43 | # 使用GBK Profile 44 | echo -ne "\033]50;SetProfile=GBK\a" 45 | # 环境编码切换为GBK 46 | export LANG=zh_CN.GBK 47 | export LC_ALL=zh_CN.GBK 48 | # 更改当前 iTerm2 tab title 49 | echo -ne "\033]0;"$@"\007" 50 | $@ 51 | echo -ne "\033]0;"${PWD/#$HOME/~}"\007" 52 | # GBK任务完成后,自动切换回默认编码(UTF-8) 53 | echo -ne "\033]50;SetProfile=Default\a" 54 | export LANG=zh_CN.UTF-8 55 | export LC_ALL=zh_CN.UTF-8 56 | ``` 57 | 58 | 第二种是使用 Luit 做编码转换。 59 | 60 | Luit 似乎没有被收录到 brew 仓库,需要手动下载编译,不过也是很简单的。 61 | 62 | ```bash 63 | wget -c ftp://invisible-island.net/luit/luit.tar.gz 64 | tar -xzvf luit.tar.gz 65 | cd luit-20141204/ 66 | ./configure 67 | make 68 | make install 69 | ``` 70 | 71 | 搞定之后直接执行下面的命令就可以用指定编码登录服务器了。 72 | 73 | ``` 74 | TERM="xterm" luit -encoding ssh 75 | ``` 76 | 77 | 不知什么缘故,我的 Hexo 环境出了点问题,启动的 hexo server 没法像以前一样监听文件的变更了,真是要命。出问题的可怜虫还不止我一个,我在 Hexo 的 issue 列表里面找到了类似的[问题][1]。希望这个问题能早点解决,不然写博客的体验那是大大的糟糕。 78 | 79 | [1]: https://github.com/hexojs/hexo/issues/1175 80 | [2]: http://blog.jobbole.com/86571/ 81 | [3]: http://foocoder.com/blog/zhong-duan-huan-jing-zhi-tmux.html 82 | [4]: https://github.com/Treri/dotfile/blob/master/tmux/tmux.conf 83 | [5]: http://www.sitepoint.com/10-killer-tmux-tips/ 84 | [6]: http://blog.chenxiaosheng.com/posts/2013-10-29/mac_osx_iterm2_utf8_gbk_switch.html 85 | 86 | -------------------------------------------------------------------------------- /source/_posts/minimalist-lifestyle.md: -------------------------------------------------------------------------------- 1 | title: 扔掉那些垃圾,开始简单生活 2 | tags: 3 | - Thinking 4 | categories: 5 | - Life 6 | - Essay 7 | thumbnail: 'https://ws3.sinaimg.cn/small/e724cbefgw1et3ud93atyj208o0bujrs.jpg' 8 | cc: true 9 | comments: true 10 | date: 2015-06-14 20:27:23 11 | --- 12 | 13 | 不久之前,我的房间里堆满了垃圾。其实这些东西也不是真正意义上的垃圾,都是一些鸡肋的衣物、杂物,食之无味,弃之可惜。 14 | 15 | 16 | 17 | {% recruit %} 18 | 19 | 大概是从大学的时候开始,每个季度我总是去淘宝上面弄几条廉价的衣物,然后就凑合着穿着。毕竟一分钱一分货,一毛钱两分货,一块钱三分货,那种价钱下能有什么好东西,自然是穿的时候也没多舒服,穿了一两个季度就不想再穿了,然后下一个周期再去淘宝弄几条。 20 | 21 | 简直就是恶性循环。四年下来我就多出了许多破烂,但是又没舍得扔,想着或许哪天这些衣物还能派上用场。后来,这些衣服就这样被我带到了杭州。 22 | 23 | 刚到杭州那一年也是死性难改,接着在淘宝买廉价衣物,洗了几次就变形了还是没头没脑的穿着。 24 | 25 | 如果不是前段时间起了搬家的念头,我都没有发现自己的生存状态如此糟糕。 26 | 27 | 真正下决心作出改变,还需要感谢知乎。有一天早上我看到这么一个瞎扯,一语惊醒梦中人。 28 | 29 | {% blockquote @ScottDong http://zhi.hu/PfsM %} 30 | 问:关于房间的整理与收纳,有什么好的建议? 31 | 32 | 答:贵!我有过被房东赶出门的经历,树立了一个坚定的信念——买贵的东西。你现在买什么价位的衣服?电脑?各种用品?价格直接翻 10 倍!于是你会发现,你就不需要整理什么东西了,因为每样东西就那么几件。 33 | {% endblockquote %} 34 | 35 | 太机智了,不用想着怎么去收拾这一堆破烂,直接扔掉扔掉,买贵的买好的,重质不重量。贵的东西不一定好,好的东西一定贵。 36 | 37 | 我们常常说一个优秀的程序员比十个平庸的程序员不知道高到那里去,这个道理也适用于各种物品,一个好的东西,比十个廉价的东西不知道高到哪里去。 38 | 39 | 于是我把之前淘宝买的山寨货全都扔掉了,去附近的一个商业中心购置了几套衣服鞋子,价格虽然没有比之前的翻 10 倍,但也差不多了。 40 | 41 | 至于电脑手机,目前在用的设备在消费品中已经可以说是最好的了,想翻 10 倍那就得是奢侈品了。 42 | 43 | 现在已经开始渐渐感受到这种简单生活带来的好处,不被物品所束缚。只要是对我没用的东西,该扔扔,不能手软。 44 | 45 | 这几个星期来我也扔了不少东西,反正这些破烂玩意也没法送人,不如扔了省事,给自己留个清净。我送人的东西从来不是自己觉得鸡肋的东西,那样多没诚意,别人又不傻。 46 | 47 | 断舍离,就是要从自己出发,把那些对自己没用的东西处理干净,然后让自己从外到内重获新生。 48 | 49 | 扔东西还在继续,同时还要做好源头控制,不再去买那些廉价的东西,不再去买那些自己没什么机会用的到的东西,如无必要,勿增实体。 50 | 51 | {% blockquote 王垠 《人的价值》 http://www.yinwang.org/blog-cn/2015/01/29/human-value/ %} 52 | 在我的心目中,物质是卑贱的,是为人服务的。所以我不怜惜钱,车子或者其它物品,不觉得穿了什么衣服或者开了什么车,就凸显了自己的价值。在我的心里,我的价值大于所有的这些:名牌车子,名牌衣服,名牌大学,知名教授,高深的理论,知名公司,亿万富翁,甚至民族传统。我的个人价值如此之大,所以我不惜抛弃名牌大学的学位,我不屑为某些知名大公司工作。我毫不在意别人怎么看我,我毫不在意别人定义的所谓“成功”。我最得意的成就,其实就是我自己。这就是我所谓的“个人价值”,这跟一个人对于其它人的“利用价值”,是完全不同的两回事。 53 | {% endblockquote %} 54 | 55 | 物质是为人服务的,我的物品应该是为我服务的。不幸的是,我之前把关系弄颠倒了,反被物品所累。 56 | 57 | 《断舍离》中讲到一个案例,有人家里收藏这一套名贵的餐具,却感觉自己配不上这套餐具而不忍使用。看别人的故事总觉得可笑,自己过去又何尝不是一样的心态? 58 | 59 | > 当你所有东西能放进一个行李箱,你就等于拥有了全世界。 60 | 61 | 放下身外之物带来的烦恼,希望自己能够变得更好,也希望有一天我能像王垠一样,最得意的成就,就是我自己。 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /source/_posts/movies-during-national-day.md: -------------------------------------------------------------------------------- 1 | title: 新世界的大门打开了——国庆假期的电影之旅 2 | tags: 3 | - Movie 4 | categories: 5 | - Life 6 | cc: true 7 | comments: true 8 | date: 2015-10-05 05:05:11 9 | --- 10 | 11 | 说来也是可笑,二十多年了,都没去过几次电影院。想想那数的过来的几次,无非都是小学初中的时候被迫去海口的工人电影院看那些什么教育片,「美丽的大脚」之类的。 12 | 13 | 高中之后开始玩电脑,而且玩的挺溜的,于是各种电影唾手可得。那是最好的时代,也是最坏的时代,没有人在意版权不版权的,只管分享和下载。 14 | 15 | 再后来上了大学,学渣属性叠加了死宅、穷逼、屌丝和单身狗四大属性,对电影院这种花式虐狗的地方就更是敬而远之。于是乎,本科四年,未曾踏入电影院半步。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | 如今的我,除了死宅、穷逼、屌丝和单身狗,还叠加了码农属性,这可不得了,天上飘来五个字,「注定孤独终生」。就算注孤生已成定局,本屌丝也想像个正常的年轻人一样生活玩耍,于是我开始学习身边的年轻人的业余生活和娱乐方式。 22 | 23 | 敏政君是一个犬系男孩纸,喜欢户外活动,喜欢素描和摄影,喜欢和 PLMM 们开轰趴,谁不喜欢呢😂。敏政君是我的产品经理(之一),我是敏政君的开发(之一)。感谢那天邀请我去轰趴,为我打开了新世界的大门,原来年轻人的周末生活也可以如此丰富多彩(误,除了看书编码写博客,还可以玩杀人游戏。 24 | 25 | 为什么我会突然想到要去电影院受虐呢?其实原因很简单,就是我想看电影了,而互联网上找不到资源,想花钱买都没地方收,只好去电影院了。让我动了心的电影,是「夏洛特烦恼」。 26 | 27 | ![](https://ws3.sinaimg.cn/mw1024/e724cbefgw1ewprgllvyij21kw0opam6.jpg) 28 | 29 | 这电影还蛮搞笑的,毕竟就是一部喜剧。看这种电影就跟看搞笑动漫似的,图个开心。嗯,这部片比「煎饼侠」不知道高到哪里去! 30 | 31 | 第一张电影票,纪念一下。因为第一次自己去买票看电影,还因为不懂潜规则闹了个笑话。明明是在猫眼买的电影票,结果去中影的机器上扫了半天二维码,输入了 N 次验证码,当然都是白忙活。最后在路人的提醒下找到了猫眼的机器,把票刷出来了。不过也不能全怪我,谁让中影的机器上写着,「从以下平台购买的电影票均可在此领取」中就包含着猫眼的 Logo 呢。 32 | 33 | ![](https://ws3.sinaimg.cn/mw1024/e724cbefgw1ewprxxc017j21kw1kw7s1.jpg) 34 | 35 | 我还发现猫眼的机器,刷猫眼 App 中的二维码没啥反应,需要刷 Wallet 中的二维码才行。 36 | 37 | 我还发现,现在放电影之前居然有好几分钟的广告!广!告! 38 | 39 | ![](https://ws1.sinaimg.cn/mw1024/e724cbefgw1ewprlc4zqpj21kw0ontkb.jpg) 40 | 41 | 没想到连电影院都被广告占领了,优酷好歹也就 90 秒的广告,电影院这广告是几分钟啊。 42 | 43 | 因为买的是晚上十点多的场,电影放完的时候就十二点多了,从印象城出来是披星戴月。 44 | 45 | ![](https://ws3.sinaimg.cn/mw1024/e724cbefgw1ewprpyeonaj21kw16oatv.jpg) 46 | 47 | 至于为什么要买这个场次的,也许是因为考虑到平时要想看电影,这个场次是为数不多的选择吧? 48 | 49 | 第二天晚上又跑去电影院了,看的是「解救吾先生」,还是十点多的场。这个奇怪的称谓,让我不由自主想起高中时候看过的一本 YY 小说「极品家丁」,里面的主角林三的一个化名就是「窝老攻」,是不是和「吾先生」异曲同工? 50 | 51 | 这次没有抓拍影片标题,也许是觉得在以后的日子里,去影院看电影会成为生活中的一种常态,不必去特意记录罢。 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /source/_posts/mysterious-bug-of-hexo.md: -------------------------------------------------------------------------------- 1 | title: Hexo Server 的一个迷の bug 2 | tags: 3 | - Blogging 4 | categories: 5 | - Study 6 | cc: true 7 | comments: true 8 | thumbnail: 'https://ws2.sinaimg.cn/small/e724cbefgw1et26nuhrnhj20c60b4mxl.jpg' 9 | date: 2015-06-13 10:21:25 10 | --- 11 | 12 | 13 | 前几天我突然发现,Hexo 启动 server 之后,没法感知文章的修改然后自动刷新页面。这个问题让我很困扰啊。虽然我写 markdown 的时候不需要实时预览,但是修改主题的时候如果没有实时预览,根本就没法开心地玩耍了。 14 | 15 | 然后我又重新踏上了折腾之路。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | # 入局 # 22 | 23 | 服务器没法感知文件更新,这种事情用脚趾头想都知道是监听文件系统的模块出了问题。Hexo 有一个核心模块叫 hexo-fs,专门负责和文件系统打交道。然后 hexo-fs 依赖了 [chokidar][1],这是一个监视文件系统各种事件的类库,它又依赖了 [fsevents][2] 去实现 OS X 上对文件系统事件的监听。 24 | 25 | 虽然我最近一段时间都没有去更新 hexo 的各个模块,但是我还是觉得问题出在 node 模块上面。于是我开始各种调整 fsevents 的版本,然后各种 npm install。{% heimu 然而并没有什么卵用。 %} 26 | 27 | # 困局 # 28 | 29 | 后来我尝试着把 Hexo 整个干掉,在博客目录旁边新建一个目录,然后用 Hexo init 出来一个全新的只有 Hello World 的博客。没想到这个全新的博客也遭遇了同样的问题。 30 | 31 | 想到我之前还搞了一个 Docker 镜像,里面有一个好用的 Hexo 环境。在那个版本的 Hexo 环境中,一切都是正常的,修改了文件是能够得到实时更新的。于是我又尝试着把 Docker 中 Hexo 环境的 package.json 文件弄出来,把范围版本修改成固定版本,然后把 Hexo 环境的 node\_modules 目录砍掉重练。{% heimu 然而并没有什么卵用。 %} 32 | 33 | # 难友 # 34 | 35 | 一筹莫展,无计可施。没想到我也有被一个 bug 折腾的死去活来的时候。 36 | 37 | 只好求助于 Google 了。 38 | 39 | 然而并没有几个人遇到了和我一样的问题。最后我还是在 Hexo 的 issue 列表[^1]中找到了难友。 40 | 41 | [^1]: [\`hexo server\` fails to update content after a while (3.0.0)][3] 42 | 43 | 但是,整个 issue 里面就只有 3 个人啊!这个问题太小众了啊!其他两个家伙也没办法解决啊!解决问题还是只能靠自己啊! 44 | 45 | 不过我还是从 issue 交流中获得了一些线索。另外一个遇到同样问题的家伙用的是 Debian,也就是说这个 bug 不是 OS X 独占的了,可以把 fsevents 的问题排除。 46 | 47 | # 破局 # 48 | 49 | 昨天,我突然想起前段时间我弄了一个虚拟机安装的 OS X 10.10,虽然卡的不行但是勉强能用。于是我在虚拟机里面打了快照之后,开始安装 Node.js 环境,Hexo 环境。这样子安装出来的博客居然是好的! 50 | 51 | 怀着激动的心情,我把本机里面的 Node.js 连同 Hexo 全部砍掉重练,然后满怀期待的在之前的博客目录启动 server。我似乎听到了心碎的声音。 52 | 53 | 为什么会这样。我心有不甘,然后随手在家目录新建了一个 Hexo 环境。然后,奇迹!粗!线!了!这个博客环境居然是好的。 54 | 55 | 然后我尝试着把之前的博客目录复制一份到家目录,然后这个博客也就这样莫名其妙的好了。 56 | 57 | 于是,我的博客目录就从 ~/Sites/blog.jamespan.me 迁移到了 ~/blog.jamespan.me,可怜的家目录又多出一个目录来。 58 | 59 | 后来又尝试了一下,似乎博客目录放到其他地方比如 ~/Downloads 或者 ~/Documents 都是可以的,唯独 ~/Sites 不行,至于原因,还不清楚。 60 | 61 | 在把各种尝试时候创建出来的博客目录删掉时,不小心用 rm -rf 把家目录里面的博客目录干掉了。顿时心都凉了。自从我把 Hexo 升级到 3.x,之前用的一个把博客文章备份到 github 的插件就不能用了,于是我除了偶尔记得用 Time Machine 做全盘备份之外,对博客的单独备份一直没怎么做。 62 | 63 | 还好我在 ~/Sites 目录还有一个博客环境,家目录那个是从那里复制出来的,如果是移动出来的,我就只能老老实实去时光机找备份了。 64 | 65 | 于是我又可以愉快的写博客改主题了~ 66 | 67 | 另外,[Browsersync][4] 真是神器,我可以同时在 iPhone、iPad、Chrome 上调试页面,推荐安装 Hexo 插件 [hexo-browsersync][5]。 68 | 69 | [1]: https://github.com/paulmillr/chokidar 70 | [2]: https://github.com/strongloop/fsevents 71 | [3]: https://github.com/hexojs/hexo/issues/1175 72 | [4]: http://www.browsersync.io 73 | [5]: https://github.com/hexojs/hexo-browsersync 74 | -------------------------------------------------------------------------------- /source/_posts/oh-my-giant-atx-777.md: -------------------------------------------------------------------------------- 1 | title: 高速过弯的时候抱死后轮,自行车也会漂 2 | categories: 3 | - Life 4 | cc: true 5 | thumbnail: //i.imgur.com/8ePQrMcm.jpg 6 | comments: true 7 | date: 2015-12-20 23:59:52 8 | --- 9 | 10 | 上一辆自行车大约是一年之前在天猫上买的,花了一下午自己组装。毕竟是门外汉,又没有组装自行车的专用设施不便调校,刚组装好就觉得怪怪的,后轮转动的时候还一直和刹车片有摩擦。 11 | 12 | 后来骑着骑着后轮不摩擦刹车片了,但是传动系统开始吱吱呀呀地响,不停地响,难受极了。后来我尝试着洗车,洗链条,上润滑油,稍有好转,但是过了一两周就被打回原形。小区和公司都在荒郊野外,连个正经修车的地方都没有,想把维护自行车的工作外包出去都不可能。 13 | 14 | 最近我在小区附近发现了一个捷安特专卖店,似乎找到了从吱吱呀呀中解脱出来的希望! 15 | 16 | 17 | 18 | {% recruit %} 19 | 20 | 这周五下班后去捷安特专卖店看看,在老板的推荐下买了一辆 ATX 777,2015 款。据老板说这辆车算是街车,性价比高之类的,现在还搞活动,要么车价减 400,要么送 500 的配件。我是选了要 500 的配件的。 21 | 22 | 之所以决定在专卖店买车,看中的就是配套的售后服务啊,以后就可以花点钱把清理和保养自行车这种蛋疼的事情外包出去了,毕竟我还是不是发烧友,自己花时间学这些东西,再亲手去搞,时间成本太高,不如多写几行代码去。 23 | 24 | 由于我不赶时间,老板决定组装一辆新车给我。老板姓童,是捷安特认证的技师,本身就是个骑行发烧友。据说他自己那辆改装过的自行车值好几万呢。 25 | 26 | 老板一边组装,一边给我讲解 ATX 777 的重要部件,比如前后轮的轴都是禧玛诺的,飞轮也是禧玛诺的,花鼓和刹车碟是中锁的,刹车是油碟的,前叉锁是线控的…… 27 | 28 | 看着老板熟练的操作,我不禁想,如果当初没有自己瞎折腾该多好,直接在专卖店一步到位,还能少花点钱少受点吱吱呀呀的罪。贪小便宜吃大亏差不多就是这个理吧。 29 | 30 | 组装得差不多之后,老板开始带我选配件。照例我是需要挡泥板的,虽然这样比较 low,但是在公路上骑行的话挡泥板还是很有用的。然后还要了码表、行李架、停车架,还有一个带胎压计的打气筒。 31 | 32 | 配件组装完成后,老板开始给我讲一些一看就知道我不知道的知识,比如雨天骑车之后要用布把链条、飞轮和前叉擦干,第二天给链条飞轮喷一点 WD-40,千万不要喷到刹车碟上,比如后飞轮变速的时候要同时踩脚踏…… 33 | 34 | 后来回家后翻看捷安特的说明书发现这些其实都在说明书上,属于最基础的知识,然而当初在网上买的那辆自行车的说明书毛都没有,于是我就以各种错误的操作骑了一年多带变速的自行车。 35 | 36 | 骑行锻炼的时候不在于骑快,而是要维持一个稳定的踏频,平地前后都挂中间齿轮,踏频维持在 90/min,碰到上坡后轮就换大齿轮,还是保持 90/min 的踏频。 37 | 38 | 周六的时候按照这样的踏频从小区骑到公司,行程 6km,后背微微出汗。 39 | 40 | 我想我喜欢上骑行这种锻炼方式了,至少在现阶段挺合适的。 41 | 42 | 之前我在做有氧运动的时候都是选择跑步,但是运动中断了大半年之后,我发现自己跑不动了,好几个星期了,跑个十分钟小腿就开始疼,十五分钟就坚持不下去了。这么短时间的有氧运动没啥效果啊,但是实在是疼得不要不要的。健身房的固定单车不知道为啥坐垫搞得那么大,坐起来不如山地车的坐垫舒服,而且惯性有点奇怪。 43 | 44 | 如果天气好的话,下班后我或许可以在小区内绕圈,如果天气不好或许可以去健身房骑骑固定单车。 45 | 46 | 于是周日早晨我去迪卡侬买了一套冬季的骑行衣物,几条打底骑行内衣,一条骑行外套。骑行裤没买,感觉骑行裤在屁股那里缝了一大块海绵,看起来好奇怪好羞耻,穿起来也不舒服。 47 | 48 | 周日下午我就真的骑着自行车在小区里面绕圈了,绕了 10km。小区里面的柏油路不错,美中不足的是有减速带,而且有些减速带没法从两边绕过,只好停止踩踏,过了减速带颠簸一下接着踩。 49 | 50 | 比较悲剧的是,有一次我过了减速带之后,想研究研究有没有比较高速通过减速带又不太颠簸的方法。于是我停车,掉头,往回骑,尝试从减速带旁边的大理石绿化带边缘上绕过。头文字 D 里面不是有一个借助水沟过弯的桥段嘛,我也想搞个类似的。 51 | 52 | 但是,我在拐弯的时候,直接摔倒了!!! 53 | 54 | 不但膝盖破了点皮,还把早上刚买的骑行外套磨破了个小口子,自行车的右侧副把、脚踏磨花了。幸好人没大事,皮外伤。虽然当时马上就跳起来,但还是站着,手撑着大腿缓了好几分钟。 55 | 56 | 缓过来之后,感觉今天不能继续骑行训练了,就骑车回去休息吧。回去的路上经过一个直角弯,那时候车速大概 20km/h 吧,刚入弯就迎面开来一辆汽车,吓得我赶紧刹车。当时先刹的后轮,有点用力直接抱死了,然后,自行车就侧滑了。 57 | 58 | 吓死爹了。 59 | 60 | 我还不会自行车漂移啊,被这突如其来的侧滑吓了一跳,赶紧松开后闸,再前后闸一起刹车,总算没侧滑地停下来了,对面的来车也停下来了,捡回一条小命。 61 | 62 | 看起来油碟的制动效果比线碟强太多了,还需要一段时间适应,之前那辆用的线碟,直到最近轮胎磨秃了抓地力不足了,才能在急刹车的时候搞出后轮抱死。 63 | 64 | 65 | -------------------------------------------------------------------------------- /source/_posts/oh-my-programmer-back.md: -------------------------------------------------------------------------------- 1 | title: 噢,我的码农背 2 | tags: 3 | - Exercise 4 | categories: 5 | - Life 6 | thumbnail: //i.imgur.com/veJ66PU.jpg 7 | cc: true 8 | comments: true 9 | date: 2015-11-03 22:52:22 10 | --- 11 | 12 | 13 | 这两天请了年假在家休息。经历了半年多的高强度工作和缺乏锻炼,我大约在一个多月前出现有点严重的背疼。歪果仁把这种职业病叫做「[Programmer Back][1]」,我把它翻译为「码农背」。「鼠标手」和「颈椎病」是另外两个臭名昭著的程序员职业病,至于「腰椎盘突出」似乎还不是程序员的专属,坐着上班的所谓「白领」都有风险。 14 | 15 | 具体的表现是斜方肌僵硬疼痛,右侧菱形肌拉伸、按压疼痛,第七颈椎棘突以及下面几个棘突按压疼痛。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | ![](//i.imgur.com/Wn3k6Q1.png) 22 | 23 | 周日的时候,背部疼痛得愈发厉害,站着啥都不干也感觉难受,上炕都费劲。我有一种预感,如果这次不慎重对待,那么我的码农生涯可能就要到此终结了,说好的出任 CTO,迎娶白富美呢 TnT 24 | 25 | 其实我已经不是第一次经历背部疼痛了,只不过前几次都在疼痛早期就被我强行用力量训练打发了,这次由于生不逢时,拖了许久都没时间去锻炼,于是小病拖成大病。 26 | 27 | 第一次遭遇「码农背」是我大三的时候。高中时期就没怎么锻炼,到了大学,高强度的写了两年代码,到了大三的时候就开始得到报应了。那时候赶紧买了南开里一个健身房的年卡,吭哧吭哧把疼痛赶跑了。 28 | 29 | 第二次是去年双 11 之后,因为搞双 11 我的健身计划中断了两个月,于是背又疼了,还是老地方。还好有之前几个月锻炼的底子,恢复训练之后没几天就康复了。 30 | 31 | 第三次就是现在。码农背仿佛附骨之锥,每当我身体虚弱的时候,它就会跑出了兴风作浪。这几天的训练让我感觉好了许多,其实很多职业病就是缺乏锻炼导致的,最有效的治疗方法也是恢复锻炼。 32 | 33 | > 要么运动,要么读书,身体和灵魂,必须有一个在路上。 34 | 35 | 针对码农背,我选择的是对上背部做力量训练,比如高位下拉,硬拉 + 杠铃耸肩,配合以跑步还有其他腿部臀部的力量训练作为交替。 36 | 37 | 经过三天的训练,背部感觉好了些,明天又可以去上班了。希望下班后还能有时间去健身房练练。 38 | 39 | 最近突然发现 Podcasts 有点意思,我目前主要收听的是 IPN 出品的「[内核恐慌][2]」,又名「中老年程序员夜话」,感觉听吴涛和 Rio 扯扯淡还是蛮有趣的~ 40 | 41 | 今天突然发现,我的 iPhone 5s 出现了电池标量还没用完就自动关机的情况,关机点是 20%。手机用了还不到两年,这么快就寿终正寝了?网上的说法是电池坏了,于是我就找了个 O2O 修手机的网站,好像叫「闪修侠」的,提交了一笔上门修手机的订单。 42 | 43 | 说起来其实蛮伤感的,手机都快用坏了,却还没写出一个像样的 iOS App。 44 | 45 | 刚提交不久就发现一个让人惊异的说法,链接找不到了,说是把「电量百分比」关掉,就不会出现这种电还有好些就直接关机的情况。当时看到的时候简直惊呆了,感觉有点自欺欺人的样子!但是我试了一下,好像真的有用! 46 | 47 | 过几天看看效果好了,如果实在不行就花个几十一百换个电池好了,最近买不起 iPhone 6s,全身上下都是穷 TnT 48 | 49 | 愿程序员同行们远离码农背、鼠标手和颈椎病! 50 | 51 | 噢对了,最近似乎「[山河故人][3]」挺有名的,Fenng 也给了好评,昨晚从微博看到 Fenng 说今天是[最后一天][4]了,于是我赶紧买了今天最后一场的票。 52 | 53 | ![](//i.imgur.com/PtMPLDWh.jpg) 54 | 55 | 我能说我没怎么看懂么😂 56 | 57 | [1]: http://www.hanselman.com/blog/TheComputerBackPainAndTheProgrammer.aspx 58 | [2]: https://ipn.li/kernelpanic/ 59 | [3]: https://movie.douban.com/subject/25890005/ 60 | [4]: http://weibo.com/1577826897/D22Cg99mn 61 | -------------------------------------------------------------------------------- /source/_posts/one-year-in-ali.md: -------------------------------------------------------------------------------- 1 | title: 不知不觉,加入阿里巴巴一年了 2 | categories: 3 | - Work 4 | photo: 'https://ws4.sinaimg.cn/large/e724cbefgw1etunkma721j215i05840j.jpg' 5 | cc: true 6 | comments: true 7 | date: 2015-07-08 22:10:47 8 | --- 9 | 10 | 11 | 12 | 13 | 2014 年 7 月 7 日 下午,我办理了入职手续,于是我摆脱了学生的身份,摇身一变成为了研发工程师。 14 | 15 | 一年过去了,2015 年 7 月 7 日,早上一到公司打开阿里内外,就看到入职一周年的祝贺。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | ![一周年快乐](https://ws1.sinaimg.cn/large/e724cbefgw1etuneoh8hjj21kw0uqjw6.jpg) 22 | 23 | 我一开始没太在意,开始像平常一样啃面包,然后师兄突然出现在身后,对我说“一周年快乐”,并送给了我一枚纪念徽章。 24 | 25 | ![一周年纪念徽章](https://ws1.sinaimg.cn/bmiddle/e724cbefgw1etuo7xew2qj21kw1kwx1k.jpg) 26 | 27 | 28 | 29 | 晚上的时候收到 HR 的邮件,问我要照片,说是用来做晋升喜报的宣传。 30 | 31 | 于是我在毕业之后的一年间,职位从研发工程师,变成开发工程师,再变成资深开发工程师,需要处理的事情越来越多,面对的技术挑战越来越难。 32 | 33 | 相比起许多同期毕业工作的人,我是非常幸运的,遇到了好师兄、好老板,做了一个好项目,有付出,更有回报。如今我也做师兄了,琨少说,师兄怎么带我,我就怎么带师妹,希望我能做好。可是无论如何,我都是觉得自己做的不够好。 34 | 35 | 阿里巴巴-菜鸟网络给了我一个施展能力的平台,师兄和大老板给了我快速成长的空间。阿里系的技术并不像外界想象的那么高大上,并不是该有的设施都有了,还有很多事情可以去做,需要我们去做。阿里系的技术也并不像外界想象的那么糟糕,确实有历史包袱,也确实有前沿科技。 36 | 37 | 当然,成长不是白给的,是付出了时间,付出了汗水的。 38 | 39 | 接下来的日子,肯定会比去年更加辛苦,这已经是能够预见的。前进路上遇到的每一座山,翻过去,便是成长;翻不过去,就歇一歇,换一条路绕过去,也是成长。 40 | 41 | 共勉。 42 | 43 | -------------------------------------------------------------------------------- /source/_posts/oreilly-free-books.md: -------------------------------------------------------------------------------- 1 | title: "分享几本 O'Reilly 出品的免费电子书" 2 | tags: 3 | - Reading 4 | categories: 5 | - Study 6 | hljs: true 7 | thumbnail: 'https://i.imgur.com/NrX0gRz.jpg' 8 | cc: true 9 | comments: true 10 | date: 2016-04-30 02:40:11 11 | --- 12 | 13 | 14 | 有一些书,如果你不是行内人士,那么可能你一辈子都不会看。有一些出版社,就是专门做这种书,比如国内的机工华章,比如国外的 O'Reilly,都是专注计算机和软件行业二十年的好出版社。 15 | 16 | 这两家出版社的书,都是颇有特色个性鲜明。华章的图书,我在大学期间读了很多,以计算机科学领域的基础和经典居多,这套书在民间诨号「黑皮书」,官方的称谓好像是「计算机科学丛书」。O'Reilly 的图书则诨号「动物书」,因为图书的封面是各种各样的动物,有些动物是技术的吉祥物,比如 Python 书籍的封面是各种各样的蟒蛇,Golang 书籍的封面则是地鼠。至于 Perl,似乎还是 O'Reilly 先在 Programming Perl 这本书的封面上画了骆驼,然后骆驼才成了 Perl 的吉祥物。 17 | 18 | 19 | 20 | {% recruit %} 21 | 22 | 华章出版的最有名的图书,当属这本「施法导论」(误 23 | 24 | ![](https://i.imgur.com/7L1KiAL.jpg) 25 | 26 | 而 O'Reilly 出的最接地气的一本书,当属下面这本(误 27 | 28 | ![](https://i.imgur.com/aZEascJl.jpg) 29 | 30 | 回到正题。前几天我终于用排队打饭、吃饭、上厕所等等碎片时间,看完了大半年之前就保存在手机中的一本电子书,*[Software Architecture Patterns][1]*。 31 | 32 | 这本书内容挺好,介绍了几种常见的架构模式,比如泥球、事件驱动、插件化,还有时下火热的微服务、云架构等等,详细解释各种架构的设计,为了解决什么问题,做了哪些折衷,有哪些缺陷,还定性地描述可部署性、可测试性、敏捷度等等关键指标。 33 | 34 | 之前发现这本电子书纯属偶然,最近我养成了个习惯,不管是看过的书还是电影还是动漫,只要是觉得不错的,都在 [Favorite][2] 记录下来。这些文艺作品大多数都能在豆瓣找到相关页面,而这次我看的是电子书,豆瓣里也没人分享,我也懒得去提交申请。 35 | 36 | 于是我顺藤摸瓜找到 O'Reilly 官网上关于这本书的页面,然后再次顺藤摸瓜找到 O'Reilly 分享的其他免费编程类电子书,[Free Programming Reports][3]。页面下方还有其他主题的免费电子书,商业的,数据的,物联网的……简直就像是一个吃货走进了摆满各种各样 delicious free food 的房间,幸福来得太突然。 37 | 38 | ![](https://i.imgur.com/wFEdZ5a.jpg) 39 | 40 | 看到美好的东西,总是忍不住占为己有,看到有用的互联网资源,总是忍不住下载到本地,这叫做落袋为安。 41 | 42 | 可是,那么多本电子书,难道要我一个一个点开下载吗? 43 | 44 | 子曰,举一隅,不以三隅反,则不复也。如果点开一个两个下载之后还没找到捷径,那么真的没必要看这些书了。 45 | 46 | 这里就把下载 O'Reilly 免费电子书的捷径随便分享一下,希望读者看到的时候,这个捷径依旧有效。 47 | 48 | 万一失效了,请留言告知后来人,别留言请求我跟进修改就好,哈哈。 49 | 50 | ```js 51 | $.map($('body > article:nth-child(4) > div > section > div > a'), function(e){return e.href.replace(/free/, "free/files").replace(/csp.*/, "pdf")}) 52 | ``` 53 | 54 | 在页面上上启动检查元素,然后在终端中执行上面这个表达式,我们得到的就是当前页面展示的图书的下载地址了。有了下载地址,无论是扔给 wget 一个一个慢慢下载,还是扔给 axel 多线程并发下载,都是很轻松随意的嘛~ 55 | 56 | ![](https://i.imgur.com/txLqgnx.png) 57 | 58 | 祝阅读愉快! 59 | 60 | 61 | [1]: http://www.oreilly.com/programming/free/software-architecture-patterns.csp 62 | [2]: http://blog.jamespan.me/favorite/ 63 | [3]: http://www.oreilly.com/programming/free/ 64 | 65 | 66 | -------------------------------------------------------------------------------- /source/_posts/oreilly-free-ebooks.md: -------------------------------------------------------------------------------- 1 | title: "O'Reilly Free e-Books" 2 | tags: 3 | - Reading 4 | categories: 5 | - Study 6 | hljs: true 7 | thumbnail: 'https://i.imgur.com/NrX0gRz.jpg' 8 | cc: true 9 | comments: true 10 | date: 2016-05-04 23:25:10 11 | --- 12 | 13 | There are some books you will never want to read if you're not an expert. Yet, some presses are good at publishing those books, like [Huazhang][3] and O'Reilly. 14 | 15 | It's easy to recognize books from these two presses. I have read lot's Huazhang books at college, mostly the basis of computer science. We call these books "black cover books" while it's actual name may be "computer science series". 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | As for O'Reilly books, we call them "animal books" for there is always an animal on the cover. Some animal is the mascot of the technology, like python for Python, gophers for Golang, etc. As for Perl, it seems that it was O'Reilly who first put a camel on the cover of *Programming Perl*, then camel became Perl's mascot. 22 | 23 | In my opinions, the most famous book Huazhang ever published was this, Introduction to Casting :) 24 | 25 | ![](https://i.imgur.com/7L1KiAL.jpg) 26 | 27 | And the most honest book published by O'Reilly was following. 28 | 29 | ![](https://i.imgur.com/aZEascJl.jpg) 30 | 31 | Let's return to the main topic. I read *[Software Architecture Patterns][1]* several days ago, in fragmentary times. 32 | 33 | The book introducing some common architectures like mud, layered, event driven, etc. The most surprising part is there is a chapter about microservice, which is the hottest architectures nowadays. Not only tell how but also why it design, what problem it solved, that tradeoff it made, etc. 34 | 35 | This book is one of the O'Reilly free book collection, [Free Programming Reports][2]. Besides programming, there are topics like business, data, IoT, etc. Just like an eater wandering into a room full of delicious free food! 36 | 37 | I used to download the resource I like from the internet, in case of I can't find it anywhere some days later. Who knows, life is a bitch, so as the internet. 38 | 39 | So, the MVP of this article comes. Following is a one line code of JavaScript that helps download O'Reilly free ebooks easily. 40 | 41 | ```js 42 | $.map($('body > article:nth-child(4) > div > section > div > a'), function(e){return e.href.replace(/free/, "free/files").replace(/csp.*/, "pdf")}) 43 | ``` 44 | 45 | Just open the dev tools, then paste above jQuery expression into the console and hit enter, boom! All the PDF ebook download links are there, it's easy to download them all using wget or axel. 46 | 47 | ![](https://i.imgur.com/txLqgnx.png) 48 | 49 | Happy reading! 50 | 51 | [1]: http://www.oreilly.com/programming/free/software-architecture-patterns.csp 52 | [2]: http://www.oreilly.com/programming/free/ 53 | [3]: http://www.hzbook.com/ps/ 54 | 55 | -------------------------------------------------------------------------------- /source/_posts/paste-without-format.md: -------------------------------------------------------------------------------- 1 | title: 那些关于去除剪贴板中富文本格式的故事 2 | tags: 3 | - Tool 4 | - OS X 5 | categories: 6 | - Study 7 | cc: true 8 | comments: true 9 | date: 2015-01-28 06:13:42 10 | --- 11 | 12 | # 背景 13 | 14 | 我工作时候使用的 IM 是阿里旺旺 Mac 版。虽然我厂是个体量可以排到全球前几的互联网企业,但是在这里,Mac 用户依然不是太多,因此内部工具的 Mac 版本也就不太完善。 15 | 16 | 我经常需要从 IDE 里复制代码粘贴到 IM 发送给同事,从 IDEA 中复制出来的代码是带有格式的富文本,粘贴到 IM 之后不仅把深色的背景、高亮的颜色全都贴进去了,还带来一个挺大的副作用,新输入的文字,都有着和代码一样的颜色和背景色。要想让输入的文本变得正常,最快的方式莫过于 ⌘Q 然后重新运行 IM。 17 | 18 | 为了从频繁地重启 IM 中解脱出来,我决定做些什么。 19 | 20 | 21 | 22 | {% recruit %} 23 | 24 | # 尝试 25 | 26 | 纯文本是程序猿的好朋友。我想要这样一个东西,虽然我剪贴板中的内容是富文本,但是在我粘贴的时候,得到的是纯文本。 27 | 28 | ## 原生 29 | 30 | 对于那些 OS X 原生的应用,是自带这样的功能的,叫做 Paste and Match Style,通过快捷键 ⌥⇧⌘V 触发。 31 | 32 | 对于那些非原生的应用,则自求多福了。 33 | 34 | ## ClipMenu 35 | 36 | 那时候我有在使用一个叫做 [ClipMenu][1] 的剪贴板管理工具。在粘贴纯文本的时候,通过快捷键 ⌘⇧V 触发,弹出最近的几条剪贴板历史,右键希望粘贴的剪贴板记录,在弹出的菜单中单击 Paste as Plain Text 子菜单。 37 | 38 | 我觉得这样的操作太过繁琐,应该有更加简便快捷的实现。 39 | 40 | ## Plain Clip 41 | 42 | 几经寻找,发现一个轻巧的 App,叫做 [Plain Clip][2],可以通过 brew cask 安装。 43 | 44 | 这个 App 没有图形界面,点击图标执行后,剪贴板中的富文本就被处理成了纯文本,然后就可以粘贴到想粘贴的地方去了。 45 | 46 | 网络上都推荐把这个 App 的图标拖到 Dock 上,然后可以直接点击 Dock 图标来将剪贴板的富文本变成纯文本。 47 | 48 | 作为一个大学期间认真学习过《人本界面》的码农,我对这种交互方式的效率感到怀疑。Dock 肯定贴在屏幕的某个边界,假设鼠标位于屏幕正中央,为了完成粘贴纯文本的动作,我首先要把鼠标移动到屏幕边缘,然后单击,然后把鼠标移回原位。考虑到苹果对 Dock 图标的点击命中做了优化,即有效点击半径远大于图标半径,移动鼠标的时间和屏幕大小正相关,将鼠标移回原位的耗时约为移动鼠标点击图标的 2 倍,而且这个完成操作的时间基本上没法随着熟练程度的增加而减少。 49 | 50 | 我个人比较推荐的方式是键盘操作。无论使用 Spotlight 还是 Alfred 作为应用启动器,都只需要 2 次击键。完成应用的搜索定位也只需要 2 次击键,加上执行程序的回车击键,总共也就 5 次键。而且随着熟练程度的提高,操作速度会越来越快,比如我完成这样的应用启动耗时在 1 秒以内。 51 | 52 | ## Get Plain Text 53 | 54 | 即使我能够在 1 秒钟内完成富文本的去格式,我还是需要在完成粘贴动作前付出思考的时间和操作的时间。假如我在粘贴忘记去除格式,那我只能重启 IM 了。 55 | 56 | [Get Plain Text][3] 就是这么一款在交互上做到极致的 App。富文本对我而言是一种负担,让我时时刻刻提心吊胆要去清除格式。我希望有这么一个应用能够帮助我自动把剪贴板中的富文本变成纯文本,而 Get Plain Text 恰恰做到了。 57 | 58 | 这个应用提供了一个选项,Automatically clear formatting,一旦勾选它就会自动将剪贴板中富文本的格式清除,从此我只需要复制、粘贴,不用再去考虑文本格式的问题。 59 | 60 | 对于那些仅仅是偶尔需要粘贴纯文本的用户,可以选择不去勾选 Automatically clear formatting,在需要粘贴纯文本的时候使用 Get Plain Text 提供的快捷键 ⌘⇧K 即可。 61 | 62 | 曾经这个应用卖到了 18 CNY,如今在 [iTunes][4] 上免费获取。 63 | 64 | # 总结 65 | 66 | 这一次为了满足我摆脱富文本的小需求,尝试了 3 个应用,在使用 Plain Clip 的过程中还试图写 Apple Script 将去除富文本格式的过程自动化,不幸以失败告终。最后幸运地找到了 Get Plain Text,相信在接下来的日子里,它能为我节省不少时间。 67 | 68 | [1]: http://www.clipmenu.com 69 | [2]: http://www.bluem.net/en/mac/plain-clip/ 70 | [3]: http://zipzapmac.com/getplaintext 71 | [4]: https://itunes.apple.com/cn/app/get-plain-text/id508368068 72 | -------------------------------------------------------------------------------- /source/_posts/personal-wiki-sucks.md: -------------------------------------------------------------------------------- 1 | title: 个人 Wiki 之殇 2 | tags: 3 | - Tool 4 | categories: 5 | - Study 6 | cc: true 7 | comments: true 8 | date: 2015-06-30 22:39:57 9 | --- 10 | 11 | 我一直都在寻找一种优雅的方式来管理我的知识。如果能够优雅地分享,那是最好不过。为此,我先后尝试了 Wiki,Evernote,Blog 等各种媒介。 12 | 13 | 大三那年,学习了冯志勇教授讲授的《知识工程》之后,我发现语义网的确是知识的良好载体。知识有定义有关系,定义之间通过关系互相连接而形成一张大网,当这张网足够大,覆盖面足够全,本体就形成了。 14 | 15 | 16 | 17 | {% recruit %} 18 | 19 | 在当前的技术条件下,Wiki 俨然称为了知识的最佳载体。Wikipedia 已经称为世界上最大的百科全书,承载了全球有识之士的知识与智慧。 20 | 21 | 大而全的东西固然好,但是毕竟缺乏个性化,我还需要一个小而美的 Wiki,作为我的知识网络的载体,也让我把分享知识这件事变得更加简单。 22 | 23 | 大学的时候,我曾经尝试过在本地搭建 MediaWiki。然而这并不是一种科学的使用 Wiki 的方式。后来我一直没怎么折腾 Wiki,一个是因为没有那么强烈的管理知识的需求,另一方面是那时候搭建 Wiki 实在是一件吃力不讨好的事情。 24 | 25 | 直到最近,知识管理的需求又冒了出来,而我正好找到了 [TiddlyWiki](http://tiddlywiki.com/) 这个界面优美,使用简单的 Wiki 系统,于是一个属于我自己的 Wiki 系统,[James Pan's Wiki][1] 就出现了。 26 | 27 | 在使用 TiddlyWiki 之前,我尝试过寻找 Knowledge Base 之类的东西。然而结果不尽人意。不是不支持静态部署,就是不支持中文搜索。 28 | 29 | 使用 TiddlyWiki 之后,我发现它也不像一开始想象的那么完美。首先是标注语言的问题。虽然我安装了 Markdown 插件,但是为了发挥 TiddlyWiki 的全部特性,我还是不得不去学习一个新的小众标记语言,[WikiText][2]。 30 | 31 | 用了一段时间之后,WikiText 我也算是不陌生了,于是我开始思考一个问题:TiddlyWiki 是一个单文件的 Wiki 系统,随着我用它记录的知识越来越多,文件体积会越来越大,直到有一天,完整加载整个页面的耗时变得无法接受,我将它部署到互联网上就变得没有意义,于是我存放在 TiddlyWiki 中的知识将会和 TiddlyWiki 一起退化为一个单机系统。 32 | 33 | 一个空的 TiddlyWiki 就已经 1.8 MB 了,安装了必不可少的 Markdown 插件和 Mathjax 插件,再写上几个词条,页面膨胀就到了 2.2 MB。虽然我还不不知道一年之后这个页面会是多大,但是我已经能想象到它退化成单机系统的凄凉。恐怕这是所有的单页 Wiki 都绕不过去的坎。 34 | 35 | 其实 TiddlyWiki 提供了一个残缺的解决方案。对于使用 Node.js 本地部署的 Wiki,可以使用一些命令来导出静态站点,代价就是静态的 Wiki 页面没有 js,从此失去了搜索等一系列杀手级的功能。 36 | 37 | 假如我成功地 hack 了 TiddlyWiki,使它能够生成带 js 的多页面静态站点,那么我将直面一个问题:搜索。在静态网站上使用搜索有几种方案,一种是使用 Google 的站内搜索,一种是使用 [Swiftype][3],再有就是使用纯 js 实现的客户端搜索引擎,比如 lunr。 38 | 39 | Swifttype 我是没用过,其他两种方案我都有尝试。先说 Google,使用 Google 的好处自不必说,坏处倒是有几个,也还蛮严重的。首先是梯子的问题,毕竟访问 Google 不是那么的方便;其次是爬取的时间、索引的权重之类的参数,没法控制。 40 | 41 | 然后说说客户端搜索引擎。自从 HTML5 兴起之后,前端技术开始有燎原之势。虽然纯前端技术能够实现很多原本应该由后端实现的功能,但是它也有着不小的局限。就以客户端搜索引擎 lunr 为例,lunr 借助 search_index.json 实现索引和搜索。 42 | 43 | 首先是 lunr 不支持中文搜索,而且今后很长一段时间都不会支持中文(中文在计算机的世界里真是二等公民,把它发展为一等公民的重任就落在了我们肩上);其次,就算我 fork 了 lunr 并让它支持了中文,分词之后生成的索引文件恐怕也是不小,如此一来将 TiddlyWiki 输出成多页面形式的意义就不大了,只不过是把难以接受的大文件从 Wiki 文件变成了索引文件而已。 44 | 45 | 也许这就是个人 Wiki 之殇。因为是个人使用的 Wiki,所以想要尽可能简单易用,不要有服务器不要有数据库。因为尽可能的简单,所以只能用平面文件来组织;因为尽可能易用,所以不能用强大复杂的技术;因为要好用要 eye candy,所以要用酷炫的客户端技术。因为不能用复杂的技术,加上没有服务器没有数据库,所以搜索功能和索引文件只能放在客户端。因为使用了客户端搜索技术,用户迟早面临单文件过大的问题。 46 | 47 | 最终,Wiki 的管理、搜索只能在本地进行,部署到互联网上的 Wiki 只能残缺的静态站点,没有搜索,没有互动,只有文本以及超链接。 48 | 49 | [1]: http://wiki.jamespan.me 50 | [2]: http://tiddlywiki.com/static/WikiText.html 51 | [3]: https://swiftype.com 52 | -------------------------------------------------------------------------------- /source/_posts/play-seo-with-jianshu.md: -------------------------------------------------------------------------------- 1 | title: 大开脑洞用简书之SEO 2 | tags: 3 | - Tool 4 | categories: 5 | - Study 6 | cc: true 7 | comments: true 8 | date: 2015-03-25 20:41:48 9 | --- 10 | 11 | # 背景 12 | 13 | 前些日子,我每写完一篇新的博文之后,会找个良辰吉日,把链接投稿到[小道消息][1]和[开发者头条][2]。 14 | 15 | 就目前来说,虽然整体流量很低,但是从小道消息跳转到我的博客的流量是开发者头条的好几倍。 16 | 17 | 昨天晚上我突然想到了一个方法,或许能够帮助提升博客文章在搜索引擎的排名。当然,我主要关注的搜索引擎还是 Google。百度是啥,能吃么? 18 | 19 | 20 | 21 | {% recruit %} 22 | 23 | ![](https://ws2.sinaimg.cn/large/e724cbefgw1exdxk3zbt2j20hi0ab75y.jpg) 24 | 25 | # 简书 26 | 27 | [简书][4]是目前中文圈子一个比较流行的基于内容分享的社区,口号是"交流故事,沟通想法"。 28 | 29 | 从简书的链接还是 [jianshu.io][5] 的时候我就是简书的用户了,那时简书上面还没有多少人,口号还是“找回文字的力量”,我也还没开始认真写博客,反正就是看到一个不错的应用,然后上去注册个帐号写一篇文字试试的意思。 30 | 31 | 后来渐渐的,简书的用户渐渐多了起来,开始出现各式各样的人,写各式各样的文。 32 | 33 | 再后来,简书就成了现在的样子,一个活跃的社区,每天产生大量的原创文字。 34 | 35 | # 脑洞 36 | 37 | 一开始要我用简书,我是不愿意的。 38 | 39 | 我有自己的独立博客,我可以在自己喜爱的文本编辑器上写字,然后敲几行命令就把写好的博客发布到 GitCafe 和 Github。 40 | 41 | 我可以随心所欲定制博客的外观和使用体验,至少就我个人感觉而言,我的博客在阅读体验上不输于简书。 42 | 43 | 直到后来,我脑洞一开,发现简书是可以为我所用的。 44 | 45 | 我不需要把文章发布到简书,我的文章还是发表在我的独立博客,然后我可以模仿那些摘要输出的 RSS,把摘要信息以引用的形式发表在简书,然后在引用结束之后放一个指向博客原文的链接。 46 | 47 | 简书的在 Google 的权重,不知道比我的博客高到哪里去!最让人膝盖中箭的是,直接无论是搜索关键字还是搜索标题,我发布在简书的摘要,都排在博客本尊的前面。 48 | 49 | ![关键字搜索](https://ws4.sinaimg.cn/large/e724cbefgw1exdxkh3793j20me0kpjyt.jpg) 50 | 51 | ![标题搜索](https://ws1.sinaimg.cn/large/e724cbefgw1exdxkusnrsj20mm09jdim.jpg) 52 | 53 | 对我而言,似乎这是一种一箭双雕的做法,既能够在一个高质量的网站上面增加指向我的博客的链接,又实实在在的输出了内容。 54 | 55 | 比较对不起的就是简书了,但愿简书不要被玩坏,同时能够为我的博客带来一批高质量的读者。 56 | 57 | # 漫谈 58 | 59 | 我发现这两个网站的链接排名算法有些意思。好几年前,我还在读大学的时候,拜读过阮一峰先生的《[基于用户投票的排名算法][3]》系列文章,对这类排名算法也算是有一些粗浅的认知。 60 | 61 | 从感觉上来说,小道消息的排名算法比起开发者头条更加科学一些,那些票数比较多的投稿,能够较长时间在首页占据一席之地;相比之下,开发者头条的投稿按天滚动,即使某篇文章当天得到了很多票,第二天一到,也得老老实实退居二线。 62 | 63 | 目测开发者头条的链接排序算法的比较算子是先以天为单位比较时间,再以比较票数,最后比较达到当前票数的时间。 64 | 65 | 最近小道消息的投稿区被 Memcet 刷屏了,整屏整屏都是来自这个网站的链接,影响很坏!曾经慧都控件网也在小道消息刷屏,后来直接黑名单了。 66 | 67 | 开发者头条是我用过的华语开发者链接分享推荐社区中,仅次于小道消息的存在,投稿的文章会经过审核,质量上有一定的保证,值得关注。 68 | 69 | [1]: http://news.dbanotes.net 70 | [2]: http://toutiao.io 71 | [3]: http://www.ruanyifeng.com/blog/2012/02/ranking_algorithm_hacker_news.html 72 | [4]: http://www.jianshu.com 73 | [5]: http://jianshu.io 74 | 75 | -------------------------------------------------------------------------------- /source/_posts/poker-ii-and-kindle.md: -------------------------------------------------------------------------------- 1 | title: 新玩具之 Poker II 和 Kindle 2 | tags: 3 | - Device 4 | categories: 5 | - Life 6 | thumbnail: //i.imgur.com/YGFqPbQm.jpg 7 | cc: true 8 | comments: true 9 | date: 2016-01-23 11:19:08 10 | --- 11 | 12 | 13 | 最近呢,我入手了两个新设备,一个是 Poker II,一个是 Kindle。 14 | 15 | 这 Poker II 呢,是一把 60% 的机械键盘,红轴。这 Kindle 呢就是 Kindle,Amazon 电子书设备入门版。键盘上我先后用过 84 键的 KYECOOL 和蓝牙键盘 Filco Minila Air,都是青轴。电子书我也有 iPad Air,虽然我拿他看书和看动漫的时间一半一半,但我还是认为它是我的电子书设备。 16 | 17 | 虽然这两个新入手的设备功能上都和我已有的设备重复,价位上甚至远不如那两个名字中带有 Air 的设备,但是它们或者给我的生活带来了方便,或者可以给我当作一个实用的纪念品。总之,还是值得记录一下的。 18 | 19 | 20 | 21 | {% recruit %} 22 | 23 | 先说 Poker II。 24 | 25 | Poker II 是一把小巧酷炫的键盘,很喜欢它的外形。但是,现在在网上已经买不到 Poker II 了哦,似乎已经停产了,取而代之的是它的升级版 Poker III,外形更酷炫,功能更强大。 26 | 27 | 很早之前就知道 Poker II 了,但是购买第一把键盘的时候还在大学,预算有限,只好买了几乎是最便宜的 KEYCOOL 作为入门。购买第二把键盘用于退烧的时候,出于某种特殊的考虑想要蓝牙键盘,于是就买了 Filco Minila Air,两次都巧妙的避开了 Poker II。 28 | 29 | 最近,我在微博上看到琨少说他[不喜欢 60% 的机械键盘][1],当时我就想啊,你不喜欢没关系,我喜欢呀~于是我就回复说我可以收,然后琨少就慷慨地把键盘送给我了! 30 | 31 | 琨少是何许人也?是我在菜鸟网络的同事咯,一个让我敬佩的高级技术专家。之前在「[2014 年度回顾][2]」中提到,我曾经被琨少无意中折服。无形装逼,最为致命。 32 | 33 | ![Poker II](//i.imgur.com/9dgwRsL.jpg) 34 | 35 | 这就是我那把 Poker II 的靓照了,默认的 Mini USB 连接线是直的,我去淘宝找了个可伸缩的 L 头 USB 线,感觉和键盘更配哦。 36 | 37 | 红轴的感觉呢,木有段落感,轻轻按一下信号就出去了,跟青轴的感觉还是很不一样的。有点不适应的地方就是需要用组合键来实现方向键,在 Emacs 里面还没啥感觉,到了外面就有些不便了。 38 | 39 | 因为要离开了,这段时间没有开发任务,主要的工作就是给团队留交接文档,在 ATA 发表技术文章。用 Poker II 写了好多篇文章,感觉红轴的特点就是轻柔,噪声极小,就算中午的时候敲击红轴键盘也不会影响到同事休息。 40 | 41 | 再说说 Kindle。 42 | 43 | 看电子书这种事情从初中就开始了,那时候看的是小说。最开始的时候用的设备还是电子词典,还是借的同学的诺亚舟之类的,上课的时候偷偷放在抽屉里看「诛仙」。小说里面的各种情节,难兄难弟、兄弟反目、暗恋的学姐成了学长的老婆、扫地僧万剑一、高冷仙女爱上我、妖娆魔女爱上我、找个岳父叫鬼王之类的狗血桥段,满足了年幼无知的我们对仙侠世界的所有幻想。 44 | 45 | 后来上了高中,自己偷偷把从伙食费中抠下来的钱攒起来,买了个 MP4,然后就晚上就用被子把自己包起来,躲在里面看小说,还要注意不要把屏幕光泄露出去,不然会被舍监抓违纪。 46 | 47 | 因为种种原因,高中我一直没有手机,但是为了看那些在起点连载的小说,只好借朋友的手机,在上课的时候刷贴吧的手打贴。那时候追的小说是「凡人修仙传」,一不小心就从高二看到了大四,到阿里上班后的花名都出自这本小说,满满的都是回忆。 48 | 49 | 上了大学之后,除了「凡人修仙传」之外几乎就没有再看其他小说了,也许是厌倦了那些网络作家如出一辙的情节套路,反正都市装逼文也很难超越「极品公子」,仙侠类更是凡人一出天下无书,我的电子书阅读主要转向了技术类书籍,那时的我热衷于从网上搜寻下载各种计算机科学和软件类的经典书籍的扫描版,可耻地看了许多盗版书。 50 | 51 | 至于阅读的设备,一开始的时候用的自然是一台性能弱到极致的 ThinkPad X100,后来也是从牙缝中抠出了一台廉价 Android 平板,用一个好像叫智器的应用阅读,后来就转到了多看。7 寸屏幕看电子书总是别扭的,但是人穷志短只好将就,虽然体验很差但是也读了不少书,涨了不少知识。 52 | 53 | 工作之后不久,用信用卡买了一台 iPad Air,招行信用卡曾经的好处就是买 Apple 家的产品,分期不收手续费和利息,可惜的是如今这福利也没了。iPad Air 真是好用啊,再一次体会到了什么叫「设备驱动」,都有这么好的设备这么好的阅读体验了,看你还能找借口不读书? 54 | 55 | Kindle 对我的电子书阅读生涯是一个有益的补充,之前我阅读的电子书,要么是下载的文本文档,要么是扫描的 PDF,要么是从多看书城下载的知乎周刊之类的免费书籍。Kinkle 不仅为我打开了 Amazon 系电子书的大门,用电子墨水的屏幕也是一种奇特的体验,晚上睡觉前看会电子书也得开灯了。 56 | 57 | 不过我是不相信所谓的电子墨水不伤眼的说法的,如果说跟纸书一样不主动发光就不伤眼,我就不会在小学二年级就近视了呜呜呜。 58 | 59 | 之前由于设备的原因,我一直没去关注 epub、mobi 等等格式的电子书,因为这些电子书在电脑上的阅读体验堪称糟糕,如今有了 Kindle 倒是可以尝试一下了。 60 | 61 | ![](//i.imgur.com/NHVXy8kl.jpg) 62 | 63 | 找了个「飞鸟集」假装文化人。高中看「极品公子」那会,感觉飞鸟集逼格高到不行,动不动就是「世界以痛吻我,要我回报以歌」,泰戈尔也是潮得不要不要的。现在看到了英文,也许真的是我水平太低,完全无法理会其中的美啊。 64 | 65 | 66 | [1]: http://weibo.com/1797963165/D8eHRkHoQ 67 | [2]: /2015/05/10/look-back-2014/ 68 | 69 | -------------------------------------------------------------------------------- /source/_posts/polling-and-callback.md: -------------------------------------------------------------------------------- 1 | title: 轮询与回调 2 | tags: 3 | - Thinking 4 | categories: 5 | - Life 6 | - Essay 7 | cc: true 8 | math: true 9 | comments: true 10 | date: 2015-06-18 00:00:05 11 | --- 12 | 13 | 刚开始使用电子邮件的时候,用的 QQ 邮箱。那时候也没有使用邮件客户端,就是挂着个 QQ,收到邮件之后会在桌面右下角弹出个提醒,然后点开就进入了邮箱的 Web 界面。渐渐的我有了多个 QQ 号,自然就有了多个 QQ 邮箱。 14 | 15 | 16 | 17 | {% recruit %} 18 | 19 | 后来上了高中,开始使用 Gmail,然后用 Gmail 以 POP3 协议去收取各路邮箱。再后来上了大学有了 edu 邮箱,毕业之后偶尔还用这个邮箱伪装学生身份,也是被 Gmail 收取。在 Google 被墙之前,Gmail 的使用体验简直无可挑剔,无论是电脑上用 Thundbird 作为客户端,还是 Android 上原生的 Gmail App,都能在邮件到达之后的几秒钟给我一个提醒。 20 | 21 | 后来,我们为了能够访问全球互联网,八仙过海各显神通。但是,长城内外终究是产生了隔阂,收个邮件都得拿出梯子,着实不便。但是,我也就这样将就了好几年。 22 | 23 | 最近我开始用 iCloud 的邮件服务了。 24 | 25 | 自从 Google 关闭了 exchange 之后,在 iOS 设备上收取 Gmail 邮件,一般只能用“获取”而不能用“推送”。获取的意思就是每个 N 分钟去服务器获取一次邮件,$min(N) = 15$,而获取的前提是能够访问国际互联网。这样子一来我从手机上收取邮件就变得比较复杂而且别扭了,倒是在电脑上收取邮件比较顺畅。 26 | 27 | 但是我还是想用手机收取私人邮件,于是我试着把 Gmail 的邮件转发到 iCloud,然后把其他被 Gmail 通过 POP3 收取的邮箱的邮件也转发到 iCloud。然后我就能在手机上愉快地享受延迟可以忽略的邮件推送了。 28 | 29 | 这次我在手机收取邮件策略上的变化,让我想起编程中两种常见的策略:轮询和回调。 30 | 31 | 早先的“获取”策略其实就是轮询,客户端不停(间歇)地发起请求,询问服务端是否有新数据产生,如果有新数据就把新数据抓取下来。由于客户端消费邮件的速度远大于新邮件到达服务端的速度,绝大部分的请求都是做无用功。 32 | 33 | 为了减少朴素轮询中的无用请求,机智的开发者发明了“长轮询”。客户端发起请求,如果有新数据则立即返回,否则服务端持有请求并等待新数据一段时间再返回。这种策略极大的减少了客户端发起的无用请求,但是加大了服务端的开销。 34 | 35 | 回调策略与轮询策略截然相反。回调就像好莱坞原则,Don't call us, we'll call you,不是客户端主动向服务端请求数据,而是服务端向客户端推送数据。 36 | 37 | 长连接是服务端数据推送的一种实现方式,通常借助 iframe 来实现[^1]。 38 | 39 | [^1]: [Comet:基于 HTTP 长连接的“服务器推”技术][1] 40 | 41 | 在我的感觉中,轮询和回调的差别,就像同步和异步的差别那么大。虽然同步在实现上更加简单,但是异步的效率却更高。 42 | 43 | 其实我个人更加倾向于异步的方式,不仅在技术上,也在生活上。 44 | 45 | 在沟通上,我更倾向于异步的交流,电子邮件是上选,短信、IM 次之,电话最次。采用异步的方式,双方都可以选择最合适的时间、环境进行回复,没有中断,没有阻塞,只有提醒。 46 | 47 | 支付体验上,Uber 远胜于其他 App,秘诀也在于异步。乘客下车之后,Uber 自动从支付宝或者信用卡中扣费,不需要输入金额,不需要输入密码,不需要指纹支付。这就是传说中的“因为信任,所以简单”? 48 | 49 | 50 | [1]: http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 51 | -------------------------------------------------------------------------------- /source/_posts/popular-book-and-banned-book.md: -------------------------------------------------------------------------------- 1 | title: 卖桃君写的书卖疯了,教授写的书不见了 2 | tags: 3 | - Reading 4 | categories: 5 | - Life 6 | thumbnail: //i.imgur.com/ReiXBV0.jpg 7 | cc: true 8 | comments: true 9 | date: 2015-12-13 02:33:31 10 | --- 11 | 12 | 说来比较惭愧,最近几个周末我并没有在干和技术相关的事情,因此之前挖的坑一个都没填上。 13 | 14 | 本来想给 NGINX 写一个负载均衡插件,却越尝试越发现 NGINX 这水好深。本来想学 Swift 并写一个练手的 App,结果被 NGINX 插队优先级下降了。本来想写一个 Python 模块支持把项目和依赖全部用 zip 打包成类似 fat jar 的东西,优先级就更低了。 15 | 16 | 但是最近两个周末我看了两本书,感觉有必要在这里分享一下。 17 | 18 | 19 | 20 | {% recruit %} 21 | 22 | 第一本要分享就是卖桃君的新书,「MacTalk 跨越边界」,虽然在时间上这是第二本。这本书是几周之前我在京东买的,当时还是预售,杭州到 12 月 5 日才有货。于是我就在朋友圈和微博眼红地看着网友各种晒,到了 12 月 7 日才收到。 23 | 24 | 订阅 MacTalk 一年多了,于是这本书里面的内容我基本上都在微信公众号里看过,这次翻阅算是一次回顾吧,温故而知新。 25 | 26 | 当名人就是好,平时在博客或者公众号里写写,量到了就集结成书,最后靠着粉丝经济也能卖个好销量。因为基本上都看过,所以这次看得特别快,大概一个下午一个晚上就从头到尾看了一遍。 27 | 28 | 第二本就有点意思了,如果不是因为某些特殊的原因,我是不会去看的。这本书是「走出帝制」。为什么我会去看一本我本应该不会去看的书呢?这就要从一则来自 Solidot 的[新闻][1]说起。 29 | 30 | 我是有用 RSS 收取 Solidot 的新闻的,所以在这个新闻发布之后不久,我就得到了消息。但是明显已经迟了,各大电商网站上已经买不到这本书了,豆瓣甚至直接把这本书的信息删了。 31 | 32 | 这引发了我想要一睹为快的好奇心。于是我就在网上找啊找,一开始被我找到的是一个残缺的 PDF 文档,缺少最后一章的内容。虽然不太满意,但是当时就想先将就着看,没准过几天就有买到实体书的网友把扫描版分享出来了。就在这几天,我快要看完的时候,下载到了完整的 PDF 版本,居然还是排版良好的文字版,真不容易。 33 | 34 | 这本书真的蛮有意思,相比起大学期间学习的来自官方的近代史,几乎是颠覆性的,为读者揭开了那一层遮羞布。 35 | 36 | 如果你也对这本书感兴趣,请自行搜索下载阅读,不要问我要拷贝😂连我都能找到,你一定可以。 37 | 38 | 这周六深夜,我还去看了一部电影,「师父」,挺好看的,讲的是北洋军阀时期天津武馆江湖的故事,江湖里的阴谋诡计和扭曲的人际关系。 39 | 40 | 这周还给团队成员简单分享了一下[技术博客的写作实践][2]。写了快一年了,回头看看,写博客真的让我收获了很多东西,算是进入正循环了吧~ 41 | 42 | 2015 年就要结束了,完结撒花! 43 | 44 | 45 | [1]: http://www.solidot.org/story?sid=46342 46 | [2]: /slides/share-your-knowledge-by-blogging/ 47 | 48 | 49 | -------------------------------------------------------------------------------- /source/_posts/presentation-with-revealjs.md: -------------------------------------------------------------------------------- 1 | title: 用 reveal.js 做演示 2 | tags: 3 | - JavaScript 4 | - Tool 5 | categories: 6 | - Study 7 | date: 2015-01-13 12:52:24 8 | 9 | cc: true 10 | comments: true 11 | --- 12 | 13 | # 介绍 14 | 15 | reveal.js 是一个帮助你快速使用 HTML 创建漂亮的幻灯片的框架,提供嵌套页面、Markdown 支持、[PDF 导出][2]、演讲者模式等等功能。其中 PDF 导出功能我还没研究明白。 16 | 17 | reveal.js 提供了一个 [Demo][1],其作用更像是一个速查手册,介绍了 reveal.js 的各种功能和特效。 18 | 19 | 20 | 21 | {% recruit %} 22 | 23 | # Demo 24 | 25 |
26 | 27 |
28 | 29 | # 参考文献 30 | 31 | + [reveal.js - The HTML Presentation Framework][1] 32 | 33 | [1]: http://lab.hakim.se/reveal-js/ 34 | [2]: https://github.com/hakimel/reveal.js#pdf-export 35 | -------------------------------------------------------------------------------- /source/_posts/pyiconv.md: -------------------------------------------------------------------------------- 1 | title: pyiconv - 一个文本编码探测转换器 2 | date: 2014-08-04 22:13:02 3 | tags: 4 | - Tool 5 | - Python 6 | categories: 7 | - Study 8 | cc: true 9 | hljs: true 10 | comments: true 11 | --- 12 | 13 | 最近在 Mac 下写代码,一不小心就遭遇了编码问题,蛋疼的 GBK 陷阱,代码里面的中文注释全乱套了。本来不想自己造轮子的,但是 iconv 不具备自动探测文本编码的功能,这个很是痛点。Mac App Store 里有一个叫 [TextPal](https://itunes.apple.com/us/app/textpal/id677976033) 的 App,界面看起来很不错的样子,但是好贵,要 30 软妹币,屌丝不舍得啊。 14 | 15 | 周末的早上无聊就造了一会轮子,把代码写出来了,算是 iconv 的 Python 复刻,增加了自动识别编码的功能,顺便练习用 Python 解析命令行参数。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | 另外,我为了方便检测文本编码,使用了一个叫`chardet`的库。通过`pip install chardet`安装该依赖即可。 22 | 23 | 如果需要批量转换,可以结合`find`和`xargs`来使用,像这样子: 24 | 25 | ```bash 26 | # 批量转换文本为GBK编码,覆盖原文件 27 | find . -name "*.java" | xargs -I{} ./pyiconv -i {} -t GBK -o {} 28 | ``` 29 | 30 | 更多用法在程序的 help 里,执行`pyiconv [-h|--help]`就能看到。 31 | 32 | ```bash 33 | usage: pyiconv [-h] [-d] [-i FILE] [-o FILE] [-f ENCODING] [-t ENCODING] [-a] 34 | 35 | detect and convert text encodings 36 | 37 | optional arguments: 38 | -h, --help show this help message and exit 39 | -d, --detect-only detect the encoding of input end exit 40 | -i FILE, --input FILE 41 | read from input file, if not given, use stdin by 42 | default 43 | -o FILE, --output FILE 44 | write to output file, if not given, use stdout by 45 | default 46 | -f ENCODING, --from ENCODING 47 | the encoding that convert from, if not given, auto 48 | detect by default 49 | -t ENCODING, --to ENCODING 50 | the encoding that convert to, if not given, UTF-8 by 51 | default 52 | -a, --auto-detect auto detect encoding of input 53 | ``` 54 | 55 | 代码托管在 Github 上,[pyiconv](https://github.com/JamesPan/pyiconv) 项目。 56 | 57 | 希望我花了时间之后能帮助大家节省时间~ 58 | -------------------------------------------------------------------------------- /source/_posts/recruiting-on-blog.md: -------------------------------------------------------------------------------- 1 | title: 谈谈在独立博客发布招聘信息那些事 2 | tags: 3 | - Sketch 4 | categories: [Life, Essay] 5 | cc: true 6 | comments: true 7 | date: 2015-03-20 10:39:45 8 | --- 9 | 10 | # 背景 11 | 12 | 最近我在博客的侧栏挂上了招聘信息,一条关于社招,一条关于校招。 13 | 14 | ![招聘信息](https://ws2.sinaimg.cn/large/e724cbefgw1exdxlggtkyj207708pwf6.jpg) 15 | 16 | 刚把招聘信息挂到博客上的时候,为了让更多的人看到,我找了之前写的一篇博文,投稿到[小道消息][1]和[开发者头条][2],然后坐等访问量一点一点爬升。 17 | 18 | 19 | 20 | 有些不好意思的是,我这个博客,其实没多少访问量。挂上招聘信息那几天,我接连把两篇博文投稿到那两个网站,访问量达到历史新高,最高日PV 1735。 21 | 22 | 毕竟我的博客干货还不是很多,没有那么多的资料值得网友一次次访问;同时我也没有认真的去做 SEO,至少百度是完全搜索不到我的博客,我连站点地图都没有生成百度兼容的版本。 23 | 24 | 于是几天下来我没有收到一封简历,一封都没有。之前我往 V2EX 发招聘贴的时候,收到的简历可是一封接一封的。 25 | 26 | 我开始思考在博客发布招聘信息是不是一件靠谱的事情。 27 | 28 | # 访客画像 29 | 30 | 想想看,能访问到我的博客的网友,大概是什么样子? 31 | 32 | 首先,他们和我一样,经常去小道消息看看有没有让人涨姿势的文章,或者去开发者头条看看当天有哪些新鲜事。 33 | 34 | 能有闲情逸致去看这些东西的人,如果是上班族,那么应该是处于工作比较稳定的状态;如果是学生党,那么在技术上应该算是超出大部分同学几个段位的了。那些工作稳定的上班族没有理由跳槽去一个陌生的环境,那些学生中的技术大神们,想必也是不屑于内推的罢。 35 | 36 | 由于我的博文在自由的知识共享协议下发布,很多 IT 类信息网站也有转载我的博文,当然通过这些网站看到我的博文的网友,就看不到那可怜的招聘信息了。 37 | 38 | # 精准投放 39 | 40 | 广告投放的一个常见词汇就是,精准投放。想用户之所想,急用户之所急,分析用户行为,猜测用户所需,然后雪中送广告。 41 | 42 | 回头看看我的这个招聘信息,可是跟精准投放一点都不沾边呢。先不说访客基本没有求职意愿,就想想谁会在需要找工作的时候跑去刷博客? 43 | 44 | 有的时候想想,在独立博客投放招聘信息,就像在微博投放淘宝广告似的,人家是来看博文的,又不是来找职位信息的,转化率自然惨淡无比。 45 | 46 | # 个人博客 47 | 48 | 我开始写博客是工作之后的事情,认真写博客那是 15 年初才开始的,标志性文章就是那篇半回忆半教程不伦不类的《{% post_link when-i-talk-about-mac %} 49 | 》。其后零零散散好几篇各式各样的文章,记录自己开脑洞写的轻应用的过程,还有一些工作中遇到的粗浅的技术问题。 50 | 51 | 就像阮一峰先生的访谈《[为什么写博客?][4]》里的,我尽量的避免在自己的博客中谈论公司。 52 | 53 | > 我觉得一定要分清楚,哪些是自己建立起来的,哪些是公司带给你的。你之所以拥有后者,很可能仅仅是因为运气好,是公司的成功,而不是你的成功。所以,我不太会写到公司。 54 | 55 | 我来杭州已经一年多了,如果算上实习的话,工作时间也有一年了,现在回头看看这篇访谈,感触真的很深。 56 | 57 | 我从入职以来就跟着师兄做一个项目,一个注定解放许许多多生产力的项目。我们投入了许多,收获了许多技术进步,也因为各种原因的故障长了许多堑智。 58 | 59 | 昨天我们作为获奖团队参加兄弟部门的年会,一个 Leader 的发言让我深思。作为一个技术人员,无论你的技术头衔是什么,突然有一天把你放到一个陌生的团队,没有人知道你是谁,没有人知道你是高 P 的专家还是低 P 的工程师,你该如何让团队的人知道你的能力,认可你的价值? 60 | 61 | 借着公司的平台,个人能力可以得到快速的成长。相对的,很多人容易迷失在这个平台上,不知道什么东西是真正属于自己的,什么东西是公司借给你的。 62 | 63 | 也许这也是我开始写博客的原因之一。我希望以后回头看看我这段与时间赛跑的日子,能有一些属于我的东西留下,有一些东西能证明我的能力,不需要我多费口舌就能让别人知道我是谁。 64 | 65 | 招聘信息还是会保留一段时间,等有缘人。祝贺学姐通过实习生面试,最初投的研发,却被转到了测试。 66 | 67 | # 最后 68 | 69 | 最近我在读 *[Seven Concurrency Models in Seven Weeks][5]*,如果时间允许的话,会在博客上分享一些收获。 70 | 71 | [1]: http://news.dbanotes.net 72 | [2]: http://toutiao.io 73 | [4]: http://www.ituring.com.cn/article/111023 74 | [5]: https://book.douban.com/subject/25736606/ 75 | -------------------------------------------------------------------------------- /source/_posts/redirect-with-js.md: -------------------------------------------------------------------------------- 1 | title: 使用 JavaScript 实现 iframe 判断和页面重定向 2 | tags: 3 | - JavaScript 4 | categories: 5 | - Study 6 | date: 2015-01-12 00:23:13 7 | 8 | cc: true 9 | hljs: true 10 | comments: true 11 | --- 12 | 13 | # 背景 14 | 15 | 今天我突然发现 Google 已经能够索引[我的博客][1]了,外在特征就是我能用 Google 对博客进行[站内检索][4]。 16 | 17 | 我随便搜索了一下,发现 Google 索引的 [Timeline][2] 的内容,全都指向了作为 iframe 嵌入的 /blog/timeline/timeline.html 页面,而不是[我期望的页面][2]。这其实也不是 Google 的错,因为 iframe 中的内容,本来就是不会被爬虫认为是当前页面的内容。 18 | 19 | 从 Google 的搜索结果直接点进 Timeline,就只能看到一个纯净的时间轴,看起来这个页面跟我的博客没有半毛钱关系。那怎么才能让 Google 的搜索结果指向博客页面呢? 20 | 21 | 22 | 23 | {% recruit %} 24 | 25 | # 方案 26 | 27 | 我首先想到了用 JavaScript 来控制页面跳转,这个几乎是最经济的实现方式了。 28 | 29 | 方案选定之后就是定位问题,我要解决的问题有 2 个: 30 | 1. 如何判断当前页面是从 iframe 访问的,还是直接访问的? 31 | 2. 如何控制页面跳转? 32 | 33 | 我在 Stack Overflow 找到了两个问题的答案,见[参考文献](#参考文献)。以下是解决问题的代码。 34 | 35 | ```js 36 | //判断当前页面是否直接显示在浏览器中 37 | if (self == top) { 38 | //跳转 39 | window.location.replace("/blog/timeline/"); 40 | // window.location.href='/blog/timeline/'; 41 | } 42 | ``` 43 | 44 | 这里要指出的是,JavaScript 跳转页面有很多种实现方式,我这里选择的是最简单的实现,不依赖于 jQuery。 45 | 46 | 其中 `window.location.replace` 跳转时,浏览器历史不记录跳转之前的那一条 URL,而 `window.location.href` 会把跳转前后的 URL 都记录在浏览器中。 47 | 48 | 如果想要模拟点击链接的跳转效果,使用 `window.location.href`,如果想要模拟 HTTP 跳转,使用 `window.location.replace`。 49 | 50 | # 参考文献 51 | 1. [to check parent window is iframe or not](http://stackoverflow.com/questions/4594492/to-check-parent-window-is-iframe-or-not) 52 | 1. [How can I make a redirect page?](http://stackoverflow.com/questions/503093/how-can-i-make-a-redirect-page) 53 | 54 | [1]: http://panjiabang.gitcafe.io/blog/ 55 | [2]: http://panjiabang.gitcafe.io/blog/timeline 56 | [4]: https://www.google.com.hk/search?q=site:panjiabang.gitcafe.io/blog 57 | -------------------------------------------------------------------------------- /source/_posts/say-something-before-1111.md: -------------------------------------------------------------------------------- 1 | title: 姥姥不疼舅舅不爱,处境尴尬的老用户 2 | categories: 3 | - Life 4 | math: true 5 | cc: true 6 | comments: true 7 | date: 2015-11-09 22:54:18 8 | --- 9 | 10 | 后天就是双十一,明天晚上我们这些当码农的就要开始通宵轮值了。长达两个多月的准备,也是让人精疲力尽的,然而着一切一切都将在未来几天迎来终了,完结撒花。 11 | 12 | 前几天有高中同学微信找到我,让我帮忙在双十一的时候买东西。我自然是坚定拒绝的,不是我不想帮忙,而是身在江湖身不由己。作为系统扛第一波流量的开发者,要是因为玩忽职守没有及时发现系统的异常并消灭,估计就得回家准备简历了吧。 13 | 14 | 虽然说每个在这里的人,总有一天会离开,但是以这种方式离开,说出去也不光彩。 15 | 16 | 17 | 18 | 当几乎一切系统都可以水平扩展的时候,在某种意义上,双十一就不再是「技术的盛宴」,而是机器的堆砌。相比起明星出轨给微博带来的毁灭性打击,世界杯进球给 Twitter 带来的冲击,双十一的流量并不算是突发流量,而是一场事先策划好的大流量压测。 19 | 20 | 真的要感谢师兄极具先见之明地在系统设计之初,为数据库做了足够多份的 sharding,使得我今年在扩容的时候,没有面临数据库重构的麻烦事情,数据库扩容的工作都是给力的 DBA 帮忙搞定了,应用服务器的扩容也是问 PE 要机器搞定了。这个 sharding 的粒度,或许到明年后年也还是够用的。 21 | 22 | 当然,整个双十一准备过程也没有说的那么简单,扩容也不是加机器那么简单,加机器也得加得有理有据,要是预算没事先报上去,还得到处找人借机器,东拼西凑。 23 | 24 | DBA 妹纸近期打算开个独立博客什么的,到时候我这边给挂一个友链。 25 | 26 | 当你为系统输出了完善的业务日志,为业务产出详尽的数据报表,看着每天每天形状几乎一模一样的实时曲线,看着每周每周逐渐增长的同比曲线,基本上就可以预知双十一当日的业务报表大概的样子。 27 | 28 | 当你为系统输出了完善的错误日志,为异常配置了详细的告警,基本上不用看日志也知道哪个上游系统不稳定,或者哪个下游系统来了突发流量触发流控,或者是其他千奇百怪但是又可以忽略的告警。 29 | 30 | 当你对每个 RPC 做好异常处理,设定好能容忍的等待时长,能自动降级的弱依赖就自动降级,不能自动降级的强依赖就业务失败,基本上就不用担心上游系统的稳定性问题。 31 | 32 | 或许在电商系统的世界里,动态扩容并不是什么非有不可的特性,因为一切流量都在运营的掌控之中,今天搞个促销活动,流量翻倍,一周之后系统开始告警,同比下跌 50%😂 33 | 34 | 当然有了 Docker 之后,动态扩容也就成不了什么大问题,只要应用服务器无状态,只要物理机足够多,只要 MySQL 连接数还够用,分分钟部署镜像实现扩容。 35 | 36 | 然而这个世界上,有一种可怕的东西,叫做遗留系统。技术部里面大多数同事都在维护遗留系统。还好我负责的系统并不是遗留系统,而是去年我师兄和几个同事从零开始写出来的新系统,上线之后不久我就加入开发团队。经过半年多的开发,经历了去年双十一,又经过一年多的开发,系统里面被写入了越来越多的代码。 37 | 38 | 在物理领域,有一个著名的公式,叫做质能方程。 39 | 40 | $$e = mc^2$$ 41 | 42 | 在软件工程领域,也有一个著名的公式,叫「软件质量第一定律」。 43 | 44 | $$errors = (more\ code)^2$$ 45 | 46 | 虽然代码越来越多,越来越多,但是我还是看过代码树中几乎每一行业务代码,无论是谁提交的。也许是出于那种被称为「ownership」的东西,也许是出于对未知的不安,反正我是看过几乎每一行业务代码,当然,文件开始的那一坨 import 我是不会看的 :) 47 | 48 | 说回到双十一,我是决定不去买买买了。一个是我已经许久不在淘系电商上购物,主要消费转向线下了。另一个是我实在也没啥可买的,过冬的衣服也已经在实体店买好,服役近两年的 iPhone 5s 莫名其妙地修复了电量问题后,还能再战三年! 49 | 50 | 其实我是打算在我写出一个不是 Hello World 级别的 iOS App 之前都不换手机的。为了早日用上肾 6s,得赶在肾 7 上市之前撸一个 App 出来才行。大不了以后在后端开发的队伍中掉队了,咱还能到客户端工程师的队伍中混口饭吃,成功跨界成为客户端开发者中最会写后端的,后端开发者中最会写客户端的! 51 | 52 | 听说,每个工程师年轻的时候都有过底层梦,随着年龄的增长,当初的梦想渐渐被堆积如山的业务需求磨平,工作之余那可怜的几分钟只是想着升职加薪出任 CTO 迎娶设计师。如今的我能用多种语言换着花样写后端,能写一点简单的前端,催促着自己学习客户端,说是为了生活,却和梦想渐行渐远。 53 | 54 | 双十一是女生的购物狂欢,是情侣买买买的恩爱秀,阿里云却也跑去凑热闹,卖服务器也搞个整点秒杀。秒杀就秒杀吧,所有的优惠都只针对新用户,这让我们这些老用户怎么看? 55 | 56 | ![](//i.imgur.com/DUMujTJ.png) 57 | 58 | 也许,双十一期间,我顶多就买点新加坡地区的服务器吧。 59 | 60 | 注孤生。 61 | 62 | -------------------------------------------------------------------------------- /source/_posts/scalability-and-cost.md: -------------------------------------------------------------------------------- 1 | title: "关于可扩展性和迁移成本——以Hexo为例" 2 | date: 2015-04-28 23:12:24 3 | tags: 4 | - Blogging 5 | - Software 6 | categories: 7 | - Life 8 | - Essay 9 | cc: true 10 | comments: true 11 | thumbnail: https://ws2.sinaimg.cn/small/e724cbefgw1erloakbg0hj20hs08ymxu.jpg 12 | --- 13 | 14 | 这周六晚上我对博客动了个大手术,把博客的主题从 Pacman 换成了现在的 icarus。 15 | 16 | 大约从深夜十一点开始折腾,当我终于满意,感觉可以发布的时候,已经五点多,看看窗外天都亮了。 17 | 18 | 页面布局从之前的两栏变成了三栏,左边是个人资料和站点信息,让我可以在博客的各个页面强刷存在感。放在个人资料里面的微信二维码也不会在平板上响应式的时候把页面弄的不和谐,招聘小广告还是照样打打。 19 | 20 | 21 | 22 | 页面右侧的挂件有一个最近文章列表,如果文章有配图的话效果想必会很不错。分类挂件终于支持层级分类,之前用 Pacman 的时候我折腾了老半天才发现是主题把这个功能阉割了。总之,切换主题之后的效果我还是比较满意的。 23 | 24 | 切换的过程中,我一边修改代码调试页面效果,一边思考着为什么我切换一个主题要做这么多事情,是什么东西把博客主题的迁移成本弄的这么高? 25 | 26 | ![](https://ws2.sinaimg.cn/large/e724cbefgw1erloakbg0hj20hs08ymxu.jpg) 27 | 28 | # 学习 # 29 | 30 | 是不是一个软件需要被用户学习之后才能够正常使用,就会产生较高的迁移成本? 31 | 32 | 乍一看似乎是这么回事,花了大把的精力才学会用这么个破软件,怎么能说换就换呢?再一想,我感觉这种说法根本站不住脚,学习成本和迁移成本完全是不沾边的两回事。 33 | 34 | 当初用了许多年的 Windows,大一的时候为了技术进步,一咬牙一跺脚就把 Windows 删了只用 Linux。工作之后为了更高的工作效率买了 Mac,一个下午就把工作流从 Linux 上迁移了过来。曾经吭哧吭哧学 Vim 学了好久都没能登堂入室,大三的时候拜读了 SICP 就直接转投 Emacs。 35 | 36 | 可见,无论你在原先的软件上花了多少功夫去学习和钻研,只要别的软件更好学好用,基本上切换过去的迁移成本会很小。学习成本和迁移成本之间关系并不明显。 37 | 38 | # 扩展 # 39 | 40 | 我又在想,会不会是软件的可扩展性给软件带来了迁移成本? 41 | 42 | Hexo 是一个可扩展性很好的静态博客系统,在 2.x 版本中支持有大量的插件,升级到了 3.x 版本之后虽然插件数量减少不少,但还是瘦死的骆驼比马大。 43 | 44 | 因为并没有切换到其他的博客系统,仅仅是在 Hexo 下切换一个主题,跟插件的多少并没有关系。 45 | 46 | 如果我是切换了博客系统,然后 Hexo 能够提供目标系统不能提供的功能,目标系统在功能上的缺失就会给我带来很高的迁移成本,要么我忍忍接着迁移,要么我想办法在新系统中实现类似的功能。 47 | 48 | 之前有好长一段时间我没用 Emacs,后来还是用回去了。原因不在别的,就是有一个功能让我难以释怀,Highlight Tail。其他的编辑器没有插件或者现成方案能够实现类似效果,然而对我来说这种 eye candy 能够极大的刺激我的创作欲望,所以我最终还是回到了 Emacs 的怀抱。 49 | 50 | 虽然在这里,Hexo 的可扩展性不是造成我在切换主题时候有着有如此高的成本的原因,但是它可能称为我日后切换到其他博客系统时候的阻力。之前博客的 Timeline 页面是使用 iframe 来实现的,为了在写时间轴的时候不用手写 HTML,我在前些日子写了一个 Hexo Plugin 来处理我自定义的一个 Tag,把 Hexo Tag 语法的文本转换为我想要的 HTML 代码。 51 | 52 | 当我迁移到别的博客系统的时候,我就不得不去把这个插件用那个博客系统的方式实现一遍,甚至没法比较轻易的实现。 53 | 54 | 似乎当用户仅仅是使用别人提供的扩展的时候,只要迁移目标提供了类似的功能,其实用户的迁移成本是很低的。一旦用户为了满足自己的小众需求去创作了扩展,这时候迁移成本瞬间就上去了。 55 | 56 | # 定制 # 57 | 58 | 仔细想了想,其实创作扩展还不是导致迁移成本最高的点。一旦用户去修改了软件的源码,增加功能来满足自身的需求,用户基本上就很难迁移到其他软件上面了。 59 | 60 | 修改源码增添功能其实是一件比较费时费力的事情,而且需要用户亲自动手去做,这种需求一般来就不是普遍存在的,属于小众中的小众。软件的其他同类替代做得再好,也不太可能实现这种功能。于是,用户即使硬着头皮迁移过去了,还是面临着需求重新造轮子的悲剧。除非新的软件有着十足的吸引力,让用户不惜在一个陌生的代码中摸索,也要迁移到新的软件上。 61 | 62 | 我之前就是对 Pacman 主题做了很多很多的修改,为了尽可能的保持切换前后的一致性,我需要把这些小修改迁移到 icarus 上,同时要让这些修改和 icarus 和谐相处,因此不是简单的把代码迁移过来了事,我需要弄清楚 icarus 的代码结构页面结构等各种东西,然后在合适的地方做恰如其分的修改。 63 | 64 | 幸好 icarus 和 Pacman 的都用的 ejs 文件作为渲染页面的模板,省去了我学习新模板语言的成本。除了迁移之前的定制之外,我还把新主题中我看不顺眼的地方通通调整了一遍,可能导致访问缓慢的地方通通修改掉,于是博客终于可以拉出来见人了。 65 | 66 | # 总结 # 67 | 68 | 切换一个主题尚且如此辛苦,更不用说切换博客系统了。 69 | 70 | 但愿 icarus 这个主题能够让我用更长的时间,之前的主题,估计不会切换回去了。 71 | 72 | -------------------------------------------------------------------------------- /source/_posts/seven-concurrency-models-threads-and-lock.md: -------------------------------------------------------------------------------- 1 | title: 七周七并发模型之线程与锁 2 | tags: 3 | - Concurrency 4 | - Java 5 | categories: 6 | - Study 7 | cc: true 8 | comments: true 9 | date: 2015-04-06 23:52:07 10 | --- 11 | 12 | # 前言 # 13 | 14 | 最近我在读 *[Seven Concurrency Models in Seven Weeks][1]*,这本书使用不同的语言介绍不同的并发模型,深入浅出,让我获益匪浅。 15 | 16 | 这本书让人有一种 Talk is cheap, show me the code 的感觉。作者不会巴拉巴拉讲一大堆理论,而是先放出一段代码,然后引导读者去分析代码里面的问题,然后作出改进,然后再分析还有什么问题。这种风格适合那些真正要写代码的读者。 17 | 18 | 这本书的中文译本《[七周七并发模型][2]》于 2015 年的愚人节上架,[亚马逊][3]等多家在线商城有售。感谢黄炎先生的翻译工作,让更多国内同行能够接触到这本书。 19 | 20 | 21 | 22 | # 线程与锁 # 23 | 24 | 线程与锁是本书在第一周介绍的内容。作者将线程-锁编程模型比作福特T型轿车,虽然它能把你带到目的地,但这是一种上古时期的技术,难以驾驭,和其他新技术相比,显得更加危险和不可靠。 25 | 26 | 然而,线程-锁编程模型在大多数时候依然是开发并发程序的首选,也是其他许许多多并发模型的基础。即使我们不打算直接使用它,也得知晓其中原理。 27 | 28 | 作者以 Java 语言为载体,为我们介绍了线程与锁的工作方式,原理性的知识适用于其他所有支持线程和锁的语言。 29 | 30 | # 脑图 # 31 | 32 | ![线程与锁](https://ws1.sinaimg.cn/large/e724cbefgw1exdxm6pb8uj21b60kgwk5.jpg) 33 | 34 | 35 | [1]: http://book.douban.com/subject/25736606/ 36 | [2]: http://book.douban.com/subject/26337939/ 37 | [3]: http://www.amazon.cn/dp/B00V4B2KEI/ 38 | -------------------------------------------------------------------------------- /source/_posts/short-rest-in-70th-anniversary-of-WW2.md: -------------------------------------------------------------------------------- 1 | title: 休息,休息一会儿 2 | categories: 3 | - Life 4 | cc: true 5 | comments: true 6 | date: 2015-09-06 00:11:00 7 | --- 8 | 9 | 10 | 最近很累,终于熬到了放假,可以稍微休息一会。 11 | 12 | 这也许是近半年来第一个假期,我能够告诉自己不要去做任何与工作相关的事情并且强制执行,认认真真的过一次假期生活。 13 | 14 | 吃饭睡觉看书看电视,这三天真是少有的惬意日子。 15 | 16 | 17 | 18 | 第一天的午餐泡面解决,久违的汤达人,晚餐 KFC。第二天的午餐去公司食堂搞的烧鸭饭,晚餐跟着室友观止巨巨去印象城吃牛排。第三天午餐晚餐 KFC。 19 | 20 | 这几天终于可以睡个好觉,虽然可恶的生物钟让我早晨八九点就睁开了眼,但是我也可以随意的睡回笼觉直到午餐时间。有一次更是一觉睡了 15 个钟头,虽然睡醒之后还是感到十分疲倦,但是这几天睡下来,已经让我感觉好了一些。 21 | 22 | 借着这次放假,看完了两本书,其中一本是我拖了好久都没看完的,一本是冲着同事的名声买的。 23 | 24 | 拖了许久都没能看完的是《像外行一样思考,像专家一样实践》。这本书是观止巨巨的,被我借过来了~之前好几个周末,我在小区附近的咖啡馆吃中餐或者晚餐的时候都带着这本书去,借着咖啡馆的氛围{%ruby 读|装%}一会{%ruby 书|逼%}。然并卵,每次都是看不到几页就想着回去或者去公司干活,这次终于定下心来把它读完了,不容易。 25 | 26 | 这本书很有名,而它的内容也对得起它的名声。虽然副标题叫做“科研成功之道”,但是金出先生在里面为我们揭示的道理和个人的经历总结,对于当工程师的人同样适用,同样有参考意义和教育意义,特别是对当软件工程师的我们。 27 | 28 | 那本冲着同事的名声买的,就是《Java 并发编程的艺术》了。作者之一是方腾飞大大,并发编程网的站长。当年还在学校的时候就看过这个网站的不少文章,所以那时候虽然还没用 Java,也知道这个网站和方腾飞大大了。 29 | 30 | 入职之后师兄也推荐我有空多看看并发编程网的文章,乃至后来我开始写 Guava 系列博文之后也向并发编程网投稿了几篇,从读者变成了作者。正因为并发编程网在我刚开始使用 Java 的时候给了我不少的帮助,听闻方腾飞大大出书了,我便迫不及待地买了一本。 31 | 32 | 这本书比较深入地介绍了 Java 语言及标准库中,并发编程的原理和实现,以及各种顶层的封装,从 violate 关键字的字节码实现、内存屏障、缓存协议,到锁、并发容器、线程、线程池等方方面面。 33 | 34 | 如果回到一年之前,这本书肯定让我如获至宝,但是如今的我翻读这本书的时候,便没有意外的惊喜了。过去一年真的在 Java 开发方面学到了很多。 35 | 36 | 这三天假期里,我看了三部电影,都是在假期的最后一天看的。基本上头两天净看书,最后一天净看电影的节奏。 37 | 38 | 第一部是《模仿游戏》,讲祖师爷图灵大人的故事。第二部是《终结者:创世纪》,不知道讲的什么故事。第三部是《星际穿越》,讲的是人类快被地球整死了被迫去太空另寻家园的故事。 39 | 40 | 第二部乏善可陈,三部电影中最让我难忘的是《模仿游戏》,其次才是《星际穿越》。 41 | 42 | 虽然图灵参与破译德军密码这段历史我早已熟烂于心,而且电影作为艺术作品不免有夸张和改变,但是我依旧深陷其中。 43 | 44 | 英雄未必都有好结局,但这不影响他们成为英雄。 45 | 46 | 每次想起图灵,脑海中都会浮现出当初学习人工智能的时候,廖士中教授的那句“图灵不是计算机科学家,是计算机科学之父,后来的人做计算机做的再牛,都是孙子”。 47 | 48 | 《星际穿越》是一部少见的三小时电影,我比较喜欢里面那个叫 Dr. Brand 的妹纸,看完之后各种翻影评和电影资料,得知演员是安妮·海瑟薇。 49 | 50 | 51 | -------------------------------------------------------------------------------- /source/_posts/show-your-favorites-collection-in-hexo.md: -------------------------------------------------------------------------------- 1 | title: 做一个照片流,分享你喜欢的书和电影 2 | tags: 3 | - Hexo 4 | - Blogging 5 | categories: 6 | - Study 7 | hljs: true 8 | thumbnail: //i.imgur.com/aGTXZhIm.jpg 9 | cc: true 10 | comments: true 11 | date: 2016-01-28 02:26:02 12 | --- 13 | 14 | 最近开始有网友注意到我博客中的 [Favorite][1] 页面,并在该页面下留言或者邮件咨询页面的实现或者实施问题。有些是想知道我这个页面是怎么实现的,有些是尝试在自己的博客中加入类似页面后发现图像没有加载的。 15 | 16 | 随着 Hexo 这个静态博客框架越来越流行,它的用户群中也就加入了越来越多的普通用户。作为一个自诩为 Hexo 资深用户的家伙,看到自己信赖的软件被广泛传播,其实是挺高兴的。 17 | 18 | 19 | 20 | 之前实现这个 Favorite 页面的时候,没有想到还有人会喜欢,也就没有把它实现为一个可以从 npm 安装的 Hexo 插件,而是仅仅作为我维护的主题的一个脚本插件的存在。 21 | 22 | 于是我当初的一点点偷懒就给喜欢这个页面形式的普通用户带来了困扰,他们不知道如何从我的博客顺藤摸瓜找到我托管在 Github 的站点源码,也不知道如何排查页面行为不符合预期的问题。这些繁琐的细节,普通用户本应无需感知。 23 | 24 | 于是我决定对当初草草实现的脚本插件做一点修改,使得它能够方便地被重用、配置,尽量做到开箱即用的程度,而且在用户需要定制的时候尽量不束缚用户的手脚。于是为了平衡重用上的和定制上的便利,我依旧没有把插件发布到 npm。 25 | 26 | ## 安装 ## 27 | 28 | Hexo 的脚本插件是 Hexo 插件的一种特殊形式,仅当插件简单到不需要依赖 Hexo 之外的其他模块时使用。 29 | 30 | 从 Github 上我博客的源码目录下载脚本,然后放到你本地博客源码目录的 `scripts` 目录或者主题目录下的 `scripts` 目录。 31 | 32 | ```bash 33 | cd myblog 34 | mkdir -p scripts && cd scripts 35 | wget -c https://raw.githubusercontent.com/JamesPan/blog-src/8ac83216ef4f2904d326ec7cddcf7adba56d9757/themes/icarus/scripts/image-stream.js 36 | ``` 37 | 38 | ## 配置 ## 39 | 40 | 为了实现开箱即用,插件自带了默认配置,不做额外配置,和在站点的 `_config.yml` 中使用如下配置等价: 41 | 42 | ```json 43 | image_stream: 44 | jquery: //cdn.bootcss.com/jquery/2.1.0/jquery.min.js 45 | jquery_lazyload: //cdn.bootcss.com/jquery.lazyload/1.9.1/jquery.lazyload.min.js 46 | img_placeholder: https://ws4.sinaimg.cn/large/e724cbefgw1etyppy7bgwg2001001017.gif 47 | ``` 48 | 49 | 前面两个是插件依赖的模块的 CDN 链接,第三个是实现页面中图片懒加载时用到的占位符,如果有需要可以替换为自己喜欢的链接。 50 | 51 | 如果博客主题已经默认引入了 jQuery,那么建议在配置中将 `image_stream.jquery` 设置为 false。 52 | 53 | ``` 54 | image_stream: 55 | jquery: false 56 | ``` 57 | 58 | ## 使用 ## 59 | 60 | 在 Hexo 博客的本地目录创建一个目录作为 favorite 页面目录。 61 | 62 | ``` 63 | myblog 64 | ├── _config.yml 65 | ├── package.json 66 | ├── source 67 | │   └── favorite 68 | │      └── index.md 69 | └── themes 70 | ``` 71 | 72 | 然后在 index.md 中使用插件定义的两个模板来生成 favorite 页面。 73 | 74 | ![](//i.imgur.com/r2EVe1y.png) 75 | 76 | ## 缘由 ## 77 | 78 | 为什么我会想到要搞这么个 Favorite 页面呢?其实是受到 这个页面的启发。 79 | 80 | 这个博主在 About 页面放了一个照片墙,分享的是读过的书和在读的书,数据来自豆瓣,照片墙也是用豆瓣的 widget 弄出来的。 81 | 82 | 当时我测试了一下这个页面,发现这个页面用的豆瓣 widget 在响应式上做的很糟糕,于是就打算自己搞一套。 83 | 84 | 但是刚才我在尝试[豆瓣收藏秀][2]的时候,发现豆瓣秀不仅能展示图书,还能展示电影、音乐、舞台剧等等,而且响应式也做得不错,展示效果也勉强可用虽然我并不满意。如果你在豆瓣积累了大量数据,那么我自然会建议你直接在 Favorite 页面插入豆瓣秀,而不是像我这样自行维护。 85 | 86 | 自己维护一份 Favorite 数据也是有好处的,毕竟豆瓣收藏秀的数据都在豆瓣那里,万一豆瓣把数据弄丢了,或者由于你懂的的原因把一些书籍或者电影之类的给雪藏了,自己又很想在 Favorite 上分享,找谁说理去? 87 | 88 | 甚至还能够把一段照片墙嵌入到博文里面,就像这篇文章 「[国庆长假,那些吃喝玩乐,那些遗憾][3]」,这个如果用豆瓣秀估计就没有这么容易搞定了。 89 | 90 | 91 | [1]: /favorite/ 92 | [2]: https://www.douban.com/service/badgemakerjs 93 | [3]: /2015/10/07/the-national-days-of-2015/ 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /source/_posts/spring-of-artificial-intelligence-again.md: -------------------------------------------------------------------------------- 1 | title: AlphaGo, The Machine 和我所知道的人工智能 2 | tags: 3 | - Thinking 4 | categories: 5 | - Study 6 | thumbnail: https://i.imgur.com/Hjs8fcEm.png 7 | cc: true 8 | comments: true 9 | date: 2016-03-10 23:52:47 10 | --- 11 | 12 | AlphaGo 连续两天在围棋上击败李世石,世界为之侧目。「开发者的大事,大快所有人心的大好事」,相比起 Apple 发布 iOS 8 时的自吹自擂,这更称得上是开发者的大事,却不见得是大快所有人心的大好事。 13 | 14 | 当然不管别人怎么想,我是很开心的。毕竟我作为混迹在计算机工业界的小虾米,有幸在有生之年看到我的同行们再次越过了一座高山,虽然没有亲身参与到项这伟大的事业中,却也感同身受,喜大普奔。 15 | 16 | 17 | 18 | {% recruit %} 19 | 20 | 自从几十年前人工智能出现在大众视野中,它就成为了人民群众的一个闲聊扯淡时的谈资,尤其是类似于「奇点」这种耸人听闻的名词,更是被非专业人士津津乐道,仿佛知道了奇点就能做些什么使自己摆脱被机器人统治的命运。 21 | 22 | {% blockquote @Fenng 阿尔法狗们早就战胜了人类,但我并不太关心 http://t.cn/RGnIwnQ %} 23 | 我并不担心「奇点」的到来,如果你的思想已经受到禁锢,何必还在乎统治你的是否是机器人呢? 24 | {% endblockquote %} 25 | 26 | 现在的中文互联网上,找不到一个让我满意的关于人工智能的定义。还记得当初学习人工智能的时候,廖老师给出了一个十分得体的定义,我虽然已经回忆不起这个定义的准确遣词,但是定义中透露出来的那种谦逊、内敛的感觉,我一直无法忘记。 27 | 28 | 为此,我特意请求学弟帮忙,咨询还在学校里并且上过廖老师讲授的人工智能课程的同学。廖老师对人工智能的定义是这么说的: 29 | 30 | > 人工智能是研究理性智能主体的一般原理和计算方法的学科 31 | 32 | 至于那些所谓的人工智能是用机器去模仿人的智能,通过了图灵测试就具有人工智能之类的说法,则是人工智能萌芽期留下的陈年往事,被科技媒体翻出来炒炒冷饭,博博眼球。 33 | 34 | 主流的人工智能研究不是去研究模仿人的智能,因为人不是理性智能主体。是不是瞬间感受到了深深的歧视?人工智能也没有说自己要去造机器人啊,造机器人的那叫机器人学不叫人工智能。 35 | 36 | 其实人工智能一直都是计算机科学的前沿领域,现在我们所知道的自然语言处理(NLP)、机器学习(ML)以及其他许多子领域,都曾经被叫做人工智能,或者是人工智能领域的问题。一个有趣的现象是,当一个问题被人工智能搞出了大致方向、产出了一些成果之后,这个问题就不再被叫做人工智能了,它会换一个名字,在计算机科学里面开创一个全新的子领域然后继续发展。 37 | 38 | 人类善于构造比自己强大的机器,这是不争的事实,前人构造出了比人类更擅长快速移动的汽车飞机,比人类更擅长挖断光纤的挖掘机,比人类更擅长下国际象棋的深蓝,我们的生活并没有因此而变得更糟,却是因此变得更好。如今我们有生之年,AlphaGo 被我们之中天赋更高,工作更努力的天才们创造出来了,人类因此拥有了比人类更擅长下围棋的机器,有什么不好呢? 39 | 40 | 愚蠢的地球人啊,在计算机技术如此发达而且还在快速发展的今天,你还以为在智力活动上你能有几件事情比计算机强,就算有,能强多久?我算微积分不如 Mathematica,打 Dota 不如疯狂的电脑,算矩阵不如 Matlab,那又如何? 41 | 42 | 就算我高数挂科,也不妨碍我在 Mathematica 的帮助下解决数学问题,就算我线代挂科,也不妨碍我在 Matlab 的帮助下解决矩阵问题。科技的进步,就会使得原本需要大量时间勤学苦练才能获得的技能,变得唾手可得,就会使得原本只有专家才能拥有的经验和决断能力,普通人在机器的辅助下也能拥有。 43 | 44 | 或许未来,我们中间出现了天才般耀眼的人物,创造出了比我更擅长开发软件的机器,我也不必担心失业,因为在那之前,我会转职成为产品经理,然后每天改三次需求。 45 | 46 | 前些日子我看过一部美剧,「疑犯追踪」。里面也有一台「超级人工智能」,被称作 The Machine,不知道会不会有美剧迷在 AlphaGo 大火之后想起这台萌萌哒的神龙见首不见尾的机器。 47 | 48 | {% blockquote Obituary Steve Jobs http://www.economist.com/blogs/babbage/2011/10/obituary %} 49 | All computers do is fetch and shuffle numbers, he once explained, but do it fast enough and “the results appear to be magic”. 50 | {% endblockquote %} 51 | 52 | 乔帮主明明是一个不那么懂计算机的人,说出的关于计算机的话,却是那么的在理。计算机的英文是 computer,而 compute 是计算的意思,而且不是微积分这种级别的计算,算微积分叫做 calculate,算 1+1 叫做 compute。计算机原本就是只能做这么简单的计算,但是算得足够快,魔法就开始了。 53 | 54 | 接下来的几天,让我们一起见证奇迹。 55 | 56 | 57 | -------------------------------------------------------------------------------- /source/_posts/surge-is-a-developer-tool.md: -------------------------------------------------------------------------------- 1 | title: Surge 是一个 Web 开发者工具,你们不要拿来干坏事 2 | tags: 3 | - Tool 4 | categories: 5 | - Study 6 | cc: true 7 | thumbnail: https://ws2.sinaimg.cn/small/e724cbefgw1exhepdy2j3j204v04v0sl.jpg 8 | comments: true 9 | date: 2015-10-29 01:01:44 10 | --- 11 | 12 | 最近有一个叫 Surge 的 App 火了。一时间网上出现各种介绍如何科学使用 Surge 的文章,V2EX 还有网友发帖感谢 Surge 的作者。 13 | 14 | 这个 App 售价 68 RMB,好贵有木有,但是我还是没忍住加入了剁手大军。 15 | 16 | 17 | 18 | Surge 是一个支持 HTTP、HTTPS、SOCKS5 等协议的代理工具,通过在设备上添加 VPN 服务来接管设备的网络流量。启动代理的时候,启动一个名为 Surge 的 VPN,然后网络流量就到 Surge 那里去了,至于每个 package 应该直接发送还是借助代理,则由代理规则决定。 19 | 20 | 这个描述也许会让你想起 ProxySharp、gfwlist 之类的工具,但是它也仅仅是一个代理工具而已,并不是红杏之类的科学上网工具。 21 | 22 | 不要看到代理就想到科学上网😂不是每一个代理都可以科学上网。 23 | 24 | 然而,Surge 却是一个非常适合科学上网的代理。之前我还想着 iOS 上面怎么搞个黑科技,通过 SSH Tunnel 代理一下,然后我就可以不用买梯子了,这下好了,黑科技出来了。 25 | 26 | 27 | Surge 的入门以及使用可以参考「[Surge 新手使用指南][1]」。 28 | 29 | 在毕勤的[博文][2]中给出了一个好用的配置文件的链接,,可以直接导入 Surge,但是导入之后需要手动修改一下服务器的 IP、端口,服务的密码密码等等关键信息。我这里为它做了个备份,。网址长了不少,但是可用性还是有保障的,毕竟异地多活~ 30 | 31 | 如果你也买了 Surge,我们还是好好地把它当做开发者工具吧,不要拿来科学上网什么的。 32 | 33 | [1]: https://medium.com/@scomper/surge-配置文件-a1533c10e80b#.r4987iufv 34 | [2]: https://www.lifetyper.com/2015/10/shadowsocks_conf_for_surge_on_ios.html 35 | 36 | -------------------------------------------------------------------------------- /source/_posts/svn-http-timeout.md: -------------------------------------------------------------------------------- 1 | title: SVN 连接超时与 http-timeout 参数 2 | tags: 3 | - Subversion 4 | - Tool 5 | categories: 6 | - Work 7 | cc: true 8 | comments: true 9 | hljs: true 10 | date: 2015-04-15 01:08:28 11 | --- 12 | 13 | 我厂大部分项目使用 SVN 进行版本控制,只有一些新的项目,然后项目的开发者们都喜欢使用 Git,才会使用 Git 和 Gitlab 进行代码托管。 14 | 15 | 我正在开发的一个项目就是这种情况,主应用托管在 SVN 上,由我亲自搭建的后台应用托管在 Gitlab,然后另一个新搭建的半后台应用由于某种原因,又使用了 SVN。 16 | 17 | 最近我在使用 SVN 的时候遭遇了奇怪的问题。提交和更新都没有问题,唯独拉取提交记录的时候,总是失败,无论是用 IDEA 还是命令行。错误信息是类似下面这样的。 18 | 19 | ``` 20 | svn: E175012: Connection timed out 21 | ``` 22 | 23 | 24 | 25 | 一开始的时候我怀疑是 SVN 的版本比较低,于是用 brew 安装了最新的稳定版,问题依旧。 26 | 27 | 使用错误码在 Google 上一番搜索之后,发现一个参数,http-timeout 或许能够帮助解决问题。 28 | 29 | 接下来直接搜索 http-timeout,结果找到一篇很长的英文文档,[Runtime Configuration Area][1]。当时我随便扫了扫,没有仔细阅读。我直接在文章中搜索 http-timeout,结果第一个出现的位置是关于 Windows 注册表的,第二个就是介绍参数的作用、单位之类的,对于我调整参数没什么帮助。 30 | 31 | 无意间我从这篇文档中看到,用户对 SVN 的自定义配置在 ~/.subversion 目录。于是我直接切换到这个目录,然后用 ack 命令搜索 http-timeout,果然被我找到了。 32 | 33 | 从配置上看,超时时间被设置成了 10s。于是我试着把超时时间调整为 60s,接着执行 svn log 查看提交记录,果然成功获取到记录,不再超时了。 34 | 35 | 36 | [1]: http://svnbook.red-bean.com/en/1.7/svn.advanced.confarea.html 37 | 38 | -------------------------------------------------------------------------------- /source/_posts/the-duoshuo-migrator.md: -------------------------------------------------------------------------------- 1 | title: "我把博客评论从多说迁移到 Disqus 时造的轮子" 2 | date: 2015-04-21 00:48:10 3 | tags: 4 | - Python 5 | - Tool 6 | categories: 7 | - Study 8 | 9 | cc: true 10 | hljs: true 11 | comments: true 12 | --- 13 | 14 | 这是我在一年前随手写下的代码,而且这个代码只会被我使用一次,如今我已经没有精力和时间再去跟进和维护它了。如果你在使用中遇到问题,能够自己解决最好,不能解决的话请访问 http://urouge.github.io/migrate-to-disqus/ 获取一个更新的轮子,前些日子有人用它完成了评论系统的迁移。 15 | 16 | # 背景 # 17 | 18 | 前几天我受够了多说的各种漏洞和问题,终于把评论系统切换到了 Disqus。为了尽可能的保留之前网友们的留言和评论,我写了个 Python 程序把多说导出的 JSON 格式文件转换成了 Disqus 支持的 WXR (WordPress eXtended RSS) 格式。 19 | 20 | 对切换评论系统的前因后果以及中间过程感兴趣的话,可以看看我之前的博文《{% post_link goodbye-duoshuo %}》。 21 | 22 | 23 | 24 | # 轮子 # 25 | 26 | 代码我以 GPL 2.0 协议开源托管在 [Github][2],如果感兴趣可以自行取用。 27 | 28 | {% github JamesPan duoshuo-migrator 3f9938c %} 29 | 30 | 代码明显属于糙快猛的风格,没有太多的讲究,能把活干好就行。好像自从我大学时期读了垠神的这篇 《[谈程序的“通用性”][1]》 之后,写出的脚本和一次性轮子都是这种风格。 31 | 32 | # 用法 # 33 | 34 | 这个脚本依赖 lxml 来生成 XML 文件,所以使用之前需要把这个依赖给装好。 35 | 36 | ```bash 37 | pip install lxml 38 | ``` 39 | 40 | 这个脚本的参数其实很少,-h 查看帮助,-i 指定输入文件,如果不指定就从 stdin 读取,-o 指定输出文件,如果不指定就输出到 stdout。 41 | 42 | 我一般这么用: 43 | 44 | ```bash 45 | python duoshuo-migrator.py -i ~/Desktop/export.json -o a.xml 46 | ``` 47 | 48 | 如果程序执行的过程中发现有文章的标题为空,会往 stderr 中输出一些信息来提醒用户注意,比如这样: 49 | 50 | > found article without title, id=1173938669371785301, link=http://www.jamespan.me/blog/2015/01/22/trick-of-paging-query/ 51 | 52 | # 最后 # 53 | 54 | 我对 lxml 库不是很熟悉,所以写生成 XML 那段代码还是颇费了一番功夫,写这种代码真是磨性子。 55 | 56 | 希望我顺手造的轮子能在你逃离多说拥抱 Disqus 的时候,帮你减少麻烦节省时间,也希望我的贡献让这个世界稍微变得美好了那么一点点~ 57 | 58 | 59 | [1]: http://www.yinwang.org/blog-cn/2013/04/13/generality/ 60 | [2]: http://github.com/JamesPan/duoshuo-migrator 61 | [3]: https://www.haomwei.com -------------------------------------------------------------------------------- /source/_posts/time-is-money-friend.md: -------------------------------------------------------------------------------- 1 | title: 时间就是金钱啊,朋友 2 | tags: 3 | - Tool 4 | categories: 5 | - Life 6 | thumbnail: https://i.imgur.com/BVWHz6bm.jpg 7 | cc: true 8 | comments: true 9 | date: 2016-07-27 00:30:15 10 | --- 11 | 12 | 最近因为工作上的原因,每天都在杭州市的转塘街道和仓前街道两地奔波,一趟几十公里,打车都需要几十分钟到一小时的样子,出租车跑一趟的钱都接近一百大洋。不过好在这种状态持续不了多久了,很快部门就要搬迁了,到时候上班起来会近很多。 13 | 14 | 连接留下和转塘的道路比较有意思的,一条是国道,另一条是绕城高速,两条路几乎是平行着走的,只不过高速在上面,国道在下面。于是每次打车的时候,都会被司机师傅询问同一个问题:走不走高速? 15 | 16 | 17 | 18 | {% recruit %} 19 | 20 | 自从我离开海南之后,我才知道,在中国的绝大部分地方,走高速是要收取过路费的。从留下到转塘这段,高速费 10 元,预期能节省 20 分钟。 21 | 22 | 用 10 块钱买 20 分钟提早到达,是否值得呢?20 分钟 10 元,1 小时 30 元,8 小时 240 元,12 小时 360 元。这笔账算下来,作为工薪阶层,如果一天的收入超过了 240 元,那么这笔金钱和时间的交易基本上就是划算的。如果工作比较辛苦,996 什么的,一天的收入就得超过 360 元才勉强称得上划算。 23 | 24 | 搬家住进转塘某贫民窟之后,我买了一台价值大约 3.6k 大洋的带烘干功能的洗衣机。过去两年的生活,让我确认了一件事情:我实在实在实在是讨厌做家务啊! 25 | 26 | 洗衣服已经有洗衣机代劳了,可是晾衣服对我来说也是苦事一桩,经常是晚上把衣服扔进洗衣机里洗了一夜,早上起床一看时间不早了该上班去,便记不得还有晾衣服这种事情。夜里加班回来从洗衣机里拿出湿漉漉的衣物放到脸盆里,本应立刻去阳台晾起,却又磨磨蹭蹭十分不愿,几分钟后便将家务事抛在脑后,一心一意玩我的电脑去了。待到我从赛博空间回到现实世界,却又夜色已深,常常是凌晨一两点,躺床上便沉沉睡去说什么也不愿爬起来把衣服晾了。如此循环往复几日,衣服上便有了异味,只能重新放回洗衣机再洗一遍,直直折腾到快要没有干净衣服可穿了,才强迫自己把晾衣服这等苦差事执行了,避免陷入更大的尴尬。 27 | 28 | 一盆衣服洗多次,浪费资源不说,更烦的是到了公司后开始为自己的行为感到自责,「又不晾衣服,懒死你算了」、「懒成这样怎么找得到女朋友」、「死宅の日常生活」各种弹幕在脑海中飞过,心中立下今晚下班就回去把衣服晾了的 flag。第二天到公司还是依旧上映和昨日并无差别的批评与自我批评的内心戏,「Re:从零开始的死宅生活」天天热播。 29 | 30 | 终于买了一台带烘干的洗衣机,终于迎来了救赎,再也不用为晾衣服伤脑筋了,仿佛生命因此得到了延长。天若有情天亦老,我为自己续一秒。 31 | 32 | 除了讨厌晾衣服,我还讨厌叠衣服,感觉自己已经没救了。为此,我打算要尝试一种不需要衣柜的生活。我买了一座竹制衣架,有淡淡的 MUJI 风格。原本打的如意算盘,衣服在洗衣机里烘干之后,不用叠了直接挂起来。突然,我发现一个十分严重的问题:晾衣架并不会自己长腿跑到衣服上,我该如何把衣服挂起来? 33 | 34 | 在此之前,晾衣服是必不可少的步骤,因此当我把晒干的衣服收下来的时候,晾衣架就在衣服上,我随手一挂就可以了。如今我成功跳过了晾衣服这个步骤,顺带着把晾衣架穿到衣服里的工序也跳过了,这可如何是好?如果我需要一件一件把衣服挂起来,这和晾衣服有什么区别! 35 | 36 | 我陷入了沉思。我开始思考人生。 37 | 38 | 我讨厌的不仅仅是晾衣服,也讨厌衣服几天不晾就会产生异味需要重新洗,更讨厌几天不晾就没有干净衣服可以穿。现在衣服洗完就是烘干的,即使几天不挂起来也不会造成什么尴尬事件,那么我只需要尽可能的推迟处理挂衣服这种麻烦事就好了。 39 | 40 | 把不愉快的事情尽可能向后拖延,直到不得不去做的时候才开始做,这对我们学计算机科学的人来说再熟悉不过了,各种延迟求值就是这种策略的具体运用。还有我们设计大型系统中常常会用到一种叫做「消息队列」的中间件,帮助系统削峰填谷,前端系统把各种事件一股脑扔进消息队列,后端系统在合适的时机慢慢消费。 41 | 42 | 于是我也需要一个帮助我削峰填谷的衣服队列。衣服从洗衣机里烘干拿出来,先扔到队列里头,这样就完成了衣服的生产。我心情好的时候从队列中挑选一些衣服挂起来,相当于把衣服放入了另一个队列;心情不好的时候直接从队列里把衣服翻出来穿上走人,相当于完成了衣服的消费。衣服穿了一天回来脏了臭了,扔到脏衣框里,脏衣框满了再扔到洗衣机里,完成一次大循环! 43 | 44 | 我真的是太机智了!这个衣服队列也可以有很多种实现,比如直接把洗出来的衣服堆床上,也可以买一个专门放干净衣服的篮子。 45 | 46 | 感觉生命又一次得到了延长,为自己续一秒。 47 | -------------------------------------------------------------------------------- /source/_posts/tmux-static-compile.md: -------------------------------------------------------------------------------- 1 | title: 静态编译 Tmux 2 | tags: 3 | - Linux 4 | categories: 5 | - Work 6 | hljs: true 7 | cc: true 8 | comments: true 9 | date: 2015-06-12 23:36:07 10 | --- 11 | 12 | 最近开始使用 Tmux 之后,感觉还是在服务器上才能发挥出 Tmux 的价值。可惜的是公司的服务器上没有安装 Tmux,跳板机上我也只有普通用户权限,没法安装软件,于是我琢磨着从源码编译一个。 13 | 14 | Tmux 唯一的依赖是 libevent,所以我需要先把它编译出来。之前我编译软件之后都是直接使用 root 权限,如今没有了 root 权限,安装软件都成了让我拙计的事情。 15 | 16 | 17 | 18 | 先从最近声名狼藉的 sourceforge 把 libevent 的源码包抓下来,然后从 Github 把 tmux 的源码包也抓下来。 19 | 20 | ```bash 21 | wget -c https://sourceforge.net/projects/levent/files/libevent/libevent-2.0/libevent-2.0.22-stable.tar.gz 22 | wget -c https://github.com/tmux/tmux/releases/download/2.0/tmux-2.0.tar.gz 23 | ``` 24 | 25 | 解压之后开始配置编译过程。当我们没有 root 权限的时候,编译之前就要设置软件的安装目录了。 26 | 27 | ```bash 28 | ./configure --prefix=~/libevent 29 | make 30 | make install 31 | ``` 32 | 33 | 不同的软件编译配置不尽相同,但是作为一个约定,`configire -h` 总是能给出当前命令的帮助文档。 34 | 35 | 安装 libevent 到指定目录之后,可以开始编译 tmux。因为要让 tmux 的 configure 脚本找到 libevent,tmux 的安装命令稍显复杂。 36 | 37 | ```bash 38 | ./configure --prefix=~/tmux --enable-static CFLAGS=-I~/libevent/include LDFLAGS=-L~/libevent/lib 39 | make 40 | make install 41 | ``` 42 | 43 | CFLAGS 是 C 编译器参数,-I 后面带着需要引用的头文件的路径。LDFLAGS 是链接器的参数,-L后面带着库文件的路径。 44 | 45 | 与 libevent 的默认开启静态链接不同,配置 tmux 编译过程时需要显示开启静态链接,否则以后运行 tmux 的时候都需要在动态库目录中包含 libevent 的动态库。当然,静态链接之后的二进制文件会相应的大一些。 46 | 47 | 48 | -------------------------------------------------------------------------------- /source/_posts/two-years-in-alibaba-xixi-campus.md: -------------------------------------------------------------------------------- 1 | title: 别了,西溪园区 2 | categories: 3 | - Life 4 | thumbnail: https://i.imgur.com/4bv9V0Gm.jpg 5 | cc: true 6 | comments: true 7 | date: 2016-07-31 23:33:57 8 | --- 9 | 10 | 明天开始,我就要换个地方上班了,告别工作了两年多的阿里巴巴西溪园区。不是换了工作,而是部门换了办公地点,从乡下(余杭)搬到了山里(转塘)。在更早一些时候,为了迎接办公地点的变动,我十分不舍地搬离了一到杭州就进驻的小区——翡翠城,住进了转塘某贫民窟。不仅居住条件下降了,房租开销还上涨了,真是无奈。 11 | 12 | 最近我工作上比较忙,为了追赶进度,周末不得已也得加班写代码,于是周日的今天,(也许)就成了我在西溪园区办公的最后一天。 13 | 14 | 15 | 16 | {% recruit %} 17 | 18 | 周五下午我们就已经把个人办公物品打包,显示器什么的全都贴上了标签,周六的时候就被运到了云栖小镇,于是整个办公区便是空荡而略显凌乱的样子。没有了外接显示器,Air 那不大的屏幕便愈发显得狭小仓促,进入分屏模式写代码更觉得不便。 19 | 20 | > 叶先生,今日我把名声送给你。往后的路,你是一步一擂台。希望你像我一样,凭一口气,点一盏灯。要知道念念不忘,必有回响,有灯就有人。 21 | 22 | ![Filco Minila Air](https://i.imgur.com/4bv9V0Gl.jpg) 23 | 24 | 午饭之后,我让小师妹来了一趟园区,送了她一副机械键盘。当年我离开菜鸟,琨少赠我一把 Poker II 作为[纪念][1]。那把 Poker II 我一直在用着,我也一直在努力向琨少看齐。这把 Minila Air 陪伴我度过了在菜鸟的最后半年多的时光,直到后来我加入阿里云后,买了一把 HHKB,它才渐渐闲置起来。 25 | 26 | 下午回到翡翠城我之前居住的小屋里,把搬家时候没能带走的东西,该扔的扔,该打包的打包,然后给小屋做了个大扫除。 27 | 28 | ![](https://i.imgur.com/xLbZ3iMl.jpg) 29 | 30 | 感觉这房间自从我住进来之后,从来没有这么干净过。 31 | 32 | 我再次被自己的衣服杂物的数量吓到。说好的断舍离,为什么最后还是有这么多乱七八糟的东西? 33 | 34 | 无论如何不舍,终究还是离开了我生活了两年的地方。离开了翡翠城小区,离开了西溪园区,也离开了宇宙中心——西溪印象城。 35 | 36 | ![黑暗之门@印象城](https://i.imgur.com/jIgKRJFl.jpg) 37 | 38 | 印象城是我在杭州这两年来唯一去过的商业街,也是我所知范围内唯一靠谱像样的 Mall,两年来的吃喝玩乐都在里面了,地下一层的 KFC,一层的无印良品、Lee、星巴克,二层的西堤厚牛排、煮火,三层的中影国际影城,构成了我对印象城的记忆。还有朋友带着朋友的朋友从深圳来杭州玩,于是我们阿里腾讯联谊会的几个小伙伴在印象城完成了一次愉快的午餐。 39 | 40 | 因为感觉自己在未来比较长的一段时间都没有时间和机会再来印象城玩耍了,我趁着「魔兽」电影还在上映,魔兽周边还可以兑换的时候,用全部的印象城会员积分,兑换了一个手机壳和一个钥匙扣。美中不足的是联盟的钥匙扣已经没货了,我只好拿了个部落的。 41 | 42 | ![](https://i.imgur.com/c4WfYv6l.jpg) 43 | 44 | 还好,就在今晚,我和室友发现了转塘地区的新的宇宙中心——象山国际广场。 45 | 46 | 日子一天一天过去,天下没有不散的宴席。在翡翠城的两年,几位室友都成了亲近的朋友,感谢朋友们在事业和生活上对我的提携和关照。 47 | 48 | 离开了西溪园区,失去了许多小小的福利。再也没有哪个理发店能像园区里的理发店那样物美价廉,还不用煞费苦心和理发师进行打死不办卡的周旋;再也没有哪个星巴克能像园区一样给九折优惠,虽然九折也并没有少多少钱。当年我加入阿里,并不是为了这些小小的福利,如今失去了,又有什么可惜呢? 49 | 50 | ![凌晨五点的西溪园区](https://i.imgur.com/92xbZ7ll.jpg) 51 | 52 | 轻轻的我走了,正如我轻轻的来;我轻轻的招手,作别西溪的云彩。 53 | 54 | [1]: /2016/01/23/poker-ii-and-kindle/ 55 | -------------------------------------------------------------------------------- /source/_posts/url-encoding.md: -------------------------------------------------------------------------------- 1 | title: "陈年老坑之 URL Encoding" 2 | date: 2015-05-17 22:51:22 3 | categories: 4 | - Work 5 | cc: true 6 | comments: true 7 | thumbnail: https://ws3.sinaimg.cn/small/e724cbefgw1es8uaglowgj20ca07f3yz.jpg 8 | --- 9 | 10 | 下午去公司蹭健身房,本以为可以悄悄的来,悄悄的走,结果锻炼完回到工位歇会的功夫,就被同事叫去帮忙看问题了。同事在项目中用到一个基于 Solr 构建的搜索引擎,我这边也用了。 11 | 12 | 同事那边的查询条件比我这边的复杂好多,各种条件与或非的。文档里写了,通过在条件前面写上“+”来表示两个条件是逻辑与。同事照着文档在搜索的 URL 中以各种姿势添加“+”,可是搜索引擎就是不认这个加号,查出的结果是两个条件做逻辑或得到的。 13 | 14 | 15 | 16 | {% recruit %} 17 | 18 | 一开始我给同事的建议是使用搜索引擎的客户端提供的 API 去组装查询条件,不要自己在地址栏里面拼链接,如果 API 出了问题那就可以去找维护搜索引擎的同学修复了。也许我这种有 API 就调 API 的习惯,是我很少掉进坑里的原因? 19 | 20 | 我直接问同事要了他正在调试的链接和文档,开始折腾。几分钟之后我发现,URL 中的加号,在搜索引擎返回的查询参数中,变成了空格。然后我怀疑这个问题和 URL Encoding 有关,一番 Google 之后把加号换成了 %2B,然后就搞定了。 21 | 22 | # 寻寻觅觅 # 23 | 24 | 在 Java Web 开发中,如果需要访问一个网址,尤其是拼装了很多参数的网址,我们一般都会先用 URLEncoder 做一个编码,接收方收到网址中的参数之后,一般都会用 URLDecoder 做一个解码。 25 | 26 | 为了了解这套编码解码背后的映射规则,我去翻看 JDK 的文档,基本上没有收获,除了 "application/x-www-form-urlencoded" 这个东西。不看代码的原因是这个类的代码写的实在不怎么样。 27 | 28 | 顺藤摸瓜,我在维基百科找到了我想要的答案[^1]。 29 | 30 | [^1]: [百分号编码][1] 31 | 32 | # 百分号编码 # 33 | 34 | 百分号编码是用于 URI 的编码机制,也用于为 "application/x-www-form-urlencoded" MIME 准备数据。 35 | 36 | URI 把允许出现的字符分为“保留”和“未保留”。 37 | 38 | 保留字符是这么定义的[^2]: 39 | 40 | [^2]: [RFC 3968][2] 41 | 42 | ``` 43 | reserved = gen-delims / sub-delims 44 | gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" 45 | sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 46 | / "*" / "+" / "," / ";" / "=" 47 | ``` 48 | 49 | 百分号编码一个保留字符,其实是在这个字符的 16 进制 ASCII 值前面加上转义字符 '%'。 50 | 51 | 未保留字符是这么定义的: 52 | 53 | ``` 54 | unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 55 | ``` 56 | 57 | 未保留字符不需要被百分号编码。 58 | 59 | 对于那些不在保留字符和未保留字符范围内的字符,先转换为UTF-8字节序列,然后对其字节值使用百分号编码。 60 | 61 | # 加号与空格 # 62 | 63 | 维基百科百分号编码词条的最后一段解释了 URL Encoding 中加号与空格之间的陈年老坑。 64 | 65 | > 当 HTML 表单中的数据被提交时,表单的域名与值被编码并通过 HTTP 的 GET 或者 POST 方法甚至更古远的 email 把请求发送给服务器。 66 | > 67 | > 这里的编码方法采用了一个非常早期的通用的 URI 百分号编码方法,并且有很多小的修改如新行规范化以及把空格符的编码 "%20" 替换为 "+"。 68 | > 69 | > 按这套方法编码的数据的 MIME 类型是 application/x-www-form-urlencoded,当前仍用于(虽然非常过时了)HTML 与 XForms 规范中。此外,CGI 规范包括了 web 服务器如何解码这类数据、利用这类数据的内容。 70 | 71 | 在正常的编码解码流程中,编码的时候先把加号替换为 %2B,然后把空格替换为加号;解码的时候先把加号替换为空格,再把 %2B 替换为加号,天衣无缝。 72 | 73 | 假如我在一个经过编码的 URI 中直接添加加号,然后直接被拿去解码,加号就会妥妥的被替换成空格了。 74 | 75 | 76 | [1]: http://zh.wikipedia.org/wiki/百分号编码 77 | [2]: http://tools.ietf.org/html/rfc3986#section-2.2 78 | 79 | 80 | -------------------------------------------------------------------------------- /source/_posts/wiki-with-gzip.md: -------------------------------------------------------------------------------- 1 | title: 压缩在手,Wiki 不愁 2 | tags: 3 | - NGINX 4 | categories: 5 | - Study 6 | cc: true 7 | comments: true 8 | date: 2015-07-29 01:56:25 9 | --- 10 | 11 | 12 | 我在之前的一片文章《[个人 Wiki 之殇][1]》中,提到我我正在使用的一个单文件 Wiki 系统,TiddlyWiki。 13 | 14 | 当时出于对未来 Wiki 页面文件体积的担忧,我感觉它的加载时间会逐渐发展到难以接受的程度。不久之前,我的 Wiki 页面文件就已经有 2.3MB 了,最近不知道是因为 TiddlyWiki 升级到 5.1.9 还是我安装了一个用于渲染 LaTeX 数学公式的插件,体积更是瞬间膨胀到了 2.7MB。 15 | 16 | 17 | 18 | {% recruit %} 19 | 20 | 之前我总是觉得用手机访问一次 Wiki 就要消耗 2.3M 的流量,代价有点高昂但还可以接受。如今访问一次就得 2.7M,四舍五入将近 100M 啊,完全接受不能。 21 | 22 | 我习惯用 Opera 来访问和调试我自己的这几个小网站,如今的 Opera 也用了 Chrome 内核,开发者工具十分顺手。我开着开发者工具,在 Opera 中访问部署到 Gitcafe 的 Wiki,惊奇地发现整个页面加载过程只消耗了 664KB 的流量。(当我开始写这篇文字,打算截图的时候,页面的流量消耗就变成 763KB 了,与此相伴的还有 Gitcafe 的 NGINX 版本从 1.6.3 变成了 1.8.0,当时的现场已经找不回来了) 23 | 24 | ![Opera 开发者工具](https://ws2.sinaimg.cn/large/e724cbefgw1euizo5rnp2j20ht07lwfp.jpg) 25 | 26 | 这是什么黑科技!说好的 2.7MB 呢? 27 | 28 | 我于是把本地的 node 服务启动起来,发现访问本地的页面果然是消耗了 2.7MB 的流量的。 29 | 30 | 这是为什么呢?我陷入了沉思。突然,四个英文字母在脑海中浮现: 31 | 32 | **G Z I P** 33 | 34 | 会不会是 Pages 的服务端开启了 gzip 压缩,而我在本地启动的 node 服务没有压缩,所以有这么明显的流量差别?之前我不知道在哪里看关于 gzip 的文章,具体细节记不得了。 35 | 36 | 往 Response Header 一看,gzip 字样赫然在目。 37 | 38 | 为了弄清楚这个压缩是个啥情况,我找了 NGINX 关于压缩模块的文档[^1],学习一个。 39 | 40 | [^1]: [Module ngx_http_gzip_module][2] 41 | 42 | 很明显很划算的资源置换,压缩页面损耗的 CPU 资源比起节省的带宽和流量费,还有提高的网速,简直可以忽略不计了。记得之前支持我们的 DBA 大大看我们应用的数据库 CPU 使用率太低,还特意开启了压缩,用 CPU 资源换内存资源,让更多的数据页可以缓存到内存中。 43 | 44 | 有了压缩之后,我的个人 Wiki 应该很长一段时间之内都不用太关心页面太大加载太久的问题了,虽然现在就已经没法做到秒开,但是至少不会好几秒都开不出来。 45 | 46 | 47 | [1]: http://blog.jamespan.me/2015/06/30/personal-wiki-sucks/ 48 | [2]: http://NGINX.org/en/docs/http/ngx_http_gzip_module.html 49 | -------------------------------------------------------------------------------- /source/_posts/you-are-not-a-real-expert.md: -------------------------------------------------------------------------------- 1 | title: 正因为我不是专家,才会在意这些东西 2 | tags: 3 | - Blogging 4 | - Thinking 5 | categories: 6 | - Life 7 | thumbnail: //i.imgur.com/JiLypI8.jpg 8 | cc: true 9 | comments: true 10 | date: 2016-01-26 01:05:47 11 | --- 12 | 13 | 最近在琨少的推荐下,我稀里糊涂的就变成了「云栖社区专家」,人生中第一次在某个平台变成了大 V。云栖社区是阿里云推出的一个技术博客社区,我在云栖社区的主页是 [潘家邦的云栖小居][1]。 14 | 15 | 上周,云栖社区的运营妹纸从旺旺上找到我,问我是否愿意入驻云栖社区,有人向他们推荐了我云云。 16 | 17 | 18 | 19 | {% recruit %} 20 | 21 | 其实一两个月前我就知道了云栖社区的存在,几周前我就从内部邮件知道了他们正在阿里内部寻找专家入驻社区。也许是我当时大意看走眼,以为作为专家入驻之后每周需要发表两三篇文章,当时就打消了入驻的念头。 22 | 23 | 有一次在微博上和网友讨论 IBM 的 [developerWorks][2],我提到阿里云正在搞一个类似的社区,就是云栖社区,会找阿里的专家在上面写东西。网友说我文章质量不错,应该能上。当时我想到一周两三篇这么可怕的频率,心里就发毛,感觉还是玩自己的博客好了,反正集团那么多专家在呢应该没我啥事。 24 | 25 | 于是当运营妹纸问我是否愿意入驻的时候,一开始我是拒绝的。但是后来我才知道一周两三篇是我误会了,其实只要一个月在云栖首发一篇就好。 26 | 27 | 没有一点点防备,也没有一丝顾虑,我就这样入驻了云栖社区,然后通过审核成了云栖社区专家。 28 | 29 | 入驻云栖社区之后,能够得到一些象征性的奖励。当然这些奖励并不是我入驻的原因,之前也有几个组织找到我,说是愿意给我一定的报酬(千字百元)换取我的博文的首发权之类的,然而我至今都没有和他们产生实质的合作。 30 | 31 | 曾经,我也写了一篇博文给他们发过去,等了一天多之后,却得到回复说我的文章在「实际场景」方面略有不符。 32 | 33 | ![](//i.imgur.com/Dlfs2Mol.png) 34 | 35 | 当时我就有种日了狗的感觉。当初是你要首发,首发就首发,现在又来跟我扯这些没用的。于是我也就懒得为这点钱折腾自己,毁了写作的乐趣。反正写文章卖钱本就不是我写博客的初衷,不忘初心方得始终。 36 | 37 | 于是呢以后每个月我会在云栖社区首发至少一篇技术向的博文,还请感兴趣的朋友捧场。首发两天之后博文会回到我的博客发表,毕竟这里才是我的博客,这里有我亲自优化的的阅读体验和最及时的讨论(读者评论后 Disqus 会给我发提醒邮件,要是不守规矩搞评论轰炸的话我会拉黑哦)。 38 | 39 | 之前通过了这个云栖社区专家审核的时候还挺高兴,如今想想其实也挺可怜的。申请专家认证的过程中,第一步是完善认证条件,认证条件三选一: 40 | 41 | ![](//i.imgur.com/qLsgRh9.png) 42 | 43 | 虽然我很想选择后面两个,但是我终于还是发现自己并没有点下去的底气:我并没有在任何一个领域称得上技术专家,没有,一个领域都没有。 44 | 45 | 多么痛的领悟。 46 | 47 | 这个世界就是如此的讽刺,当你总是在说某件事情,其实你最缺的就是这件事情。当你如此在意一个专家认证的虚名,正说明了你不是专家,差的老远。 48 | 49 | 刚在第一步遭受会心一击之后,第二步又是一个灵魂拷问。 50 | 51 | ![](//i.imgur.com/mQZbpsf.png) 52 | 53 | 当我在一大堆标签中寻找自己擅长的技术领域时,虽然不愿意,但是却不得不承认,其实,这些领域,我都不擅长。甚至我都不知道自己到底擅长什么,看起来似乎什么都会,实际上却什么都不会。Java 也就看过一本「深入理解 Java 虚拟机」,数据库也就看过 「高性能 MySQL」,编程语言上虽然号称「平生之所学囊括五大编程范式」,却只有 Java 经过生产环境的考验。 54 | 55 | 最后还是厚着脸皮选了两个标签,已经是矮子里面拔将军了。写了一年多 Java,却连 SSH 都没摸过;自诩 Python 汪,却未曾向 pypi 提交模块;曾为 Lisp 倾倒,却仅是写写 SICP 课后习题,如今唯一的用途就只剩下修改 Emacs 配置文件。倒是在 Node.js 上无心插柳,为了扩展 Hexo 的功能,已经向 NPM 提交了三个插件,也有微薄的下载量给我些许安慰。 56 | 57 | 「鶸」这个字,也许是如今的我最真实的写照。 58 | 59 | 希望在不久的将来,我能从如今的困局中走出来,找到一个领域,深入钻研,成为真正的专家。 60 | 61 | [1]: https://yq.aliyun.com/u/jamespan 62 | [2]: http://www.ibm.com/developerworks/cn/ 63 | 64 | 65 | -------------------------------------------------------------------------------- /source/about/index.md: -------------------------------------------------------------------------------- 1 | title: About 2 | date: 2014-07-17 11:03:29 3 | comment: true 4 | --- 5 | 6 | 小鶸一枚,除了 Java 和 Python,其他语言都没生产环境经验的代码渣 7 | 8 | 封印全栈技能树,重新点数据库与云数据库服务平台技能树中 9 | 10 | 业余生活逃不出写代码、[读书、看动漫、看电影](/favorite/)这几件事,偶尔写点博客 11 | 12 | 综上所述,一条单身狗 13 | 14 | 15 | + E-mail: [panjiabang@gmail.com](mailto:panjiabang@gmail.com) 16 | + Github: [@JamesPan](https://github.com/JamesPan) 17 | + Weibo : [@潘小鶸](http://weibo.com/panjiabang) 18 | 19 | -------------------------------------------------------------------------------- /source/asset/surge/ss.module: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/source/asset/surge/ss.module -------------------------------------------------------------------------------- /source/categories/index.md: -------------------------------------------------------------------------------- 1 | title: Categories 2 | date: 2014-07-17 11:03:29 3 | layout: categories 4 | comments: false 5 | --- 6 | -------------------------------------------------------------------------------- /source/en/resume/index.md: -------------------------------------------------------------------------------- 1 | title: Pan Jiabang 2 | #date: 2015-08-30 21:03:29 3 | 4 | comment: true 5 | --- 6 | 7 | # OBJECTIVE 8 | 9 | To obtain a **senior software engineer** position based in Mountain View, Beijing or Shanghai. 10 | 11 | # CONTACT 12 | 13 | Email: [panjiabang@gmail.com](mailto:panjiabang@gmail.com) 14 | Blog: [http://blog.jamespan.me](http://blog.jamespan.me) 15 | Github: [https://github.com/JamesPan](https://github.com/JamesPan) 16 | 17 | # WORK EXPERIENCE 18 | 19 | ## Alibaba Group, Cainiao Network (Jul. 2014 - Present) 20 | 21 | ### Senior developer engineer 22 | 23 | *Waybill System Team (Jul. 2015 - Present)* 24 | keyword: high concurrency, reliability, performance 25 | - Participate the refactoring the Dispatch Service System before it was published, to support the persistence and high concurrency visit of a large number of real addresses 26 | - Participate the design of failover strategy of the Waybill System 27 | - Design and implement an application performance monitoring, acquisition and analysis program based on AOP 28 | - Stress testing, tuning, etc 29 | 30 | ### Developer engineer 31 | 32 | *Waybill System Team (Jul. 2014 - Jun. 2015)* 33 | keyword: developing, refactoring 34 | 35 | - Developing Website and API services using Java 36 | - Design and implement a Bean Validation like program that generate validation code on compile time 37 | - Refactoring the core of Waybill System, decoupling it into engine and config 38 | 39 | # WORKS 40 | 41 | - [hexo-ruby-character](https://github.com/JamesPan/hexo-ruby-character) 42 | Add ruby character feature for Hexo,like 博客(blog) 43 | 44 | # EDUCATION 45 | 46 | - Bachelor of Engineering, Computer Science 47 | (Sep. 2010 - Jul. 2014, Tianjin University) 48 | 49 | 50 | # MAIN SKILLS 51 | 52 | - Programming Language: Java, Python, JavaScript/Node.js, C/C++ 53 | - Storage/Cache: MySQL, Memcached 54 | - Big Data: HiveQL/ODPS SQL 55 | 56 | -------------------------------------------------------------------------------- /source/flea/index.md: -------------------------------------------------------------------------------- 1 | title: Exchange 2 | date: 2016-04-10 15:18:29 3 | comment: true 4 | --- 5 | 6 | 这里展示的是我手上已经看完了的而且不打算收藏的实体书。如果你手上有我想看的书,那么正好,我们可以做个交换,或许还可以交个朋友。当然,运费到付。 7 | 8 | 如果你手上闲置的书籍不在我的「心愿单」中,但你觉得我或许会感兴趣,也可以商量。 9 | 10 | 如果我们在三次元中已经是朋友,尽管开口便是,直接赠送。话虽如此,我更希望你能有书籍和我交换,毕竟友谊的基础是平等交流而不是单向索取。 11 | 12 | 请在评论区留言交流。 13 | 14 | {% stream %} 15 | 16 | {% figure https://ws2.sinaimg.cn/bmiddle/e724cbefgw1f58tdhrqmbj208o0bu74l.jpg [Objective-C 程序设计](https://book.douban.com/subject/19967897/) %} 17 | {% figure https://ws2.sinaimg.cn/bmiddle/e724cbefgw1f5h0i5casaj20a30a6wem.jpg [正义女神不睁眼](https://book.douban.com/subject/26689753/) %} 18 | 19 | {% endstream %} 20 | 21 | ## 心愿单 22 | 23 | {% stream %} 24 | 25 | {% figure https://ws2.sinaimg.cn/bmiddle/72f96cbagw1f6qpc9p6h7j20eq0iy407.jpg [设计原本 珍藏版](https://book.douban.com/subject/23820913/) %} 26 | {% endstream %} 27 | 28 | -------------------------------------------------------------------------------- /source/googleb04e35886a5dda4b.html: -------------------------------------------------------------------------------- 1 | layout: false 2 | --- 3 | google-site-verification: googleb04e35886a5dda4b.html -------------------------------------------------------------------------------- /source/nonsense/index.md: -------------------------------------------------------------------------------- 1 | title: Bullshit 2 | meta: false 3 | comments: false 4 | static-disqus: true 5 | --- 6 | 7 | 8 | [Disqus 都支持哪些 HTML 标签呢?][1]可以用 `
` 换行,用 `

` 分段,用 `` 写超链接,用 `

` 引用别人的话,用 `` 加删除线,`` 加下划线,`` 加粗,还可以用 `
` 给代码加上高亮特技!
 9 | 
10 | 点击[这里][2]订阅我的扯淡~
11 | 
12 | 
16 | 
17 | 
30 | 
31 | 
36 | 
37 | [1]: https://help.disqus.com/customer/portal/articles/466253-what-html-tags-are-allowed-within-comments-
38 | [2]: https://jamespan.disqus.com/nonsense/latest.rss
39 | 


--------------------------------------------------------------------------------
/source/resume/index.md:
--------------------------------------------------------------------------------
 1 | title: 潘家邦童鞋的简历
 2 | date: 2016-02-15 11:03:29
 3 | 
 4 | comment: true
 5 | ---
 6 | 
 7 | # 个人信息
 8 | 
 9 | -   潘家邦/男/1993
10 | -   本科/天津大学 计算机科学系
11 | -   工作年限:1 年
12 | 
13 | 
14 | -   Email:[panjiabang@gmail.com](mailto:panjiabang@gmail.com)
15 | -   QQ/微信号:851677201/panjiabang
16 | -   技术博客:http://blog.jamespan.me
17 | -   Github:https://github.com/JamesPan
18 | 
19 | 目前暂无求职意向。如果你有兴趣加入我们,请给我发[邮件](mailto:panjiabang@gmail.com)。
20 | 
21 | 
22 | # 工作经历
23 | 
24 | ## 阿里巴巴-阿里云 (2016 年 2 月 ~ 至今)
25 | 
26 | ### AliCloudDB
27 | 
28 | 更多精彩,未完待续
29 | 
30 | ## 阿里巴巴-菜鸟网络 (2014 年 3 月 ~ 2016 年 1 月)
31 | 
32 | ### 电子面单平台(资深开发工程师,2015 年 7 月 ~ 2016 年 1 月)
33 | 
34 | 2015 年 7 月晋升为资深开发工程师,除了接各种业务需求外,还负责系统灾备、大促稳定性相关事务。
35 | 
36 | 1. 参与菜鸟分单系统上线前重构,修改持久化方案以支持全国详细地址的高并发读,并支持其接入圆通中通等物流商
37 | 2. 参与设计系统灾备方案
38 | 3. 设计并实现单机性能、调用树的全量/抽样采集、持久化、分析方案,并以可复用的形式输出到其他团队(集团尚无广泛采用的解决方案)
39 | 4. 系统容量评估、扩容,压测、优化
40 | 5. 作为电子面单双 11 稳定性负责人参与菜鸟网络的大促稳定性工作
41 | 
42 | ### 电子面单平台(开发工程师,2014 年 7 月 ~ 2015 年 6 月)
43 | 
44 | 资源中心发布之后,我花了一个月多回学校写论文答辩,然后就回公司继续实习直到毕业入职,期间一直在电子面单团队。
45 | 
46 | 双 11 前业务系统开发:
47 | 
48 | 1. 重写商家接入系列页面
49 | 2. 接口原子化重构,开发新业务接口,搭建并运维面单搜索引擎
50 | 3. 在全链路压测中高效构造压测数据,在压测、双 11 大促中和同事一起全程监控系统、业务指标
51 | 
52 | 双 11 后负责系统改造:
53 | 
54 | 1. 将核心逻辑分离为执行引擎和配置,使得新物流商接入无需做代码变更,接入耗时从 5 个工作日下降为 30 分钟
55 | 2. 设计并实现基于注解的参数校验方案(使用方式类似于 Bean Validation),将开发者从乏味的参数校验和对反射的性能担忧中解脱出来
56 | 3. 设计修改淘宝分布式数据层中间件的技术方案以更好地支持系统需求,因时间问题尚未落地
57 | 
58 | ### 物流宝 3.0-资源中心(实习,2014 年 3 月 ~ 2014 年 5 月)
59 | 
60 | 参与菜鸟网络底层系统——物流宝的重构,主要负责页面开发。此前几乎没怎么用过 Java,更没做过 Web 开发,但是依然在一周之内上手。
61 | 
62 | 1. 学习 Java Web 开发
63 | 2. 熟悉阿里系技术栈
64 | 
65 | # 开源项目和作品
66 | ## 开源项目
67 | -   [hexo-ruby-character](https://github.com/JamesPan/hexo-ruby-character)
68 |     为静态博客系统 Hexo 添加「旁注标记」功能的插件,效果如博客(bó kè)
69 | 
70 | -   [pyiconv](https://github.com/JamesPan/pyiconv)
71 |     Unix 实用工具 iconv 的 Python 复刻和增强,增加自动识别编码的功能,在公司内网发表后立刻被同事用于日常工作
72 | 
73 | ## 技术文章
74 | 
75 | -   Guava 是个风火轮之函数式编程系列[(1)](/2015/03/22/guava-functional-programing-1/)
76 | -   Guava 是个风火轮之基础工具系列[(1)](/2015/02/08/guava-basic-utilities-1/)[(2)](/2015/02/09/guava-basic-utilities-2/)[(3)](/2015/03/01/guava-basic-utilities-3/)[(4)](/2015/03/10/guava-basic-utilities-4/)
77 | -   [一种错误的缓存使用方式](/2015/01/24/missuse-of-cache/)
78 | -   [分页查询的那些坑和各种技巧](/2015/01/22/trick-of-paging-query/)
79 | -   [Timestamp - 一个关于时间戳的轻应用](/2015/01/19/timestamp-the-light-app/)
80 | -   [使用 JavaScript 实现 iframe 判断和页面重定向](/2015/01/12/redirect-with-js/)
81 | 
82 | ## 演讲和讲义
83 | 
84 | -   [与世界分享你的技术、思考和吐槽——技术博客写作实践](/slides/share-your-knowledge-by-blogging/)
85 | 
86 | # 技能清单
87 | 
88 | - 高级语言:Java, Python, JavaScript/Node.js, C/C++(只有 Java 开发能力经过生产环境的考验,其余是自我感觉能写)
89 | - 存储:MySQL(阿里系数据库标配), Tair mdb/memcached(阿里系缓存标配)
90 | - 数据分析:HiveQL/ODPS SQL(阿里系大数据处理标配)
91 | 
92 | # 致谢
93 | 
94 | 感谢您花时间阅读我的简历,期待能有机会和您共事。
95 | 


--------------------------------------------------------------------------------
/source/tags/index.md:
--------------------------------------------------------------------------------
1 | title: Tags
2 | date: 2014-07-17 11:03:29
3 | layout: tags
4 | comments: false
5 | ---
6 | 


--------------------------------------------------------------------------------
/themes/icarus/.gitignore:
--------------------------------------------------------------------------------
1 | 
2 | 


--------------------------------------------------------------------------------
/themes/icarus/Gruntfile.js:
--------------------------------------------------------------------------------
 1 | module.exports = function(grunt){
 2 |   grunt.initConfig({
 3 |     gitclone: {
 4 |       fontawesome: {
 5 |         options: {
 6 |           repository: 'https://github.com/FortAwesome/Font-Awesome.git',
 7 |           directory: 'tmp/fontawesome'
 8 |         },
 9 |       },
10 |       fancybox: {
11 |         options: {
12 |           repository: 'https://github.com/fancyapps/fancyBox.git',
13 |           directory: 'tmp/fancybox'
14 |         }
15 |       }
16 |     },
17 |     copy: {
18 |       fontawesome: {
19 |         expand: true,
20 |         cwd: 'tmp/fontawesome/fonts/',
21 |         src: ['**'],
22 |         dest: 'source/css/fonts/'
23 |       },
24 |       fancybox: {
25 |         expand: true,
26 |         cwd: 'tmp/fancybox/source/',
27 |         src: ['**'],
28 |         dest: 'source/fancybox/'
29 |       }
30 |     },
31 |     _clean: {
32 |       tmp: ['tmp'],
33 |       fontawesome: ['source/css/fonts'],
34 |       fancybox: ['source/fancybox']
35 |     }
36 |   });
37 | 
38 |   require('load-grunt-tasks')(grunt);
39 | 
40 |   grunt.renameTask('clean', '_clean');
41 | 
42 |   grunt.registerTask('fontawesome', ['gitclone:fontawesome', 'copy:fontawesome', '_clean:tmp']);
43 |   grunt.registerTask('fancybox', ['gitclone:fancybox', 'copy:fancybox', '_clean:tmp']);
44 |   grunt.registerTask('default', ['gitclone', 'copy', '_clean:tmp']);
45 |   grunt.registerTask('clean', ['_clean']);
46 | };


--------------------------------------------------------------------------------
/themes/icarus/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Tommy Chen
2 | 
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 | 
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 | 
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


--------------------------------------------------------------------------------
/themes/icarus/_config.yml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 | 
 5 | # Content
 6 | excerpt_link: Read more
 7 | fancybox: true
 8 | profile: true
 9 | # Sidebar
10 | sidebar: right
11 | widgets:
12 | # - announce
13 | - recent_posts
14 | - links
15 | 
16 | thumbnail: true
17 | 
18 | # Miscellaneous
19 | twitter:
20 | google_plus:
21 | fb_admins:
22 | fb_app_id:
23 | 
24 | 
25 | # Contacts
26 | contacts:
27 |   github: http://github.com/JamesPan
28 |   weibo: http://weibo.com/panjiabang
29 |   twitter: https://twitter.com/_JamesPan_
30 |   # linkedin: https://cn.linkedin.com/pub/jiabang-pan/50/bb4/86
31 |   telegram: https://telegram.me/jamespan
32 |   # wechat: http://i.imgur.com/icILRWd.jpg
33 |   rss: /atom.xml
34 | 
35 | #wechat: //i.imgur.com/JDKdlapm.jpg
36 | 
37 | cnzz: 1000543904
38 | recruit: false
39 | default_thumbnail: //i.imgur.com/w2aNvOlm.jpg
40 | 


--------------------------------------------------------------------------------
/themes/icarus/_config.yml.example:
--------------------------------------------------------------------------------
 1 | # Header
 2 | menu:
 3 |   Home: /
 4 |   Archives: /archives
 5 |   Categories: /categories
 6 |   Tags: /tags
 7 |   About: /about
 8 | 
 9 | # Content
10 | excerpt_link: Read More
11 | fancybox: true
12 | 
13 | # Profile
14 | profile: true # whether to show profile bar
15 | 
16 | # Sidebar
17 | sidebar: right # set to false if you don't want a sidebar
18 | widgets:
19 | - recent_posts
20 | - category
21 | - tag
22 | - tagcloud
23 | - archive
24 | - links
25 | thumbnail: true
26 | 
27 | # Contacts
28 | contacts:
29 |   github: http://github.com/ppoffice/hexo-theme-icarus
30 |   twitter: '#'
31 |   facebook: '#'
32 |   dribbble: '#'
33 |   rss: /atom.xml
34 | 
35 | # Links
36 | links:
37 |   Hexo: http://hexo.io
38 | 
39 | # Miscellaneous
40 | google_analytics:
41 | favicon: /favicon.png
42 | twitter:
43 | google_plus:
44 | fb_admins:
45 | fb_app_id:
46 | 
47 | # WeChat QrCode URL
48 | #wechat: https://ws4.sinaimg.cn/large/e724cbefgw1erjd7qc6xcj20b40b4myy.jpg
49 | 
50 | # CNZZ id
51 | #cnzz: 
52 | 
53 | # Default Article Thumbnail
54 | default_thumbnail: https://ws1.sinaimg.cn/small/e724cbefgw1et25m6xn6ej20rs0rkjy4.jpg
55 | 


--------------------------------------------------------------------------------
/themes/icarus/_config.yml.site.example:
--------------------------------------------------------------------------------
 1 | # Hexo Configuration
 2 | ## Docs: http://hexo.io/docs/configuration.html
 3 | ## Source: https://github.com/hexojs/hexo/
 4 | 
 5 | # Site
 6 | title: Icarus
 7 | subtitle:
 8 | description: Hexo theme - Icarus
 9 | author: PPOffice
10 | author_title: 'Web Developer & Designer'
11 | avatar: css/images/avatar.png
12 | location: 'Harbin, China'
13 | follow: https://github.com/ppoffice/
14 | language: en
15 | timezone:
16 | 
17 | # URL
18 | ## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
19 | url: http://ppoffice.github.io/hexo-theme-icarus
20 | root: /hexo-theme-icarus/
21 | permalink: :year/:month/:day/:title/
22 | permalink_defaults:
23 | 
24 | # Directory
25 | source_dir: source
26 | public_dir: public
27 | tag_dir: tags
28 | archive_dir: archives
29 | category_dir: categories
30 | code_dir: downloads/code
31 | i18n_dir: :lang
32 | skip_render:
33 | 
34 | # Writing
35 | new_post_name: :title.md # File name of new posts
36 | default_layout: post
37 | titlecase: false # Transform title into titlecase
38 | external_link: true # Open external links in new tab
39 | filename_case: 0
40 | render_drafts: false
41 | post_asset_folder: false
42 | relative_link: false
43 | future: true
44 | highlight:
45 |   enable: true
46 |   line_number: true
47 |   tab_replace:
48 | 
49 | # Category & Tag
50 | default_category: uncategorized
51 | category_map:
52 | tag_map:
53 | 
54 | # Date / Time format
55 | ## Hexo uses Moment.js to parse and display date
56 | ## You can customize the date format as defined in
57 | ## http://momentjs.com/docs/#/displaying/format/
58 | date_format: YYYY-MM-DD
59 | time_format: HH:mm:ss
60 | 
61 | # Pagination
62 | ## Set per_page to 0 to disable pagination
63 | per_page: 6
64 | pagination_dir: page
65 | 
66 | # Extensions
67 | ## Plugins: https://github.com/hexojs/hexo/wiki/Plugins
68 | ## Themes: https://github.com/hexojs/hexo/wiki/Themes
69 | theme: icarus
70 | 
71 | # Disqus
72 | # disqus_shortname: hexo-theme-icarus
73 | 
74 | # DuoShuo
75 | # duoshuo_shortname: hexo-theme-icarus
76 | 
77 | 
78 | # Deployment
79 | ## Docs: http://hexo.io/docs/deployment.html
80 | deploy:
81 |   type: git
82 |   repository: https://github.com/ppoffice/hexo-theme-icarus.git
83 |   branch: gh-pages


--------------------------------------------------------------------------------
/themes/icarus/_source/categories/index.md:
--------------------------------------------------------------------------------
1 | title: "Categories"
2 | layout: "categories"
3 | ---
4 | 


--------------------------------------------------------------------------------
/themes/icarus/_source/tags/index.md:
--------------------------------------------------------------------------------
1 | title: "Tags"
2 | layout: "tags"
3 | ---
4 | 


--------------------------------------------------------------------------------
/themes/icarus/languages/en.yml:
--------------------------------------------------------------------------------
 1 | index:
 2 |   home: 'home'
 3 |   search: 'Search'
 4 |   archive: 'archive'
 5 |   category: 'category'
 6 |   uncategorized: 'uncategorized'
 7 |   tag: 'tag'
 8 | nav:
 9 |   next: 'Next'
10 |   prev: 'Prev'
11 | widget:
12 |   announces: 'announces'
13 |   recents: 'recents'
14 |   archives: 'archives'
15 |   categories: 'categories'
16 |   links: 'links'
17 |   tags: 'tags'
18 |   tag_cloud: 'tag cloud'
19 | article:
20 |   comments: 'Comments'
21 |   share: 'Share'
22 |   hits: 'Hits'
23 | profile:
24 |   follow: 'FOLLOW'
25 |   post: 'post'
26 |   tag: 'tag'
27 |   posts: 'posts'
28 |   tags: 'tags'


--------------------------------------------------------------------------------
/themes/icarus/languages/id.yml:
--------------------------------------------------------------------------------
 1 | index:
 2 |   home: 'home'
 3 |   search: 'Cari'
 4 |   archive: 'arsip'
 5 |   category: 'kategori'
 6 |   uncategorized: 'tanpa kategori'
 7 |   tag: 'tag'
 8 | nav:
 9 |   next: 'Berikutnya'
10 |   prev: 'Sebelumnya'
11 | widget:
12 |   recents: 'terbaru'
13 |   archives: 'arsip'
14 |   categories: 'kategori'
15 |   links: 'tautan'
16 |   tags: 'tag'
17 |   tag_cloud: 'awan tag'
18 | article:
19 |   comments: 'Komentar'
20 |   share: 'Bagikan'
21 | profile:
22 |   follow: 'IKUTI'
23 |   post: 'pos'
24 |   tag: 'tag'
25 |   posts: 'pos'
26 |   tags: 'tag'
27 | 


--------------------------------------------------------------------------------
/themes/icarus/languages/zh-CN.yml:
--------------------------------------------------------------------------------
 1 | index:
 2 |   home: '主页'
 3 |   search: '搜索'
 4 |   archive: '归档'
 5 |   category: '分类'
 6 |   uncategorized: '未分类'
 7 |   tag: '标签'
 8 | nav:
 9 |   next: '下一页'
10 |   prev: '上一页'
11 | widget:
12 |   recents: '最新文章'
13 |   archives: '归档'
14 |   categories: '分类'
15 |   links: '链接'
16 |   tags: '标签'
17 |   tag_cloud: '标签云'
18 | article:
19 |   comments: '评论'
20 |   share: '分享到'
21 |   hits: '次访问'
22 | profile:
23 |   follow: '关注我'
24 |   post: '文章'
25 |   tag: '标签'
26 |   posts: '文章'
27 |   tags: '标签'


--------------------------------------------------------------------------------
/themes/icarus/layout/_partial/after-footer.ejs:
--------------------------------------------------------------------------------
 1 | 
 2 | <%- partial('comment') %>
 3 | 
 4 | 
 5 | <% if (theme.fancybox){ %>
 6 |   <% /*
 7 |   
10 |   */ %>
11 |   
12 |   
13 | 
14 | 
52 | <% } %>
53 | 


--------------------------------------------------------------------------------
/themes/icarus/layout/_partial/archive-post.ejs:
--------------------------------------------------------------------------------
 1 | 
2 |
3 | <% if(theme.thumbnail == true) { %> 4 |
5 | <%- partial('post/thumbnail.ejs', {post: post}) %> 6 |
7 | <% } %> 8 |
9 | <%- partial('post/title', {class_name: 'archive-article-title'}) %> 10 | <% if(archive) { %> 11 | <%- partial('post/date', {class_name: 'archive-article-date', date_format: 'MMM D'}) %> 12 | <% } else { %> 13 | <%- partial('post/date', {class_name: 'archive-article-date', date_format: 'YYYY MMM D'}) %> 14 | <% } %> 15 |
16 |
17 |
-------------------------------------------------------------------------------- /themes/icarus/layout/_partial/archive.ejs: -------------------------------------------------------------------------------- 1 | <% switch (type) { 2 | case 'archive': 3 | var last; 4 | page.posts.each(function(post, i){ 5 | var year = post.date.year(); 6 | if (last != year){ 7 | if (last != null){ %> 8 | 9 | <% } 10 | last = year; %> 11 |
12 | 13 | <%= year %> 14 |
15 |
16 |
17 | <% } %> 18 | <%- partial('archive-post', {post: post, archive: true}) %> 19 | <% }); 20 | if (page.posts.length){ %> 21 |
22 | <% } 23 | if (page.total > 1){ %> 24 | 30 | <% } 31 | break; 32 | case 'category': %> 33 |
34 |
35 | 36 | <%= page.category %> 37 |
38 |
39 | <% page.posts.each(function (post, i) { %> 40 | <%- partial('archive-post', {post: post, archive: false}) %> 41 | <% }); %> 42 |
43 | <% if (page.total > 1){ %> 44 | 50 | <% } 51 | break; 52 | case 'tag': %> 53 |
54 |
55 | 56 | #<%= page.tag %> 57 |
58 |
59 | <% page.posts.each(function (post, i) { %> 60 | <%- partial('archive-post', {post: post, archive: false}) %> 61 | <% }); %> 62 |
63 | <% if (page.total > 1){ %> 64 | 70 | <% } 71 | break; 72 | default: 73 | page.posts.each(function(post){ %> 74 | <%- partial('article', {post: post, index: true}) %> 75 | <% }) 76 | if (page.total > 1){ %> 77 | 83 | <% } 84 | break; 85 | } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/article.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | <% if (post.banner){ %> 4 | <%- partial('post/banner') %> 5 | <% } %> 6 | <%- partial('post/gallery') %> 7 | <% if (post.link || post.title){ %> 8 |
9 | <%- partial('post/title', {class_name: 'article-title'}) %> 10 | <% if ((post.meta == null) || (page.meta != null && post.meta)){ %> 11 | 17 | <% } %> 18 |
19 | <% } %> 20 |
21 | <% if (post.excerpt && index){ %> 22 | <%- post.excerpt %> 23 | <% if (theme.excerpt_link){ %> 24 |

25 | <%= theme.excerpt_link %> 26 |

27 | <% } %> 28 | <% } else { %> 29 | <% if (is_post() && (post.toc == null || page.toc != null && post.toc)){ %> 30 |
31 | <%- toc(post.content) %> 32 |
33 | <% } %> 34 | <%- post.content %> 35 | <% } %> 36 |
37 | <%- partial('post/cc') %> 38 | <%- partial('post/highlight') %> 39 | <%- partial('post/math') %> 40 | 49 |
50 | <% if (!index){ %> 51 | <%- partial('post/nav') %> 52 | <% } %> 53 |
54 | 57 | 58 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/cnzz.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.cnzz){ %> 2 | Analyse with 3 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/comment.ejs: -------------------------------------------------------------------------------- 1 | <% if (config.disqus_shortname){ %> 2 | 17 | <% } else if (config.duoshuo_shortname){ %> 18 | 29 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/footer.ejs: -------------------------------------------------------------------------------- 1 |
2 | <% if (theme.sidebar === 'bottom'){ %> 3 | <%- partial('_partial/sidebar') %> 4 | <% } %> 5 |
6 | 11 |
12 |
-------------------------------------------------------------------------------- /themes/icarus/layout/_partial/github-corner.ejs: -------------------------------------------------------------------------------- 1 | <% if (config.github_repo) { %> 2 | 3 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/google-ads.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/google-analytics.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.google_analytics){ %> 2 | 3 | 13 | 14 | <% } %> 15 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/header.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/author.ejs: -------------------------------------------------------------------------------- 1 | <% if (is_post()){ %> 2 | 8 | <% } %> 9 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/banner.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.link){ %> 2 | 3 | <% } else if (post.title){ %> 4 | <% if (index){ %> 5 | 6 | <% } else { %> 7 | 8 | <% } %> 9 | <% } %> 10 | 11 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/category.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.categories && post.categories.length){ %> 2 | <%- list_categories(post.categories, { 3 | show_count: false, 4 | class: 'article-category', 5 | style: 'none', 6 | separator: '' 7 | }) %> 8 | <% } %> 9 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/cc.ejs: -------------------------------------------------------------------------------- 1 | <% if (page.cc){ %> 2 | 3 | <% } %> 4 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/comment.ejs: -------------------------------------------------------------------------------- 1 | <% if (!index && post.comments && config.disqus_shortname){ %> 2 |
3 |
4 | 5 |
6 |
7 | <% } else if (!index && post.comments && config.duoshuo_shortname){ %> 8 |
9 |
10 | 11 |
12 |
13 | <% } %> 14 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/date.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 |
6 |
7 | 8 | 9 |
10 |
11 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/eof.ejs: -------------------------------------------------------------------------------- 1 | <% if (page.cc){ %> 2 | 5 | 6 | 26 | <% } %> 27 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/gallery.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.photos && post.photos.length){ %> 2 |
3 |
4 | <% post.photos.forEach(function(photo, i){ %> 5 | 6 | 7 | 8 | <% }) %> 9 |
10 |
11 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/highlight.ejs: -------------------------------------------------------------------------------- 1 | <% if (page.hljs){ %> 2 | 3 | <% for (var i in page.hljs) { %> 4 | 5 | <% } %> 6 | 7 | <% /* 8 | 12 | */ %> 13 | 14 | <% } %> 15 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/math.ejs: -------------------------------------------------------------------------------- 1 | <% if (page.math){ %> 2 | 10 | 11 | 18 | 19 | 27 | 28 | 29 | <% } %> 30 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/nav.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.prev || post.next){ %> 2 | 22 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/pv.ejs: -------------------------------------------------------------------------------- 1 | <% if (is_post()){ %> 2 | 6 | <% } %> 7 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/source.ejs: -------------------------------------------------------------------------------- 1 | <% if (is_post()){ %> 2 | 5 | <% } %> 6 | 7 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/tag.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.tags && post.tags.length){ %> 2 | <%- list_tags(post.tags, { 3 | show_count: false, 4 | class: 'article-tag' 5 | }) %> 6 | <% } %> 7 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/thumbnail.ejs: -------------------------------------------------------------------------------- 1 | 2 | <% 3 | var s = ""; 4 | 5 | if (post.thumbnail){ 6 | s = post.thumbnail; 7 | }else if (post.banner){ 8 | s = post.banner; 9 | }else if (theme.default_thumbnail){ 10 | s = theme.default_thumbnail; 11 | }else{ 12 | var img=/\/ig; 13 | var result = post.content.match(img); 14 | result = img.exec(post.content); 15 | if(result != null) { 16 | for(var i = result.length -1; i; --i){ 17 | s += result[i]+"\n"; 18 | } 19 | } 20 | } 21 | if(s.length > 0){ 22 | if(config.post_asset_folder){ 23 | var pattern = /^[\\{0,1}\/{0,1}]([^\/^\\]+)/, 24 | pattern_ = /([^\/^\\]+)/; 25 | if((ret = pattern.exec(s)) != null) { 26 | if(ret[0].length == s.length) 27 | s = config.root + post.path + ret[1]; 28 | } else if ((ret = pattern_.exec(s)) != null) { 29 | if(ret[0].length == s.length) 30 | s = config.root + post.path + ret[1]; 31 | } 32 | } 33 | %> 34 | 35 | <% } else { %> 36 | 37 | <% } %> 38 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/title.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.link){ %> 2 |

3 | 4 |

5 | <% } else if (post.title){ %> 6 | <% if (index){ %> 7 |

8 | <%= post.title %> 9 |

10 | <% } else { %> 11 |

12 | <%= post.title %> 13 |

14 | <% } %> 15 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/post/wechatpp.ejs: -------------------------------------------------------------------------------- 1 | <% if (page.cc){ %> 2 |
3 | <% /* 21 | <% } %> 22 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/profile.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /themes/icarus/layout/_partial/sidebar.ejs: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/announce.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.posts.length){ %> 2 |
3 |

<%= __('widget.announces') %>

4 |
5 |

如果你有闲置的图书,可以尝试和我 交换

6 |

云栖社区有奖征集优秀博文,点 传送门

参与活动 7 |
8 |
9 | <% } %> 10 | -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/archive.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.posts.length){ %> 2 |
3 |

<%= __('widget.archives') %>

4 |
5 | <%- list_archives() %> 6 |
7 |
8 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/category.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.categories.length){ %> 2 |
3 |

<%= __('widget.categories') %>

4 |
5 | <%- list_categories() %> 6 |
7 |
8 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/google-ads.ejs: -------------------------------------------------------------------------------- 1 |
2 |

<%= __('Google Ads') %>

3 |
4 | <%- partial('../_partial/google-ads') %> 5 |
6 |
7 | 8 | -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/links.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.posts.length){ %> 2 |
3 |

<%= __('widget.links') %>

4 |
5 |
    6 | <% for (var i in theme.links){ %> 7 |
  • 8 | <%= i %> 9 |
  • 10 | <% } %> 11 |
12 |
13 |
14 | <% } %> 15 | -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/recent_posts.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.posts.length){ %> 2 |
3 |

<%= __('widget.recents') %>

4 |
5 |
    6 | <% site.posts.sort('date', -1).limit(5).each(function(post){ %> 7 |
  • 8 | <% if(theme.thumbnail == true) { %> 9 |
    10 | <%- partial('../_partial/post/thumbnail.ejs', {post: post}) %> 11 |
    12 | <% } %> 13 |
    14 | 15 |

    <%= post.title %>

    16 |

    <%- list_categories(post.categories, {show_count: false, depth:2, class: 'article-category', style: 'none', separator: ''}) %>

    17 |

    18 |
    19 |
  • 20 | <% }) %> 21 |
22 |
23 |
24 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/tag.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.tags.length){ %> 2 |
3 |

<%= __('widget.tags') %>

4 |
5 | <%- list_tags() %> 6 |
7 |
8 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/_widget/tagcloud.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.tags.length){ %> 2 |
3 |

<%= __('widget.tag_cloud') %>

4 |
5 | <%- tagcloud() %> 6 |
7 |
8 | <% } %> -------------------------------------------------------------------------------- /themes/icarus/layout/archive.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_partial/archive', {type: 'archive', index: true}) %> -------------------------------------------------------------------------------- /themes/icarus/layout/categories.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | <%= page.title %> 5 |
6 |
7 | <% if(site.categories.length) { %> 8 | <%- list_categories(site.categories) %> 9 | <% } %> 10 |
11 |
-------------------------------------------------------------------------------- /themes/icarus/layout/category.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_partial/archive', {type: 'category', index: true}) %> -------------------------------------------------------------------------------- /themes/icarus/layout/index.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_partial/archive', {type: '', index: true}) %> -------------------------------------------------------------------------------- /themes/icarus/layout/layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%- partial('_partial/head') %> 4 | 5 |
6 | <%- partial('_partial/header') %> 7 |
8 | <% if (theme.profile){ %> 9 | <%- partial('_partial/profile', null, {cache: !config.relative_link}) %> 10 | <% } %> 11 |
<%- body %>
12 | <% if (theme.sidebar){ %> 13 | <%- partial('_partial/sidebar', null, {cache: !config.relative_link}) %> 14 | <% } %> 15 |
16 | <%- partial('_partial/footer', null, {cache: !config.relative_link}) %> 17 | <%- partial('_partial/after-footer') %> 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /themes/icarus/layout/page.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_partial/article', {post: page, index: false}) %> -------------------------------------------------------------------------------- /themes/icarus/layout/post.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_partial/article', {post: page, index: false}) %> -------------------------------------------------------------------------------- /themes/icarus/layout/tag.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_partial/archive', {type: 'tag', index: true}) %> -------------------------------------------------------------------------------- /themes/icarus/layout/tags.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | <%= page.title %> 5 |
6 |
7 | <% if(site.tags.length) { %> 8 | <%- tagcloud({min_font: 14, max_font: 28}) %> 9 | <% } %> 10 |
11 |
-------------------------------------------------------------------------------- /themes/icarus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hexo-theme-icarus", 3 | "version": "0.0.1", 4 | "private": true, 5 | "devDependencies": { 6 | "grunt": "~0.4.2", 7 | "load-grunt-tasks": "~0.2.0", 8 | "grunt-git": "~0.2.2", 9 | "grunt-contrib-clean": "~0.5.0", 10 | "grunt-contrib-copy": "~0.4.1" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /themes/icarus/scripts/fancybox.js: -------------------------------------------------------------------------------- 1 | var rUrl = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[.\!\/\\w]*))?)/; 2 | 3 | /** 4 | * Fancybox tag 5 | * 6 | * Syntax: 7 | * {% fancybox /path/to/image [/path/to/thumbnail] [title] %} 8 | */ 9 | 10 | hexo.extend.tag.register('fancybox', function(args){ 11 | var original = args.shift(), 12 | thumbnail = ''; 13 | 14 | if (args.length && rUrl.test(args[0])){ 15 | thumbnail = args.shift(); 16 | } 17 | 18 | var title = args.join(' '); 19 | 20 | return '' + 21 | '' + title + '' 22 | '' + 23 | (title ? '' + title + '' : ''); 24 | }); -------------------------------------------------------------------------------- /themes/icarus/scripts/image-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var config = { 4 | 'jquery': '//cdn.bootcss.com/jquery/2.1.0/jquery.min.js', 5 | 'jquery_lazyload': '//cdn.bootcss.com/jquery.lazyload/1.9.1/jquery.lazyload.min.js', 6 | 'img_placeholder': 'https://ws4.sinaimg.cn/large/e724cbefgw1etyppy7bgwg2001001017.gif' 7 | } 8 | 9 | if (hexo.config.image_stream) { 10 | for (var key in config) { 11 | if (hexo.config.image_stream[key] != null) { 12 | config[key] = hexo.config.image_stream[key]; 13 | } 14 | } 15 | } 16 | 17 | hexo.extend.tag.register('stream', function(args, content){ 18 | var result = ''; 19 | if (config['jquery']) { 20 | result += ''; 21 | } 22 | if (config['jquery_lazyload']) { 23 | result += ''; 24 | } 25 | result += '
'; 26 | result += ''; 29 | result += content; 30 | result += '
'; 31 | result += ''; 32 | return result; 33 | }, {ends: true}); 34 | 35 | hexo.extend.tag.register('figure', function(args){ 36 | var imgUrl = args.shift(); 37 | var title = args.join(' '); 38 | var placeholder = config['img_placeholder']; 39 | 40 | var result = '
'; 41 | result += ''; 42 | result += ''; 43 | result += '
' + hexo.render.renderSync({text: title, engine: 'markdown'}).replace(/

/, '').replace(/<.p>/, '') + '

'; 44 | result += '
'; 45 | return result; 46 | }); 47 | -------------------------------------------------------------------------------- /themes/icarus/scripts/moegirl-template.js: -------------------------------------------------------------------------------- 1 | /** 2 | * heimu tag 3 | * 4 | * Syntax: 5 | * {% heimu content %} 6 | */ 7 | 8 | hexo.extend.tag.register('heimu', function(args) { 9 | var content = args.join(' '); 10 | 11 | var result = ''; 12 | result += content; 13 | result += ''; 14 | return result; 15 | }); 16 | 17 | /** 18 | * douban tag 19 | * 20 | * Syntax: 21 | * {% douban movie 26219198 [title] %} 22 | */ 23 | hexo.extend.tag.register('douban', function(args) { 24 | var category = args.shift(); 25 | var id = args.shift(); 26 | var url = 'http://' + category + '.douban.com/subject/' + id + '/'; 27 | var title = args.join(' '); 28 | if (title === "") { 29 | title = url; 30 | } 31 | 32 | var result = '

' + title + '

'; 33 | return result; 34 | }); 35 | 36 | 37 | -------------------------------------------------------------------------------- /themes/icarus/scripts/recruit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * recruit tag 3 | * 4 | * Syntax: 5 | * {% recruit %} 6 | */ 7 | 8 | hexo.extend.tag.register('recruit', function(args) { 9 | 10 | var content1 = 11 | '
' + 12 | '

Careers

' + 13 | '

目前我所在的技术团队是「阿里云 云数据库 团队」,我们正在寻找优秀的资深工程师以及技术专家。如果你有数据库、云计算等方面的工作经验,或者在 Python、Java 等语言上有一定的造诣,而且愿意在云数据库平台领域做点事情,那么,我很期待你的 来信

' + 14 | '
'; 15 | 16 | var content2 = 17 | '
' + 18 | '

Exchange

' + 19 | '

目前我手上有一批看完之后闲置的实体书,如果你正好也有闲置中的实体书,我们或许可以做个 交换 :)

' + 20 | '
'; 21 | 22 | return content1 + content2; 23 | }); 24 | -------------------------------------------------------------------------------- /themes/icarus/scripts/timeline.js: -------------------------------------------------------------------------------- 1 | hexo.extend.tag.register('mood', function(args, content){ 2 | 3 | date = args[0] 4 | time = args[1] 5 | logo = args[2] 6 | var result = ''; 7 | 8 | result += '
'; 9 | logo = ''; 10 | result += hexo.render.renderSync({text: logo + content, engine: 'markdown'}); 11 | footer = '' + date + ' ' + time + '' 12 | result += '
' + footer + '
'; 13 | result += '
'; 14 | 15 | return result; 16 | }, {ends: true}); 17 | -------------------------------------------------------------------------------- /themes/icarus/source/css/_extend.styl: -------------------------------------------------------------------------------- 1 | $link-dark 2 | &, 3 | &:visited 4 | color: color-default 5 | transition: 0.2s ease 6 | &:hover, 7 | &:visited:hover 8 | color: color-link 9 | 10 | $block-caption 11 | text-decoration: none 12 | text-transform: uppercase 13 | color: color-grey 14 | line-height: 1em 15 | 16 | $block 17 | background: #fff 18 | box-shadow: 0 1px 2px rgba(0,0,0,0.05) 19 | 20 | $base-style 21 | h1 22 | font-size: 2em 23 | h2 24 | font-size: 1.5em 25 | h3 26 | font-size: 1.3em 27 | h4 28 | font-size: 1.2em 29 | h5 30 | font-size: 1em 31 | h6 32 | font-size: 1em 33 | color: color-grey 34 | hr 35 | border: 1px dashed color-border 36 | strong 37 | font-weight: bold 38 | em, cite 39 | font-style: italic 40 | sup, sub 41 | font-size: 0.75em 42 | line-height: 0 43 | position: relative 44 | vertical-align: baseline 45 | sup 46 | top: -0.5em 47 | sub 48 | bottom: -0.2em 49 | small 50 | font-size: 0.85em 51 | acronym, abbr 52 | border-bottom: 1px dotted 53 | ul, ol, dl 54 | margin: 0 20px 55 | line-height: line-height 56 | ul, ol 57 | ul, ol 58 | margin-top: 0 59 | margin-bottom: 0 60 | ul 61 | list-style: disc 62 | ol 63 | list-style: decimal 64 | dt 65 | font-weight: bold -------------------------------------------------------------------------------- /themes/icarus/source/css/_partial/comment.styl: -------------------------------------------------------------------------------- 1 | #comments 2 | @extend $block 3 | padding: article-padding 4 | margin: block-margin 0 5 | a 6 | color: color-link -------------------------------------------------------------------------------- /themes/icarus/source/css/_partial/footer.styl: -------------------------------------------------------------------------------- 1 | #footer 2 | padding: 20px 0 3 | border-top: 1px solid color-border 4 | color: color-default 5 | font-size: font-size + 2 6 | text-align: center 7 | .outer 8 | margin-bottom: 0 9 | a 10 | color: color-link 11 | text-decoration: none 12 | &:hover 13 | text-decoration: underline 14 | 15 | #footer-info 16 | line-height: line-height 17 | font-size: 0.85em -------------------------------------------------------------------------------- /themes/icarus/source/css/_partial/mobile.styl: -------------------------------------------------------------------------------- 1 | @media mq-mobile 2 | #mobile-nav 3 | position: absolute 4 | top: 0 5 | left: 0 6 | width: mobile-nav-width 7 | height: 100% 8 | background: color-mobile-nav-background 9 | border-right: 1px solid #fff 10 | 11 | @media mq-mobile 12 | .mobile-nav-link 13 | display: block 14 | color: color-grey 15 | text-decoration: none 16 | padding: 15px 20px 17 | font-weight: bold 18 | &:hover 19 | color: #fff 20 | -------------------------------------------------------------------------------- /themes/icarus/source/css/_util/grid.styl: -------------------------------------------------------------------------------- 1 | ///////////////// 2 | // Semantic.gs // for Stylus: http://learnboost.github.com/stylus/ 3 | ///////////////// 4 | 5 | // Utility function — you should never need to modify this 6 | // _gridsystem-width = (column-width + gutter-width) * columns 7 | gridsystem-width(_columns = columns) 8 | (column-width + gutter-width) * _columns 9 | 10 | // Set @total-width to 100% for a fluid layout 11 | // total-width = gridsystem-width(columns) 12 | total-width = 100% 13 | 14 | ////////// 15 | // GRID // 16 | ////////// 17 | 18 | body 19 | clearfix() 20 | width: 100% 21 | 22 | row(_columns = columns) 23 | clearfix() 24 | display: block 25 | width: total-width * ((gutter-width + gridsystem-width(_columns)) / gridsystem-width(_columns)) 26 | margin: 0 total-width * (((gutter-width * .5) / gridsystem-width(_columns)) * -1) 27 | 28 | column(x, _columns = columns) 29 | display: inline 30 | float: left 31 | width: total-width * ((((gutter-width + column-width) * x) - gutter-width) / gridsystem-width(_columns)) 32 | margin: 0 total-width * ((gutter-width * .5) / gridsystem-width(_columns)) 33 | 34 | push(offset = 1) 35 | margin-left: total-width * (((gutter-width + column-width) * offset) / gridsystem-width(columns)) 36 | 37 | pull(offset = 1) 38 | margin-right: total-width * (((gutter-width + column-width) * offset) / gridsystem-width(columns)) -------------------------------------------------------------------------------- /themes/icarus/source/css/_util/mixin.styl: -------------------------------------------------------------------------------- 1 | // http://www.zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement/ 2 | hide-text() 3 | text-indent: 100% 4 | white-space: nowrap 5 | overflow: hidden 6 | 7 | // http://codepen.io/shshaw/full/gEiDt 8 | absolute-center(width, height = width) 9 | // margin: auto 10 | // position: absolute 11 | // top: 50% 12 | // top: 0 13 | // left: 0 14 | // bottom: 0 15 | // right: 0 16 | // width: width 17 | // height: height 18 | // overflow: auto 19 | width: width 20 | height: height 21 | position: absolute 22 | top: 50% 23 | left: 50% 24 | margin-top: width * -0.5 25 | margin-left: height * -0.5 26 | 27 | avoid-column-break() 28 | vendor("column-break-inside", avoid, only: webkit) 29 | page-break-inside: avoid // for firefox 30 | overflow: hidden // fix for firefox 31 | break-inside: avoid-column 32 | -------------------------------------------------------------------------------- /themes/icarus/source/css/_variables.styl: -------------------------------------------------------------------------------- 1 | // Config 2 | support-for-ie = false 3 | vendor-prefixes = webkit moz ms official 4 | 5 | // Colors 6 | color-default = #565a5f 7 | color-grey = #999 8 | color-border = #eceff2 9 | color-link = #38b7ea 10 | color-background = #f5f8f9 11 | color-sidebar-text = #777 12 | color-sidebar-text-dark = #333 13 | color-widget-background = #ddd 14 | color-widget-border = #ccc 15 | color-mobile-nav-background = #191919 16 | color-twitter = #00aced 17 | color-facebook = #3b5998 18 | color-pinterest = #cb2027 19 | color-google = #dd4b39 20 | 21 | // Fonts 22 | //font-sans = normal, "Avenir Next", Avenir, "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", Arial, sans-serif 23 | //font-sans = 'Hiragino Sans GB', Helvetica, Arial, 'Microsoft Yahei', sans-serif 24 | //font-sans = Arial, sans-serif 25 | font-sans = "Classic Grotesque W01", "Avenir Next", "Segoe UI", "Helvetica Neue", Arial, "Hiragino Sans GB", "PingFang SC", "Heiti SC", "Microsoft YaHei UI", "Microsoft YaHei", "Source Han Sans", sans-serif; 26 | font-serif = "Georgia", serif 27 | font-mono = 'Source Code Pro', Courier, monospace 28 | font-size = 100% 29 | line-height = 1.5em 30 | line-height-title = 1.1em 31 | 32 | // Header 33 | logo-size = 40px 34 | header-height = 64px 35 | header-sub-height = 48px 36 | logo-url = "images/logo.png" 37 | 38 | // Sidebar 39 | sidebar = hexo-config("sidebar") 40 | thumbnail-default-small = 'images/thumb-default-small.png' 41 | 42 | // Profile bar 43 | profile = hexo-config("profile") 44 | profile-avatar-size = 128px 45 | 46 | // Layout 47 | block-margin = 40px 48 | article-padding = 20px 49 | mobile-nav-width = 280px 50 | main-column = 7 51 | sidebar-column = 3 52 | profile-column = 3 53 | sidebar-column-tablet = 4 54 | 55 | if sidebar 56 | _sidebar-column = sidebar-column 57 | else 58 | _sidebar-column = 0 59 | 60 | if profile 61 | _profile-column = profile-column 62 | else 63 | _profile-column = 0 64 | 65 | // Grids 66 | column-width = 80px 67 | gutter-width = 20px 68 | if _sidebar-column is 0 and _profile-column is 0 69 | columns = 10 70 | main-column = 10 71 | else 72 | columns = main-column + _sidebar-column + _profile-column 73 | 74 | if sidebar 75 | main-column-tablet = 6 76 | if profile 77 | main-column-tablet = 9 78 | 79 | // Media queries 80 | mq-mini = "screen and (max-width: 559px)" 81 | mq-mobile = "screen and (min-width: 560px) and (max-width: 799px)" 82 | mq-tablet = "screen and (min-width: 800px) and (max-width: 1199px)" 83 | mq-normal = "screen and (min-width: 1200px)" -------------------------------------------------------------------------------- /themes/icarus/source/css/custom.styl: -------------------------------------------------------------------------------- 1 | .heimu 2 | background-color #252525 !important 3 | color #252525 !important 4 | .toc-article 5 | background color-code 6 | margin 2em 0 0 0.5em 7 | padding 1em 8 | strong 9 | padding 0.3em 0 10 | #toc 11 | line-height 1em 12 | font-size 0.8em 13 | float right 14 | .toc 15 | padding 0 16 | li 17 | list-style-type none 18 | .toc-child 19 | padding-left 1.5em 20 | 21 | @media only print 22 | .print-invisible * 23 | display: none !important 24 | 25 | @media mq-mobile 26 | .mobile-hide 27 | display: none !important 28 | 29 | @media mq-mini 30 | .mobile-hide 31 | display: none !important 32 | 33 | .article-author 34 | float: right 35 | line-height: 1em 36 | color: #9a9ea3 37 | margin-right: 10px 38 | 39 | .article-simple 40 | padding-left: 20px; 41 | //padding-bottom: 5px; 42 | background: #fff; 43 | font-size: 15px; 44 | 45 | .article-entry 46 | h1, h2, h3, h4, h5, h6 47 | font-weight: normal 48 | 49 | #footer 50 | border-top: 0px 51 | 52 | .article-inner 53 | box-shadow: 0 0 0 0 54 | 55 | .article-tag-list 56 | color: color-grey 57 | display: inline 58 | &:before 59 | content: "\f02c" 60 | font-family: FontAwesome 61 | padding-right: 8px 62 | padding-left: 10px 63 | 64 | .article-tag-list-item 65 | display: inline 66 | float: inherit 67 | 68 | .article-category-link 69 | color: color-grey 70 | display: inline 71 | &:before 72 | content: "\f07b" 73 | font-family: FontAwesome 74 | padding-right: 8px 75 | 76 | 77 | body 78 | -webkit-font-smoothing: antialiased 79 | -------------------------------------------------------------------------------- /themes/icarus/source/css/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/css/images/avatar.png -------------------------------------------------------------------------------- /themes/icarus/source/css/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/css/images/logo.png -------------------------------------------------------------------------------- /themes/icarus/source/css/images/thumb-default-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/css/images/thumb-default-small.png -------------------------------------------------------------------------------- /themes/icarus/source/css/style.styl: -------------------------------------------------------------------------------- 1 | @import "nib" 2 | @import "_variables" 3 | @import "_util/mixin" 4 | @import "_util/grid" 5 | 6 | global-reset() 7 | 8 | input, button 9 | margin: 0 10 | padding: 0 11 | &::-moz-focus-inner 12 | border: 0 13 | padding: 0 14 | 15 | html, body, #container 16 | height: 100% 17 | 18 | body 19 | color: color-default 20 | background: color-background 21 | font: font-size font-sans 22 | -webkit-text-size-adjust: 100% 23 | 24 | a 25 | color: color-link 26 | text-decoration: none 27 | &:visited 28 | color: color-link 29 | 30 | .outer 31 | clearfix() 32 | max-width: (column-width + gutter-width) * columns + gutter-width 33 | margin: 0 auto 34 | padding: 0 gutter-width 35 | @media mq-mini 36 | padding: 0 37 | 38 | .left, .alignleft 39 | float: left 40 | 41 | .right, .alignright 42 | float: right 43 | 44 | .clear 45 | clear: both 46 | 47 | .logo 48 | background-image: url(logo-url) 49 | background-size: cover 50 | 51 | #container 52 | position: relative 53 | & > .outer 54 | margin-bottom: 30px 55 | 56 | #main 57 | @media mq-normal 58 | column(main-column) 59 | @media mq-tablet 60 | if sidebar 61 | column(main-column-tablet) 62 | else 63 | width: 100% 64 | 65 | @import "_extend" 66 | @import "_partial/header" 67 | @import "_partial/profile" 68 | @import "_partial/article" 69 | @import "_partial/comment" 70 | @import "_partial/archive" 71 | @import "_partial/footer" 72 | //@import "_partial/highlight" 73 | @import "_partial/mobile" 74 | @import "_partial/sidebar" 75 | 76 | if sidebar is left 77 | #main 78 | float: right 79 | #profile 80 | float: right 81 | 82 | @import "custom" 83 | -------------------------------------------------------------------------------- /themes/icarus/source/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/favicon-16x16.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/favicon-32x32.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/favicon-96x96.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/favicon.ico -------------------------------------------------------------------------------- /themes/icarus/source/icons/largetile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/largetile.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/mediumtile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/mediumtile.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/smalltile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/smalltile.png -------------------------------------------------------------------------------- /themes/icarus/source/icons/widetile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamespan/blog-src/fc7ff40de551c1cb2a8febb6acc442f188d41e16/themes/icarus/source/icons/widetile.png -------------------------------------------------------------------------------- /themes/icarus/source/js/script.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | // Caption 3 | $('.article-entry').each(function(i){ 4 | $(this).find('img').each(function(){ 5 | if ($(this).parent().hasClass('fancybox')) return; 6 | if ($(this).hasClass('nofancy')) return; 7 | var alt = this.alt; 8 | if (alt) $(this).after('' + alt + ''); 9 | $(this).wrap(''); 10 | }); 11 | }); 12 | 13 | if ($.fancybox) { 14 | $('.fancybox').fancybox({ 15 | helpers: { 16 | overlay: { 17 | locked: false 18 | } 19 | } 20 | }); 21 | } 22 | // Profile card 23 | $(document).on('click', function () { 24 | $('#profile').removeClass('card'); 25 | }).on('click', '#profile-anchor', function (e) { 26 | e.stopPropagation(); 27 | $('#profile').toggleClass('card'); 28 | }).on('click', '.profile-inner', function (e) { 29 | e.stopPropagation(); 30 | }); 31 | 32 | // Toc optimize 33 | if ($('#toc').children().length == 0) { 34 | $('#toc').remove(); 35 | } 36 | })(jQuery); 37 | -------------------------------------------------------------------------------- /themes/mewpassant/_config.yml: -------------------------------------------------------------------------------- 1 | node_sass: 2 | outputStyle: nested 3 | precision: 5 4 | sourceComments: false -------------------------------------------------------------------------------- /themes/mewpassant/layout/_partial/after_footer.swig: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/_partial/article.swig: -------------------------------------------------------------------------------- 1 | {% if page.no_header %} 2 | {% else %} 3 |
4 | {% if index %} 5 |

{% if site.titlecase %}{{ post.title | title }}{% else %}{{ post.title }}{% endif %}

6 | {% else %} 7 |

{% if site.titlecase %}{{ page.title | title }}{% else %}{{ page.title }}{% endif %}

8 | {% endif %} 9 | {% if page.meta == false %} 10 | {% else %} 11 | 17 | {% endif %} 18 |
19 | {% endif %} 20 | {% if index %} 21 | {% set excerpted = 'false' %} 22 | {% if post.excerpt %} 23 | {% set excerpted = 'true' %} 24 |
{{ post.excerpt }}
25 | {% else %} 26 |
{{ post.excerpt }}
27 | {% endif %} 28 | {% if excerpted == 'true' %} 29 | 32 | {% endif %} 33 | {% else %} 34 |
{{ content }}
35 | {% endif %} 36 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/_partial/custom/footer.swig: -------------------------------------------------------------------------------- 1 | Copyright © {{ site.time }} - {{ site.author }} - 2 | Powered by Octopress on GitHubPages 3 | 4 | - Theme by Cho 5 | 6 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/_partial/custom/navigation.swig: -------------------------------------------------------------------------------- 1 | Blog 2 | Archives -------------------------------------------------------------------------------- /themes/mewpassant/layout/_partial/footer.swig: -------------------------------------------------------------------------------- 1 |
2 | {% include 'custom/footer.swig' %} 3 |
4 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/_partial/head.swig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% if page.title %}{{ page.title }} - {% endif %}{{ site.title }} 9 | 10 | 13 | {% if page.description %}{{ page.description }}{% else %}{{ content }}{% endif %} 14 | 15 | {% if page.keywords %}{% endif %} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/_partial/header.swig: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 7 | {% if site.subtitle %}

{{ site.subtitle }}

{% endif %} 8 |
9 |
10 | 13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/default.swig: -------------------------------------------------------------------------------- 1 | {% include '_partial/head.swig' %} 2 | 3 | 4 |
5 |
6 |
7 | {% block content %}{% endblock %} 8 |
9 |
10 |
11 |
12 | {% include '_partial/footer.swig' %} 13 |
14 | {% include '_partial/after_footer.swig' %} 15 | 16 | 17 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/index.swig: -------------------------------------------------------------------------------- 1 | {% extends 'default.swig' %} 2 | 3 | {% block content %} 4 |
5 |
6 | {% set index = true %} 7 | {% for post in page.posts %} 8 | {% set content = post.content %} 9 |
10 | {% include '_partial/article.swig' %} 11 |
12 | {% endfor %} 13 | 23 |
24 |
25 | {% endblock %} 26 | 27 | {% block sidebar %} 28 | 31 | {% endblock %} 32 | 33 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/page.swig: -------------------------------------------------------------------------------- 1 | {% extends 'default.swig' %} 2 | 3 |
4 |
5 |
6 | {% if page.title %} 7 |
8 |

{% if site.titlecase %}{{ page.title | titlecase }}{% else %}{{ page.title }}{% endif %}

9 | {% if page.date %}

{% include post/date.html %}{{ time }}

{% endif %} 10 |
11 | {% endif %} 12 | {{ content }} 13 | {% unless page.footer == false %} 14 |
15 | {% if page.date or page.author %}

16 | {% if page.author %}{% include post/author.html %}{% endif %} 17 | {% include post/date.html %}{% if updated %}{{ updated }}{% else %}{{ time }}{% endif %} 18 | {% if page.categories %}{% include post/categories.html %}{% endif %} 19 |

{% endif %} 20 | {% unless page.sharing == false %} 21 | {% include post/sharing.html %} 22 | {% endunless %} 23 |
24 | {% endunless %} 25 |
26 | {% if site.disqus_short_name and page.comments == true %} 27 |
28 |

Comments

29 |
{% include post/disqus_thread.html %}
30 |
31 | {% endif %} 32 |
33 |
34 | {% unless page.sidebar == false %} 35 | 42 | {% endunless %} 43 | -------------------------------------------------------------------------------- /themes/mewpassant/layout/post.swig: -------------------------------------------------------------------------------- 1 | {% extends 'default.swig' %} 2 | 3 |
4 |
5 |
6 | {% include '_partials/article.swig' %} 7 |
8 |
9 | {% include post/author.html %} and 10 | File under {% include post/categories.html %} 11 |
12 | {% unless page.sharing == false %} 13 | {% include post/sharing.html %} 14 | {% endunless %} 15 |
16 | {% if page.previous.url %} 17 | « {{page.previous.title}} 18 | {% endif %} 19 | {% if page.next.url %} 20 | {{page.next.title}} » 21 | {% endif %} 22 |
23 |
24 |
25 | {% if site.disqus_short_name and page.comments == true %} 26 |
27 |

Comments

28 |
{% include post/disqus_thread.html %}
29 |
30 | {% endif %} 31 |
32 |
33 | {% unless page.sidebar == false %} 34 | 41 | {% endunless %} 42 | -------------------------------------------------------------------------------- /themes/mewpassant/scripts/fancybox.js: -------------------------------------------------------------------------------- 1 | var rUrl = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[.\!\/\\w]*))?)/; 2 | 3 | /** 4 | * Fancybox tag 5 | * 6 | * Syntax: 7 | * {% fancybox /path/to/image [/path/to/thumbnail] [title] %} 8 | */ 9 | 10 | hexo.extend.tag.register('fancybox', function(args){ 11 | var original = args.shift(), 12 | thumbnail = ''; 13 | 14 | if (args.length && rUrl.test(args[0])){ 15 | thumbnail = args.shift(); 16 | } 17 | 18 | var title = args.join(' '); 19 | 20 | return '' + 21 | '' + title + '' 22 | '' + 23 | (title ? '' + title + '' : ''); 24 | }); -------------------------------------------------------------------------------- /themes/mewpassant/scripts/image-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var config = { 4 | 'jquery': '//cdn.bootcss.com/jquery/2.1.0/jquery.min.js', 5 | 'jquery_lazyload': '//cdn.bootcss.com/jquery.lazyload/1.9.1/jquery.lazyload.min.js', 6 | 'img_placeholder': 'https://ws4.sinaimg.cn/large/e724cbefgw1etyppy7bgwg2001001017.gif' 7 | } 8 | 9 | if (hexo.config.image_stream) { 10 | for (var key in config) { 11 | if (hexo.config.image_stream[key] != null) { 12 | config[key] = hexo.config.image_stream[key]; 13 | } 14 | } 15 | } 16 | 17 | hexo.extend.tag.register('stream', function(args, content){ 18 | var result = ''; 19 | if (config['jquery']) { 20 | result += ''; 21 | } 22 | if (config['jquery_lazyload']) { 23 | result += ''; 24 | } 25 | result += '
'; 26 | result += ''; 29 | result += content; 30 | result += '
'; 31 | result += ''; 32 | return result; 33 | }, {ends: true}); 34 | 35 | hexo.extend.tag.register('figure', function(args){ 36 | var imgUrl = args.shift(); 37 | var title = args.join(' '); 38 | var placeholder = config['img_placeholder']; 39 | 40 | var result = '
'; 41 | result += ''; 42 | result += ''; 43 | result += '
' + hexo.render.renderSync({text: title, engine: 'markdown'}).replace(/

/, '').replace(/<.p>/, '') + '

'; 44 | result += '
'; 45 | return result; 46 | }); 47 | -------------------------------------------------------------------------------- /themes/mewpassant/scripts/moegirl-template.js: -------------------------------------------------------------------------------- 1 | /** 2 | * heimu tag 3 | * 4 | * Syntax: 5 | * {% heimu content %} 6 | */ 7 | 8 | hexo.extend.tag.register('heimu', function(args) { 9 | var content = args.join(' '); 10 | 11 | var result = ''; 12 | result += content; 13 | result += ''; 14 | return result; 15 | }); 16 | 17 | /** 18 | * douban tag 19 | * 20 | * Syntax: 21 | * {% douban movie 26219198 [title] %} 22 | */ 23 | hexo.extend.tag.register('douban', function(args) { 24 | var category = args.shift(); 25 | var id = args.shift(); 26 | var url = 'http://' + category + '.douban.com/subject/' + id + '/'; 27 | var title = args.join(' '); 28 | if (title === "") { 29 | title = url; 30 | } 31 | 32 | var result = '

' + title + '

'; 33 | return result; 34 | }); 35 | 36 | 37 | -------------------------------------------------------------------------------- /themes/mewpassant/scripts/timeline.js: -------------------------------------------------------------------------------- 1 | hexo.extend.tag.register('mood', function(args, content){ 2 | 3 | date = args[0] 4 | time = args[1] 5 | logo = args[2] 6 | var result = ''; 7 | 8 | result += '
'; 9 | logo = ''; 10 | result += hexo.render.renderSync({text: logo + content, engine: 'markdown'}); 11 | footer = '' + date + ' ' + time + '' 12 | result += ''; 13 | result += '
'; 14 | 15 | return result; 16 | }, {ends: true}); 17 | --------------------------------------------------------------------------------