RunWithMusic

晚上败了个索尼大法,回想起来跑步这么些年,听坏的播放装备简直是……提起来就让人"心痛到无法呼吸”。好了,下面 来盘点一下被我玩坏过的装备。

跑步中会大量出汗,因而选择运动装备,无论是耳机还是播放设备,第一是防水、第二还是防水、第三还是防水—-重要的事情说 三遍! 如果你还没悟到防水的重要,那可能是因为:
1、 你处于高纬度地带,跑步压根不出汗;
2、 你跑步的速度可能有点。。。。。。慢;
3、 你没有汗腺,可以像狗狗一样伸个舌头就散热。。。(开个玩笑)

意外的是,在诸多运动耳机中,我第一时间想到的是Philips的耳机. 便宜、耐操, 防水性超好:

Philips 灵活挂钩式耳机 SHS3200BK/37 :

/images/2016_11_07_21_24_56_540x479.jpg

特点: 非入耳式,跑步时很安全(可以听到汽笛声铃铛声等)。这个耳机是我用过的最耐操的,先后买过两个, 白色和黑色。这个耳机的脆弱点在于,它的与耳朵接触的部位含有少量金属,因而会慢慢被腐蚀,最后 导致声音越来越少。本人右耳出汗稍微多点,每次都是坏右耳。

重音很好。

价格:入手时50左右,现在可能涨了点。

使用寿命:一年+。

飞利浦(PHILIPS) SHQ3200/98 ActionFit:

/images/2016_11_07_21_34_59_697x705.jpg

特点:
入耳式,听各种协奏曲会很爽。耐操程度不如上一个。这个耳机我也买过两个。脆弱点在于:发音部分 含有金属,所以,会被汗液慢慢腐蚀。

缺点: 带上以后,跑公路很危险,因为是入耳式。

使用寿命:9个月左右。

DECATHLON

/images/2016_11_07_21_40_15_257x377.jpg

么有评价,只是告诉你们不要买就是了。买来听两个月就挂的货,毕竟是找到国内企业低成本代工。。。。

Moto SF200

/images/2016_11_07_21_46_44_259x265.jpg
在200左右的价位入手,结果大失所望,听了5个月就坏掉了,一个耳朵没声音。

蓝牙耳机不评论。盖因本人一直用有线听音乐。当然蓝牙适配器也是有的,因为汗水的缘故,已经挂掉了 N个。。。。

跑步时候的播放设备,曾经用过PHILIPS、SANDISK、爱国者的MP3,还有几台NOKIA手机。然而我可以很负责任 的告诉各位—-这些设备现在通通不能用了,因为被汗水诟坏了。

所以,到最后我只能剁手这个:

/images/2016_11_07_21_55_10_770x607.jpg

索尼大法好,希望索尼大法能被我操两年+。

TurnQcow2IntoVagrantBox

img preparation

First you got a qcow2 file, which could let you startup a virtualmachine, so you startup a machine like following:

# cp YourQcowFile.qcow2 ./box.img
# qemu-system-x86_64 -net nic -net user,hostfwd=tcp::2222-:22 -hda ./box.img -m 512
--enable-kvm

Login to the machine and run following scripts:

useradd -m vagrant
mkdir /home/vagrant/.ssh
chmod 700 /home/vagrant/.ssh
echo "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key" > /home/vagrant/.ssh/authorized_keys
chmod 600 /home/vagrant/.ssh/authorized_keys
chown -R vagrant.vagrant /home/vagrant/.ssh

# Sudoers
sed -i -r 's/(.* requiretty)/#\1/' /etc/sudoers

cat > /etc/sudoers.d/90-vagrant-users <<EOF
# User rules for vagrant
vagrant ALL=(ALL) NOPASSWD:ALL
EOF

Now close the machine.

Metadata file

Create a new metadata file like following:

# vim metadata.json
{
  "provider"     : "libvirt",
  "format"       : "qcow2",
  "virtual_size" : 4
}

Create a Vagrantfile like following:

$ vim Vagrantfile
# The contents below were provided by the Packer Vagrant post-processor

Vagrant.configure("2") do |config|
  config.vm.provider :libvirt do |libvirt|
    libvirt.driver = "kvm"
  end
end


# The contents below (if any) are custom contents provided by the
# Packer template during image build.

Now tar the box file via following:

# tar czvf Trusty.box ./metadata.json ./Vagrantfile ./box.img 

Using box

Add box file via:

# vagrant box add Trusty.box --name "trusty64"

ClimbingMaoFengMountain

近期广州雾霾实在是有点醇厚,所以周末的第一选择当然是进山避霾啦!

今天定它个小目标,快速穿越帽峰山脉。

帽峰山是广州周边我非常喜欢的一座山,距市区有点距离(40公里?),配套设施好、 人流量适中、植被茂密、空气清新。这一年多来去了好几次,每次都有新发现。今天 走的是一条穿越的线路,20公里,白山村->山顶->古庙出口。

早上游泳的缘故,出发得晚,11点多才开始走白山村道,果然没有雾霾,蓝天白云:

/images/2016_11_06_20_39_56_1122x837.jpg

水厂后面的山峰郁郁葱葱,深山有好水:

/images/2016_11_06_20_42_05_1124x841.jpg

沿途有村民营业的大量取水点,自备矿泉水桶过来装,2元/桶。拉回城应该随便就能卖到20 块一桶吧? 发家致富的路子,窝也只能指点到这了:

/images/2016_11_06_20_43_50_801x596.jpg

锄禾日当午, 要珍惜盘中餐啊,看下图,向我学习:

/images/2016_11_06_20_46_38_1122x837.jpg

惭愧,走了一个小时就饿了,果断吃饭,考虑一会要在山里跑,吃素淡点就不点鱼了。喜欢 吃鱼的朋友到了帽峰山可以点鱼吃,铜锣湾水库水质不错,出品的鱼很美味:

/images/2016_11_06_20_57_40_660x355.jpg

这位一直围着桌子喵喵叫的小兄弟, 窝那么富有爱心当然不会忘了你:

/images/2016_11_06_21_20_34_434x659.jpg

山间风景:

/images/2016_11_06_21_23_48_427x408.jpg

15分钟到顶,开始沿着山脊往帽峰山顶广场穿行:

/images/2016_11_06_21_26_07_973x721.jpg

速度有点快,1小时不到抵达帽峰山顶广场:

/images/2016_11_06_21_27_16_974x716.jpg

山顶俯瞰林海, 空气没得说,怎样都是负氧离子饱和:

/images/2016_11_06_21_27_57_975x726.jpg

北国早已寒冷如咧,可这帽峰山里风景, 依然青翠如夏:

/images/2016_11_06_21_31_29_522x516.jpg

下午3点40,自古庙出口下到山底,结束愉快的帽峰山一日之旅。
如此算来,从白山村到杨伙寮,经箫神顶到帽峰山顶景区后经古庙下山,可以在三个小时内完成。

压轴奉上帽峰山脉一景. Life is short, play more.

/images/2016_11_06_21_35_42_1125x836.jpg

为Blog添加保存为图片功能

背景

众所周知疼讯其实一直是一个很封闭傻逼的企业,早年QZONE的代码就层层加密, 惟恐互联网爬虫爬到它上面取内容。进入到移动互联网时代,就更加变本加厉,盆友 圈里的诸多内容,恐怕诸位都是没办法弄出来的。

早年曾在Blog上添加过分享到朋友圈分享到微信好友按钮,由于github.io未 被疼讯认可,共享出来的链接通常只有自己能看到,这又是一个拿用户当SB的典型 案例。

还好,对于用户上传图片,疼讯是没法限制的。所以有了以下的开发。

功能参考

在博文里添加按钮一键保存为图片,即可将该篇文章生成为长图片。

/images/2016_11_05_18_38_31_637x390.jpg

参考设计: 锤子便签。顺便吐槽一下锤子便签,添加了关键词过滤,关键词嘛,这也是 党国拿来折腾屁民的一个傻逼玩意,例如有一首歌是这么唱的:

我爱北京关键词,
关键词上太阳升。。
伟大得领袖关键词,
带领我们向前进…

╮〔╯ε╰〕╭ —太多的关键词,容易让写博文的人心情不好。

可选方案

A. wkhtmltoimage.
这个转换起来是全屏转换,所以最初想到的是对网页做再加工,抠取出其中含有内容的一部分。 好处是,真的是所见即所得。

$ wkhtmltoimage http://www.google.com google.jpg

B. html2canvas.
这种方案直接在html页面上做文章,添加按钮后直接用画布来生成对象。缺点是有些格式显示出来 有少量阴影。

暂时基于方案B实现。

Code

参考资料:
https://www.youtube.com/watch?v=-d2FeFiBvEo
https://html2canvas.hertzen.com/

因为本博客基于hugo构建,直接修改hugo使用的主题即可添加html2canvas。

目录结构:

$ ls  
config.toml  content  id_rsa.enc  scripts  static  themes
$ themes/hyde-a
$ ls
archetypes  images  layouts  LICENSE  README.md  static  theme.toml

下载html2canvas.js到主题的static/js目录:

$ cd static/js
$ wget
https://github.com/niklasvh/html2canvas/releases/download/0.4.1/html2canvas.js

在主题的./layouts/partials/head.html文件中添加所需要的js文件及javascript代码 , (+代表新添加代码):

  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.5/styles/docco.min.css">
+  <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
+  <script type="text/javascript" src="/js/html2canvas.js"></script>
+  <script type='text/javascript'>//<![CDATA[
+  function genPostShot() { 
+          var rightNow = new Date();
+          var imageName = rightNow.toISOString().slice(0,16).replace(/(-)|(:)|(T)/g,"");
+          imageName += '.jpg'
+          html2canvas(document.getElementsByClassName('post'), {
+              onrendered: function(canvas) {
+  		// Click them for download
+          	$('#test').attr('href', canvas.toDataURL("image/jpeg"));
+          	$('#test').attr('download',imageName);
+          	$('#test')[0].click();
+              }
+          });
+  }; 
+  //]]>
+  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.5/highlight.min.js"></script>

简单解释一下这几行代码:

  1. 取当时UTC时间作为下载jpg文件名。
  2. 在当前页面中根据div的class名称找到post字段,构建一个画布。
  3. 将画布内容输出为jpeg文件,触发浏览器的一个下载动作。

注意: #test为在html文件中添加的一个不可见链接.

接下来修改每个博文用到的模板文件(layourts/post/single.html):

{{ partial "head.html" . }}
<div class="content container">
  <div class="post">
    <h1>{{ .Title }}</h1>
+    <p align="right">
+    <a href="javascript:genPostShot()">
+	    TurnToJPG --> <i class="fa fa-camera-retro fa-2x"></i>
+    </a>
+    <a id="test"></a>
+    </p>
+    <hr>
    <span class="post-date">{{ .Date.Format "Jan 2, 2006" }} {{ if .Site.DisqusShortname }} &middot; <a href="{{ .Permalink }}#disqus_thread">Comments</a>{{ end }}

简单解释一下上述添加的代码:

添加一个超链接,指向上文定义的javascript函数genPostShot().

保存修改,提交到上游仓库,重新生成整个静态网站,现在每个博文里都含有保存图片按钮。

效果

譬如,点击http://purplepalmdash.github.io/2013/11/17/run-in-winter/

效果如下:

/images/2016_11_05_18_56_04_638x402.jpg

点击按钮,下载为文件201611051057.jpg(当前UTC时间戳),效果如下:

/images/2016_11_05_18_58_11_250x375.jpg

打完,收工,以后在盆友圈想怎么咆哮就可以怎么咆哮了。

Trouble-Shooting

之所以加这么个条目是因为,在未定义背景的网页里,有时候截出来的图是黑色背景的,修正:

修改./static/js/html2canvas.js文件:

sTransparent = function(backgroundColor) {
  return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0,
0, 0)");
};

改为:

_html2canvas.Util.isTransparent = function(backgroundColor) {
  return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0,
0, 0)" || backgroundColor === undefined);
};

之后我们在./layouts/partials/head.html中,添加这一行:

          html2canvas(document.getElementsByClassName('post'), {
+              background :'#FFFFFF',
              onrendered: function(canvas) {

现在生成的图片背景就是白色的了。

SetupARegistryProxyCacheForDocker

准备

首先需要准备以下Docker image:

$ sudo docker pull registry:latest
$ sudo docker pull registry:2

/etc/hosts里加一条记录,接下来我们将用这条记录生成签名(注意修改IP地址和域名):

# echo '192.168.0.121    xxx.xxx.xxx.com'>>/etc/hosts

准备所需要的自签名文件(用于tls连接)

mkdir -p certs && openssl req   -newkey rsa:4096 -nodes -sha256 -keyout
certs/domain.key   -x509 -days 365 -out certs/domain.crt
Generating a 4096 bit RSA private key
....................................................................................................++
......++
writing new private key to 'certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Guangdong
Locality Name (eg, city) []:Guangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DashCom
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:xxx.xxx.xxx.com
Email Address []:xxxxxx@gmail.com

启动容器

首先拷贝出默认的registry容器的配置文件:

$ sudo mkdir -p /data
$ sudo chmod 777 -R /data
$ sudo docker run -it --rm --entrypoint cat registry:2 \
/etc/docker/registry/config.yml > /data/config.yml

修改默认文件,添加proxy字段等,我的配置如下:

version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  tls:
    certificate: /var/lib/registry/domain.crt
    key: /var/lib/registry/domain.key
  headers:
    X-Content-Type-Options: [nosniff]
proxy:
  remoteurl: https://registry-1.docker.io
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3

将上一步生成的domain.crtdomain.key文件也拷贝到/data文件夹下.

现在运行容器:

$ sudo docker run -d --restart=always -p 5000:5000 --name v2-mirror  -v
/data:/var/lib/registry registry:2 /var/lib/registry/config.yml

运行完这条命令后,可以用sudo netstat -anp| grep 5000来检查registry服务是否被启动。

使用Registry服务

在客户机上,需要做以下设置, 这里我写成脚本的方式,具体的调整需要根据实际情况:

echo '192.168.0.121    xxx.xxx.xxx.com'>>/etc/hosts
apt-get install -y wget
mkdir -p /etc/docker/certs.d/xxx.xxx.xx.com:5000/
wget -O /etc/docker/certs.d/xxx.xxx.xxx.com:5000/ca.crt http://192.168.0.121/domain.crt
sed -i 's#fd://#fd:// --registry-mirror https://xxx.xxx.xxx.com:5000#' /lib/systemd/system/docker.service
systemctl daemon-reload
systemctl restart docker

这里的http://192.168.0.121/domain.crt是我把domain.crt文件放在一个web服务器上了,可以 直接拷贝现成的,改名即可。

现在测试:

# curl -I https://xxx.xxx.xxx.com:5000/v2 --cacert \ 
/etc/docker/certs.d/xxx.xxx.xxx.com\:5000/ca.crt 

HTTP/1.1 301 Moved Permanently
Docker-Distribution-Api-Version: registry/2.0
Location: /v2/
Date: Fri, 04 Nov 2016 09:42:41 GMT
Content-Type: text/plain; charset=utf-8

检查镜像:

# curl  https://xxx.xxx.xxx.com:5000/v2/_catalog --cacert \
/etc/docker/certs.d/xxx.xxx.xxx.com\:5000/ca.crt 
{"":[""]}

docker pull一个镜像:

# docker pull busybox:latest

现在检查:

# curl  https://xxx.xxx.xxx.com:5000/v2/_catalog --cacert \
/etc/docker/certs.d/xxx.xxx.xxx.com\:5000/ca.crt 
{"repositories":["library/busybox","library/ubuntu"]}

可以看到,library/busybox这个镜像已经被缓存在了本地registry仓库中。