MYSQL的NOW和SYSDATE函数的区别

在MySQL Performance Blog博客上看到一篇文章介绍now()和sysdate()函数。

想起很多朋友专门问在MySQL里面提供now()和sysdate()函数,都是表示取得当前时间,他们之间有什么区别。我们下面来详细看一下

首先大家可以看一下下面的一个诡异现象:

mysql> SELECT NOW(),SYSDATE();
+---------------------+---------------------+
| NOW() | SYSDATE() |
+-----------------------------+----------------------------+
| 1999-01-01 00:00:00 | 2012-12-05 09:50:03 |
+---------------------------+----------------------------+
1 row in set (0.00 sec)

很有意思吧?
sysdate()得到的时间是当前时间,而now()取出来的时间竟然是“1999-01-01 00:00:00”。
首先申明,我不是PS或者修改得来的,你看完本文,我会教你在你的MySQL上也得出这样的结果。

另外我们看一下,now()和sysdate()的另外一个区别:

mysql> SELECT NOW(), SLEEP(2), NOW();
+---------------------+----------+---------------------+
| NOW() | SLEEP(2) | NOW( |
+-----------------------------+--------------+-----------------------------+
| 2006-04-12 13:47:36 | 0 | 2006-04-12 13:47:36 |
+---------------------------+--------------+----------------------------+

mysql> SELECT SYSDATE(), SLEEP(2), SYSDATE();
+---------------------+----------+---------------------+
| SYSDATE() | SLEEP(2) | SYSDATE() |
+-----------------------------+--------------+----------------------------+
| 2006-04-12 13:47:44 | 0 | 2006-04-12 13:47:46 |
+---------------------------+--------------+----------------------------+

在使用now()的情况下,虽然我们sleep了2秒,但是大家可以看到两次now()函数输出的结果都是’2006-04-12 13:47:36′
而使用sysdate()的情况下,是两个时间’2006-04-12 13:47:44′,’2006-04-12 13:47:46’,正好相差两秒。

这个最终的原因,大家可以直接查看MySQL的reference对now()函数的解释:http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_now
我简单给大家翻译一下。
now()函数,返回的是当前的时间。但是当前的时间是怎么取的列?

首先,对于now()函数来说,它取的时间是语句开始执行的那个时间,并且在语句执行过程中,这个值都不会变。甚至于,你在执行一个存储过程或者触发器时,这个值都是一直不变的。

这也就解释了,为什么sleep了2秒以后,在SELECT NOW(), SLEEP(2), NOW();语句中,取出的时间值是同一个:’2006-04-12 13:47:36’。

 

然后:now()函数取的当前时间从哪里来?它取自mysql的一个变量”TIMESTAMP”。

很奇怪吧?

其实这个是由于MySQL的replication导致的。你可以想象一下,一个insert into  gguard values (3,now());语句在两台MySQL上插入的值是不是一样?now()如果像sysdate()一样取的是机器的系统时间,那么在MySQL的主库和备库执行同一个这样的SQL语句,主库和备库的这一条数据肯定就不一致了。

主备库不一致的问题必须要解决,两种解决方式:

1、修复这种问题。

2、不使用statement的语句级别复制,而是类似于oracle的,将数据变更记录下来,原样在备库执行一遍。

第二种方式就是大家熟知的,binlog_format=ROW的方式。第一种就是now()不使用机器系统时间,而是取mysql的变量”TIMESTAMP”值。

另外的类似的变量还包括insert_id(用于复制时,AUTO_INCREMENT的取值)等

 

利用mysqlbinlog你可以看到每个binlog event都有一个时间值。

# at 441
#121205 10:06:52 server id 5 end_log_pos 526 Query thread_id=5 exec_time=0 error_code=0
SET TIMESTAMP=1354673212.982122/*!*/;
BEGIN
/*!*/;
# at 526
#121205 10:06:52 server id 5 end_log_pos 642 Query thread_id=5 exec_time=0 error_code=0
use `test`/*!*/;
SET TIMESTAMP=1354673212.982122/*!*/;
insert into gguard values (3,now())
/*!*/;
# at 642
#121205 10:06:52 server id 5 end_log_pos 669 Xid = 26
COMMIT/*!*/;

备库复制执行时,SQL thread在做每个insert或者其他操作前首先要执行SET TIMESTAMP这样的动作,保证now()函数在statement模式下在备库和主库一样。
这里还有另外一种含义:sysdate()函数在statement模式下,主库和备库会不一致,也就是说sysdate在statement复制模式下是不安全的。

 

那么怎么实现上面的SELECT NOW(),SYSDATE();查询出来的时间不一样列,你只需要在之前执行:

SET TIMESTAMP=UNIX_TIMESTAMP('1999-01-01');
SELECT NOW(),SYSDATE();

 
体验now()和sysdate()的神秘吧 🙂

注意:

CURRENT_TIMESTAMP() LOCALTIME() LOCALTIMESTAMP()都是now()函数的同义词,不讨论。
sysdate()没有同义词。
如果你觉得now()函数就够了,你不需要每次都取当前的机器系统时间,那么你可以在MySQL启动时指定–sysdate-is-now,这样的话MySQL会把sysdate()当成now()的一个同义词。

参考:
http://www.mysqlperformanceblog.com/2012/11/28/replication-of-the-now-function-also-time-travel/

[Redis] redis-cli 命令总结

Redis提供了丰富的命令(command)对数据库和各种数据类型进行操作,这些command可以在Linux终端使用。在编程时,比如使用Redis 的Java语言包,这些命令都有对应的方法。下面将Redis提供的命令做一总结。

官网命令列表:http://redis.io/commands (英文)

1、连接操作相关的命令

  • quit:关闭连接(connection)
  • auth:简单密码认证

2、对value操作的命令

  • exists(key):确认一个key是否存在
  • del(key):删除一个key
  • type(key):返回值的类型
  • keys(pattern):返回满足给定pattern的所有key
  • randomkey:随机返回key空间的一个key
  • rename(oldname, newname):将key由oldname重命名为newname,若newname存在则删除newname表示的key
  • dbsize:返回当前数据库中key的数目
  • expire:设定一个key的活动时间(s)
  • ttl:获得一个key的活动时间
  • select(index):按索引查询
  • move(key, dbindex):将当前数据库中的key转移到有dbindex索引的数据库
  • flushdb:删除当前选择数据库中的所有key
  • flushall:删除所有数据库中的所有key

3、对String操作的命令

  • set(key, value):给数据库中名称为key的string赋予值value
  • get(key):返回数据库中名称为key的string的value
  • getset(key, value):给名称为key的string赋予上一次的value
  • mget(key1, key2,…, key N):返回库中多个string(它们的名称为key1,key2…)的value
  • setnx(key, value):如果不存在名称为key的string,则向库中添加string,名称为key,值为value
  • setex(key, time, value):向库中添加string(名称为key,值为value)同时,设定过期时间time
  • mset(key1, value1, key2, value2,…key N, value N):同时给多个string赋值,名称为key i的string赋值value i
  • msetnx(key1, value1, key2, value2,…key N, value N):如果所有名称为key i的string都不存在,则向库中添加string,名称key i赋值为value i
  • incr(key):名称为key的string增1操作
  • incrby(key, integer):名称为key的string增加integer
  • decr(key):名称为key的string减1操作
  • decrby(key, integer):名称为key的string减少integer
  • append(key, value):名称为key的string的值附加value
  • substr(key, start, end):返回名称为key的string的value的子串

4、对List操作的命令

  • rpush(key, value):在名称为key的list尾添加一个值为value的元素
  • lpush(key, value):在名称为key的list头添加一个值为value的 元素
  • llen(key):返回名称为key的list的长度
  • lrange(key, start, end):返回名称为key的list中start至end之间的元素(下标从0开始,下同)
  • ltrim(key, start, end):截取名称为key的list,保留start至end之间的元素
  • lindex(key, index):返回名称为key的list中index位置的元素
  • lset(key, index, value):给名称为key的list中index位置的元素赋值为value
  • lrem(key, count, value):删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count>0从头至尾删除count个值为value的元素,count<0从尾到头删除|count|个值为value的元素。 lpop(key):返回并删除名称为key的list中的首元素 rpop(key):返回并删除名称为key的list中的尾元素 blpop(key1, key2,… key N, timeout):lpop命令的block版本。即当timeout为0时,若遇到名称为key i的list不存在或该list为空,则命令结束。如果timeout>0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对keyi+1开始的list执行pop操作。
  • brpop(key1, key2,… key N, timeout):rpop的block版本。参考上一命令。
  • rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部

5、对Set操作的命令

  • sadd(key, member):向名称为key的set中添加元素member
  • srem(key, member) :删除名称为key的set中的元素member
  • spop(key) :随机返回并删除名称为key的set中一个元素
  • smove(srckey, dstkey, member) :将member元素从名称为srckey的集合移到名称为dstkey的集合
  • scard(key) :返回名称为key的set的基数
  • sismember(key, member) :测试member是否是名称为key的set的元素
  • sinter(key1, key2,…key N) :求交集
  • sinterstore(dstkey, key1, key2,…key N) :求交集并将交集保存到dstkey的集合
  • sunion(key1, key2,…key N) :求并集
  • sunionstore(dstkey, key1, key2,…key N) :求并集并将并集保存到dstkey的集合
  • sdiff(key1, key2,…key N) :求差集
  • sdiffstore(dstkey, key1, key2,…key N) :求差集并将差集保存到dstkey的集合
  • smembers(key) :返回名称为key的set的所有元素
  • srandmember(key) :随机返回名称为key的set的一个元素

6、对zset(sorted set)操作的命令

  • zadd(key, score, member):向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。
  • zrem(key, member) :删除名称为key的zset中的元素member
  • zincrby(key, increment, member) :如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment
  • zrank(key, member) :返回名称为key的zset(元素已按score从小到大排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
  • zrevrank(key, member) :返回名称为key的zset(元素已按score从大到小排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
  • zrange(key, start, end):返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素
  • zrevrange(key, start, end):返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素
  • zrangebyscore(key, min, max):返回名称为key的zset中score >= min且score <= max的所有元素 zcard(key):返回名称为key的zset的基数 zscore(key, element):返回名称为key的zset中元素element的score zremrangebyrank(key, min, max):删除名称为key的zset中rank >= min且rank <= max的所有元素 zremrangebyscore(key, min, max) :删除名称为key的zset中score >= min且score <= max的所有元素
  • zunionstore / zinterstore(dstkeyN, key1,…,keyN, WEIGHTS w1,…wN, AGGREGATE SUM|MIN|MAX):对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。

7、对Hash操作的命令

  • hset(key, field, value):向名称为key的hash中添加元素field<—>value
  • hget(key, field):返回名称为key的hash中field对应的value
  • hmget(key, field1, …,field N):返回名称为key的hash中field i对应的value
  • hmset(key, field1, value1,…,field N, value N):向名称为key的hash中添加元素field i<—>value i
  • hincrby(key, field, integer):将名称为key的hash中field的value增加integer
  • hexists(key, field):名称为key的hash中是否存在键为field的域
  • hdel(key, field):删除名称为key的hash中键为field的域
  • hlen(key):返回名称为key的hash中元素个数
  • hkeys(key):返回名称为key的hash中所有键
  • hvals(key):返回名称为key的hash中所有键对应的value
  • hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value

8、持久化

  • save:将数据同步保存到磁盘
  • bgsave:将数据异步保存到磁盘
  • lastsave:返回上次成功将数据保存到磁盘的Unix时戳
  • shundown:将数据同步保存到磁盘,然后关闭服务

9、远程服务控制

  • info:提供服务器的信息和统计
  • monitor:实时转储收到的请求
  • slaveof:改变复制策略设置
  • config:在运行时配置Redis服务器

Redis高级应用
1、安全性
设置客户端连接后进行任何操作指定前需要密码,一个外部用户可以再一秒钟进行150W次访问,具体操作密码修改设置redis.conf里面的requirepass属性给予密码,当然我这里给的是primos
之后如果想操作可以采用登陆的时候就授权使用:
sudo /opt/java/redis/bin/redis-cli -a primos
或者是进入以后auth primos然后就可以随意操作了

2、主从复制
做这个操作的时候我准备了两个虚拟机,ip分别是192.168.15.128和192.168.15.133
通过主从复制可以允许多个slave server拥有和master server相同的数据库副本
具体配置是在slave上面配置slave
slaveof 192.168.15.128 6379
masterauth primos
如果没有主从同步那么就检查一下是不是防火墙的问题,我用的是ufw,设置一下sudo ufw allow 6379就可以了
这个时候可以通过info查看具体的情况

3、事务处理
redis对事务的支持还比较简单,redis只能保证一个client发起的事务中的命令可以连续执行,而中间不会插入其他client的命令。当一个client在一个连接中发出multi命令时,这个连接会进入一个事务的上下文,连接后续命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。
比如我下面的一个例子
set age 100
multi
set age 10
set age 20
exec
get age –这个内容就应该是20
multi
set age 20
set age 10
exec
get age –这个时候的内容就成了10,充分体现了一下按照队列顺序执行的方式
discard 取消所有事务,也就是事务回滚
不过在redis事务执行有个别错误的时候,事务不会回滚,会把不错误的内容执行,错误的内容直接放弃,目前最新的是2.6.7也有这个问题的
乐观锁
watch key如果没watch的key有改动那么outdate的事务是不能执行的

4、持久化机制
redis是一个支持持久化的内存数据库
snapshotting快照方式,默认的存储方式,默认写入dump.rdb的二进制文件中,可以配置redis在n秒内如果超过m个key被修改过就自动做快照
append-only file aof方式,使用aof时候redis会将每一次的函 数都追加到文件中,当redis重启时会重新执行文件中的保存的写命
令在内存中。
5、发布订阅消息 sbusribe publish操作,其实就类似linux下面的消息发布
6、虚拟内存的使用
可以配置vm功能,保存路径,最大内存上线,页面多少,页面大小,最大工作线程
临时修改ip地址ifconfig eth0 192.168.15.129

redis-cli参数
Usage: redis-cli [OPTIONS] [cmd [arg [arg …]]]
-h Server hostname (default: 127.0.0.1)
-p Server port (default: 6379)
-s Server socket (overrides hostname and port)
-a Password to use when connecting to the server
-r Execute specified command N times
-i When -r is used, waits seconds per command.
It is possible to specify sub-second times like -i 0.1
-n Database number
-x Read last argument from STDIN
-d Multi-bulk delimiter in for raw formatting (default: \n)
-c Enable cluster mode (follow -ASK and -MOVED redirections)
–raw Use raw formatting for replies (default when STDOUT is not a tty)
–latency Enter a special mode continuously sampling latency
–slave Simulate a slave showing commands received from the master
–pipe Transfer raw Redis protocol from stdin to server
–bigkeys Sample Redis keys looking for big keys
–eval Send an EVAL command using the Lua script at
–help Output this help and exit
–version Output version and exit

Examples:
cat /etc/passwd | redis-cli -x set mypasswd
redis-cli get mypasswd
redis-cli -r 100 lpush mylist x
redis-cli -r 100 -i 1 info | grep used_memory_human:
redis-cli –eval myscript.lua key1 key2 , arg1 arg2 arg3
(Note: when using –eval the comma separates KEYS[] from ARGV[] items)

常用命令:
1) 查看keys个数
keys * // 查看所有keys
keys prefix_* // 查看前缀为”prefix_”的所有keys

2) 清空数据库
flushdb // 清除当前数据库的所有keys
flushall // 清除所有数据库的所有keys

常用Openssl命令

申请证书

SSL常用于身份验证、数据加密等应用中,要使用SSL,我们密码有自己的证书。数字证书一般要向专业的认证公司(如VeriSign)申请,并且 都是收费的,某些情况下,我们只是想使用加密的数据通信,而不在乎认证,这时就可以自己制作一个证书,自己制作一个证书,有两种方式,一种是Self Signed,另一种是自己制作一个CA,然后由这个CA,来发布我们需要的证书。下面分别介绍这两个方法。

生成Self Signed证书

# 生成一个key,你的私钥,openssl会提示你输入一个密码,可以输入,也可以不输,
# 输入的话,以后每次使用这个key的时候都要输入密码,安全起见,还是应该有一个密码保护
> openssl genrsa -des3 -out selfsign.key 4096

# 使用上面生成的key,生成一个certificate signing request (CSR)
# 如果你的key有密码保护,openssl首先会询问你的密码,然后询问你一系列问题,
# 其中Common Name(CN)是最重要的,它代表你的证书要代表的目标,如果你为网站申请的证书,就要添你的域名。
> openssl req -new -key selfsign.key -out selfsign.csr

# 生成Self Signed证书 selfsign.crt就是我们生成的证书了
> openssl x509 -req -days 365 -in selfsign.csr -signkey selfsign.key -out selfsign.crt

# 另外一个比较简单的方法就是用下面的命令,一次生成key和证书
> openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privateKey.key -out certificate.crt

生成自己的CA (Certificate Authority)

CA是证书的发布者,CA可以发布其他人的证书,把CA的证书加入系统信任的根证书后,由CA发布的证书也被系统所信任,所以,CA的key是必须小心保护的,一般都要加密保护,并且限制为root权限读写。

# 生成CA的key
> openssl genrsa -des3 -out ca.key 4096

# 生成CA的证书
> openssl req -new -x509 -days 365 -key ca.key -out ca.crt

# 生成我们的key和CSR这两步与上面Self Signed中是一样的
> openssl genrsa -des3 -out myserver.key 4096
> openssl req -new -key myserver.key -out myserver.csr

# 使用ca的证书和key,生成我们的证书
# 这里的set_serial指明了证书的序号,如果证书过期了(365天后),
# 或者证书key泄漏了,需要重新发证的时候,就要加1
> openssl x509 -req -days 365 -in myserver.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out myserver.crt

查看证书

# 查看KEY信息
> openssl rsa -noout -text -in myserver.key
# 查看CSR信息
> openssl req -noout -text -in myserver.csr

# 查看证书信息
> openssl x509 -noout -text -in ca.crt

# 验证证书
# 会提示self signed
> openssl verify selfsign.crt

# 因为myserver.crt 是幅ca.crt发布的,所以会验证成功
> openssl verify -CAfile ca.crt myserver.crt

去掉key的密码保护

有时候每次都要输入密码太繁琐了,可以把Key的保护密码去掉

> openssl rsa -in myserver.key -out server.key.insecure

不同格式证书的转换

一般证书有三种格式:

  • PEM(.pem) 前面命令生成的都是这种格式,
  • DER(.cer .der) Windows 上常见
  • PKCS#12文件(.pfx .p12) Mac上常见

# PEM转换为DER
> openssl x509 -outform der -in myserver.crt -out myserver.der

# DER转换为PEM
> openssl x509 -inform der -in myserver.cer -out myserver.pem

# PEM转换为PKCS
> openssl pkcs12 -export -out myserver.pfx -inkey myserver.key -in myserver.crt -certfile ca.crt

# PKCS转换为PEM
> openssl pkcs12 -in myserver.pfx -out myserver2.pem -nodes

测试证书

Openssl提供了简单的client和server工具,可以用来模拟SSL连接,做测试使用。

# 连接到远程服务器
> openssl s_client -connect www.google.com.hk:443

# 模拟的HTTPS服务,可以返回Openssl相关信息
# -accept 用来指定监听的端口号
# -cert -key 用来指定提供服务的key和证书
> openssl s_server -accept 443 -cert myserver.crt -key myserver.key -www

# 可以将key和证书写到同一个文件中
> cat myserver.crt myserver.key > myserver.pem
# 使用的时候只提供一个参数就可以了
> openssl s_server -accept 443 -cert myserver.pem -www

# 可以将服务器的证书保存下来
> openssl s_client -connect www.google.com.hk:443 remoteserver.pem
# 转换成DER文件,就可以在Windows下直接查看了
> openssl x509 -outform der -in remoteserver.pem -out remoteserver.cer

计算MD5和SHA1

# MD5 digest
> openssl dgst -md5 filename
# SHA1 digest
> openssl dgst -sha1 filename

Notepad++ 安装版右键菜单创建失败

今天在装一台服务器的时候发现又遇到了安装 Notepad++ 没有成功创建右键菜单的问题,于是决定来研究一下究竟为啥。
在找了相关资料后,我发现 Notepad++ 的安装目录下有一个 DLL 文件专门处理邮件菜单的事情,同时很多人给了一个解决方案是运行这个批处理文件:

@Echo Off
title Notepad++右键菜单添加or卸载工具
SetLocal EnableDelayedExpansion
echo 1.添加Notepad++右键菜单
echo ------------------------
echo 2.卸载Notepad++右键菜单
echo ------------------------
Set /p u=请输入数字并按Enter确定:
If "%u%"=="1" Goto regnp++
If "%u%"=="2" Goto unregnp++
:regnp++
regsvr32 NppShell_06.dll
exit
:unregnp++
regsvr32 /u NppShell_06.dll
exit

但是在运行的时候我发现 DLL 注册并没有成功,提示有错误发生。于是打开事件查看器看到这么一行:

“C:\Program Files (x86)\Notepad++\NppShell_06.dll”的激活上下文生成失败。 找不到从属程序集 Microsoft.VC90.CRT,processorArchitecture="amd64",publicKeyToken="xxxxx",type="win32",version="9.0.21022.8"。 请使用 sxstrace.exe 进行详细诊断。

豁然开朗,原来安装的时候没有成功创建右键菜单的根本原因是缺少了 Microsoft.VC90.CRT 这个运行库,也就是 VC 2008 运行库。从微软网站下载安装之后就搞定啦~

附上下载链接:http://www.microsoft.com/zh-CN/download/details.aspx?id=26368

微软手环 Microsoft Band 使用一周体验

[info]未经许可不得转载本文或使用本文中的照片[/info]
I.购买

事实上,在微软手环刚刚出来的时候我就开始关注这款产品了。第一批发售的时候也下了单,但是最终还是没有下定决心,取消了订单。直到看到一部分评测之后,才有点后悔 可惜已经没货了。于是抱着“算了加点钱买苹果表吧”的心态,一直等到苹果发布会,然后得知了苹果表续航只有一天(18h)这个事实。。。 一天24h我都不够用你就这么给我再砍掉了6个小时啊摔!于是连夜打开微软官方网站,发现居然又有货了!(微软你故意的吧! 于是赶紧下单抢了一个。

购 买过程中发现确实微软美国商店对国内信用卡非常不友好。我的招行全币种 Visa 卡下单之后虽然扣款了,但是在账户订单列表中始终看不到订购信息。然后过了几个小时招行告诉我退款了。。。到大妈上看了一圈发现出现这个情况的人不少,于 是掏出 Google Voice 一个电话打到了在线客服。经过长达半小时的交流之后,客服 MM 帮我重新下了订单。(不过下单过程中让我报了信用卡号和 CVV 好虚啊 客服说下单成功后终于在后台查到了信息,显示预计 3月17日 发货。

II.转运

因 为之前注册过一个有家速递的账户,而且搜了一下发现这家还不错,于是就选择了使用这家作为转运商家。整个转运过程一共持续 9天,7个工作日左右,个人感觉还算是比较慢的。因为我选择的是送到香港自提,没有入关清关时间,所以个人觉得 7个工作日还是蛮久的。。。特别吐槽一下有家的后台记录:

2015-03-18 16:23:57 US DE New Castle UCS 上门取件成功
2015-03-18 21:23:57 US DE New Castle UCS 货件已到达仓库
2015-03-19 23:01:47 US DE New Castle UCS 原箱转运已处理
2015-03-21 03:46:47 US DE New Castle UCS 货件已从仓库发出
2015-03-21 03:47:29 CN 华航 AIR 货件已发往机场,预计起飞时间2015-03-21 15:10:00,预计到达时间2015-03-22 15:30:00
2015-03-21 09:00:00 CN 华航 AIR 货件已到达机场,正在装机中。
2015-03-22 23:03:00 CN 华航 AIR 航班已经起飞
2015-03-24 19:36:00 CN 华航 AIR 航班已经到达
2015-03-25 03:09:00 CN 华航 AIR 货件已到达机场,正在提货中。
2015-03-25 14:09:09 HK 香港信汇仓库 XINHUIHK 货件已到达自提仓库
2015-03-25 18:26:25 HK 香港信汇仓库 XINHUIHK 已提货签收

21号凌晨发往机场,飞机预计22号下午到,结果实际上飞机22号才起飞。。。更惊悚的是飞了一天多才到。。。

III.拆箱

在经历了半个月之后,终于拿到了这个包裹,赶紧先来看看外包装:

UPS包装1

UPS包装1

UPS包装2

UPS包装2

UPS包装3

UPS包装3

我选择的是原箱转运,所以微软发来的包装就是这个样子的。一个 UPS 的信封,内里有泡沫,基本上还是不会损坏里面的盒子的,所以我在拿到手的时候里面的盒子非常完整:

 

包装盒带保护膜1

包装盒带保护膜1

包装盒带保护膜2

包装盒带保护膜2

包装盒带保护膜3

包装盒带保护膜3

包装盒带保护膜4

包装盒带保护膜4

包装盒带保护膜5

包装盒带保护膜5

去掉这个简单套在外面的塑料膜之后:

包装盒

包装盒

包装盒2

包装盒2

包装盒3

包装盒3

包装盒4

包装盒4

包装盒4

包装盒4

顺便一说,微软官网提供了一个测试手腕大小的文档,用打印机打出来跟自己的手腕对比一下就大概知道需要哪个号。不过我觉得微软的号明显偏大,我买了 M 号的结果如果卡口不扣到最紧就能明显的感到晃动,挺难受的。不过可能是我的手腕偏瘦,如果大家要买的话记得一定要用微软提供的测试纸先试一下,再决定买哪个号码。

扣开两遍的两个圆形胶贴之后就可以抽出内盒了,一个纯黑带 Logo 的盒子:

内盒

内盒

这个盒子做的还是挺漂亮的,我们打开看看~

开箱1

开箱1

开箱2

开箱2

这个包装盒的设计还是挺用心的,底层的说明书和保修卡都做了一个突起完美存放不晃动

接下来就是本体了!绝对真开箱哦~~~

本体1

本体1

本体2

本体2

本体3

本体3

没插充电线之前死活也没打开手环,可能是我的打开方式不对,也可能是微软的设计,第一次打开必须要接电源吧。。。这个还有待考证。。。

接下来就是跟手机配对啦~总体来说,我的手环跟我的 iPhone 6 配对还是蛮顺利的,只是出了这么个问题:

Bug

Bug

搜索了一下发现这似乎是微软的软件的 Bug。不要惊慌,取消配对,删除软件重新装一下然后重新配对就好了。。。

然后就到了这么个界面:

更新

更新

更新

更新

微软的一贯风格,想用先升级,Orz。。。

等了好久终于升级成功了,看到这么个画面:

成功

成功

Yeah!开心的点 next,然后就可以开始对手环进行自定义了。不过可自定义的内容不是太多:

自定义1

自定义1

自定义2

自定义2

自定义3

自定义3

自定义4

自定义4

自定义5

自定义5

这里还可以自定义哪些通知要推送到 Microsoft Band 上,像那些脸书什么根本不存在的网站就不管他了

自定义6

自定义6

自定义之后就可以正式开始使用了:

设置完毕1

设置完毕1

注意右下角的小箭头,那个指向了 Start 按钮,手环的很多操作都需要这个 Start 按钮来触发。

设置完毕2

设置完毕2

然后这是充电头的样子:

充电

充电

这个充电头吸附的还是不太紧,很容易脱落,特别是如果你的充电头是从另一个方向吸附的话,充电中只要你去按按钮,基本上都会导致充电头脱落。。。

IV.佩戴感受

佩戴的图已经有很多人上了,所以我就不再拍照,只是说一下我的佩戴感受:

  1. 屏幕向内比较舒服。这是无需置疑的一点,因为屏幕实在是太大了,向外的话会突出手腕,很难受,所以向内比较舒服。但是如果屏幕向内的话,手放在桌子上的时候你的屏幕就遭殃了,所以最终我还是选择了屏幕向外。
  2. 心率传感器太厚。就算是屏幕向外佩戴,由于手腕内侧的心率传感器的存在,手平放在桌子上的时候还是会被抬高很多,特别难受。如果是用笔记本电脑的话打字非常难受。不过如果是台式机键盘的话刚好将手腕部分架空,还不算太难受。
  3. 卡扣很容易松动。由于卡扣稍稍按下去一点就会松动,所以在佩戴过程中只要手腕稍微靠近衣物,就可能会摩擦到卡扣按钮,导致松动。由于我的手腕本来就很细,最紧的情况下还是很送到,这个问题就显得特别严重,每过一段时间就要手动调紧一些。
  4. 整体来说不算很重。如果在正常的行走过程中,手环的重量基本不会感觉到,不会有太多的手上戴了东西的感觉。
  5. 闹钟设计太傻逼。闹钟居然只能设置一次,每次闹完了就会自动关闭,想要再闹就要手动开启。。。结果导致我每天睡前先打开闹钟再打开睡眠模式,感觉整个人都呵呵哒。。。

V.续航

接下来就是最重要的部分了,也是我放弃苹果表的根本原因:续航。在苹果重新定义了一天(18h)之后,我可以自豪的说,我的手环待机起码3天!

好了好了不开玩笑,说正经的。下面的待机描述中 天 都是指 24h,待机时间计算到手环提示电量低为止:(顺便一说电量低的时候手环会自动关掉震动,保持最基本的功能。

  1. 轻度使用,待机可以达到 3 天。打开蓝牙,打开通知推送,打开闹钟,打开心率监测,每晚打开睡眠模式,关闭手表模式,不使用运动跟踪,在第三天晚上左右提示我电量不足需要充电,而我开始使用的时间也是晚上,基本上达到了 3*24h。
  2. 中度使用,待机可以达到 2 天。打开蓝牙,打开通知推送,打开闹钟,打开心率监测,打开手表模式,每晚打开睡眠模式,不使用运动跟踪,在大约过了 48h 左右提示我电量不足需要充电。
  3. 重度使用,那就必须一天一充了。头天晚上充满电戴上,打开蓝牙,打开通知推送,打开闹钟,打开心率监测,打开手表模式,打开睡眠模式,用运动跟踪2次,总时间 1.5h 左右,打开 GPS,当天晚上回家的时候就提示电量不足需要充电,勉强够 24h。

VI.系统适配

因 为我的手机是 iPhone 6,所以只能说说手环和 iPhone 的配合。整体来说还是不错的,低功耗蓝牙 24h 连着也不会给手机带来太大的负担,不过手环对应的 App 因为要后台接收推送之类的确实也是耗电大户,或多或少减少了手机的待机时间。功能方面,在配合 iOS 的时候,消息都是只读的,不会看到回复选项。同时,手机上看过的消息在手环上还是算作未读的,所以每次点亮屏幕一划就看到好几十的未读还是挺蛋疼的。。。

好了,暂时就先写这么多了~如果后面还有什么使用感受的话会继续在这更新~如果大家有什么想知道的也可以留言询问~我会尽量解答~~~

最后附上一张睡眠追踪的截图:

睡眠跟踪

睡眠跟踪

Ubuntu 14.04 安装 Ejbca (Install Ejbca on Ubuntu 14.04)

[warning]首先,如果不是万不得已,请不要使用 EJBCA,请不要阅读本文章!这个软件真的不是正常人可以驾驭的!如果只是个人兴趣(比如我就是装着好玩),那么请千万不要尝试使用 EJBCA!非常蛋疼!千万不要用!而且这玩意的搭建特别看脸,说不定啥时候就成功了。本文的成功方法并无法复制。[/warning]

这个玩意毕竟是一个商业软件的社区免费版,功能先不说,Bug一定是比商业版多一大堆的。而且官方给的文档也基本都很老了,并且不全,大部分你遇到的问题官方文档都不会说的。官方文档似乎最喜欢教你怎么配置,当然反正按照那个配一样成功不了。。。官方这么做当然另一个目的就是卖收费服务,不然免费的随便配置下就成功了谁还买呢。。。

至于官方的 Quick Start,直接无视吧。如果你按照官方的 Quick Start 成功的把服务搭起来了,那我只能佩服你了。。。反正我一开始一直遵照官方的教程死活也没有成功过一次。直到我找到一篇第三方的教程,才终于成功了一次。原教程地址:http://ejbcacentos.blogspot.hk/2014/04/how-to-install-ejbca-611-on-centos-65.html 因为是全英文的而且需要科学上网来访问,所以我在这里参考这篇教程把我配置的过程写一下。如果按照教程配置不成功请不要提问!我也不知道为什么!我自己配十次能成功一次就很开心了!


介绍

EJBCA 是一个用 Java 编写的可以在网页上完成所有操作的全功能 CA 服务器,只要是 CA 应该支持的功能这个软件全都支持。但是!这个软件的安装完全不像官方说的那么简单!如果你只是想玩玩,建议直接下载官方的虚拟机镜像玩吧。

准备

首先要安装相关依赖。因为我在后端数据库的选择上使用的是 Mysql,所以我需要装这么些东西:
sudo apt-get install openjdk-7-jdk ant ant-optional unzip ntp mysql-server libmysql-java
那篇教程里说 Java 7 会有问题,实际上似乎已经修复了,所以可以直接用。源里 ant 的版本是 1.8.2,满足最低的版本要求,所以也可以直接用,不用下载最新的。libmysql-java 是 Java 连接 Mysql 数据库所需要的必须的组建,因为我使用 Mysql 作为后端,所以需要安装。然后防火墙什么的就不管他了,建议你在确定配置成功的情况下再去搞别的,不然纯属浪费时间。。。

配置 Mysql

mysql 主要是要更改一下默认的编码,确保一直使用 UTF-8 作为编码方式,防止乱码。在 my.cnf 中加入这一段:
#UTF-8
character-set-server=utf8
collation-server=utf8_unicode_ci
init-connect='SET NAMES utf8'
#character-set-client = utf8

然后使用 root 账号登陆,新建数据库和账号:
service mysqld start
mysql_secure_installation
mysql -u root -p
create database ejbcadb;
grant all privileges on ejbcadb.* to 'ejbcadbuser'@'localhost' identified by 'password';
flush privileges;
exit

然后确认一下你刚刚创建的账号可以正常的访问数据库:
mysql -u ejbcadbuser -p
use ejbcadb;
show grants for ejbcadbuser@localhost;
exit

创建用户

建议不要直接使用 root 用户来安装 EJBCA,而是分配专门的账户。所以我们使用 adduser ejbca 添加一个用户。然后执行 su – ejbca,切换到 ejbca 用户下操作。

下载 Ejbca 和 Jboss

wget http://download.jboss.org/jbossas/7.1/jboss-as-7.1.1.Final/jboss-as-7.1.1.Final.zip
wget http://downloads.sourceforge.net/project/ejbca/ejbca6/ejbca_6_2_0/ejbca_ce_6_2_0.zip
unzip *.zip
ln -s ejbca_ca_6_2_0 ejbca
ln -s jboss-as-7.1.1.Final jboss

配置 Jboss

cd /opt/jboss/modules/sun/jdk/main
vi module.xml

在适当位置添加下面几行:(注释不要加进去)
### Start module.xml Delta ###

### End module.xml Delta ###

安装 Mysql 连接组件

cd ~
mkdir -p jboss/modules/com/mysql/main/
ln -s /usr/share/java/mysql.jar
vi module.xml

新建 module.xml 文件,写入如下内容:
### Start module.xml ###










### End module.xml ###
现在可以启动 Jboss 了。打开一个新的终端或者使用 screen 执行 ~/jboss/bin/standalone.sh。日志会写入 ~/jboss/standalone/log/
如果你看到这样的日志,说明 Jboss 应该是启动成功了:
22:51:40,482 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-2) Starting Coyote HTTP/1.1 on http--127.0.0.1-8080
22:51:40,688 INFO [org.jboss.as.remoting] (MSC service thread 1-3) JBAS017100: Listening on /127.0.0.1:4447
22:51:40,690 INFO [org.jboss.as.remoting] (MSC service thread 1-2) JBAS017100: Listening on /127.0.0.1:9999
22:51:40,699 INFO [org.jboss.as.server.deployment.scanner] (MSC service thread 1-3) JBAS015012: Started FileSystemDeploymentService for directory /opt/jboss/standalone/deployments
22:51:40,773 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
22:51:40,774 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 1528ms - Started 130 of 204 services (74 services are passive or on-demand)

接下来给 Jboss 添加 Mysql 连接器:
cd ~/jboss/bin
sh jboss-cli.sh
connect
/subsystem=datasources/jdbc-driver=com.mysql.jdbc.Driver:add(driver-name=com.mysql.jdbc.Driver,driver-module-name=com.mysql,driver-xa-datasource-class-name=com.mysql.jdbc.jdbc.jdbc2.optional.MysqlXADataSource)
:reload
exit

这句话在 ~/jboss/standalone/configuration/standalone.xml 中定义了 Mysql Driver ,然后重启 Jboss。
接下来修改 Jboss 的配置文件,删掉自带的 h2 数据库:
### Start standalone.xml Delta ###

删除这一段:


jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
h2

sa sa

还有这一段:


org.h2.jdbcx.JdbcDataSource

### End standalone.xml Delta ###
好了!现在可以开始配置 Ejbca 了。

配置 Ejbca

Ejbca 的配置文件在这个文件夹里:
~/ejbca/conf/
默认配置文件都以 .sample 结尾。需要修改的话删除 .sample 然后进行相应的修改即可。
cd ~/ejbca/conf
cp certstore.properties.sample certstore.properties
cp cesecore.properties.sample cesecore.properties
cp crlstore.properties.sample crlstore.properties
cp database.properties.sample database.properties
cp ejbca.properties.sample ejbca.properties
cp install.properties.sample install.properties
cp mail.properties.sample mail.properties
cp web.properties.sample web.properties

接下来是要改的配置。这里只放出需要修改的行:
certstore.properties

### Start certstore.properties ###

certstore.enabled=true

certstore.contextroot=/certificates

### End certstore.properties ###

cesecore.properties

### Start cesecore.properties ###

ca.toolateexpiredate=80000000

securityeventsaudit.implementation.X=org.cesecore.audit.impl.log4j.Log4jDevice
securityeventsaudit.implementation.X=org.cesecore.audit.impl.integrityprotected.IntegrityProtectedDevice

securityeventsaudit.implementation.0=org.cesecore.audit.impl.log4j.Log4jDevice
securityeventsaudit.implementation.1=org.cesecore.audit.impl.integrityprotected.IntegrityProtectedDevice
securityeventsaudit.exporter.1=org.cesecore.audit.impl.AuditExporterXml

### End cesecore.properties ###

crlstore.properties

### Start crlstore.properties ###

crlstore.enabled=true
crlstore.contextroot=/crls

### End crlstore.properties ###

database.properties

### Start database.properties ###

datasource.jndi-name=EjbcaDS

database.name=mysql

database.url=jdbc:mysql://127.0.0.1:3306/ejbcadb?characterEncoding=UTF-8
database.driver=com.mysql.jdbc.Driver

database.username=ejbcadbuser

# Change this to your mysql user password:
database.password=pumpkin

### End database.properties ###

ejbca.properties

### Start ejbca.properties ###

appserver.home=/home/ejbca/jboss
appserver.type=jboss

ejbca.productionmode=false

approval.defaultrequestvalidity=28800
approval.defaultapprovalvalidity=28800

healthcheck.amountfreemem=32
healthcheck.dbquery=Select 1 From CertificateData where fingerprint='XX'
healthcheck.authorizedips=127.0.0.1
healthcheck.catokensigntest=true
healthcheck.publisherconnections=true
healthcheck.okmessage=ALLOK
healthcheck.sendservererror=true

ejbca.passwordlogrounds=8

### End ejbca.properties ###

install.properties

### Start install.properties ###

ca.name=mgmtca
ca.dn=CN=mgmtca,O=Your Company,C=US
ca.tokentype=soft
ca.tokenpassword=null

ca.keyspec=4096

ca.keytype=RSA

ca.signaturealgorithm=SHA256WithRSA

ca.validity=3652
ca.policy=null
ca.certificateprofile=ROOTCA

### End install.properties ###

mail.properties

### Start mail.properties ###

mail.jndi-name=java:/EjbcaMail
mail.user=ejbca
mail.password=honeybunny
mail.smtp.host=localhost
mail.smtp.port=25
#mail.smtp.auth=false
#mail.smtp.starttls.enable=false
mail.from=ejbca@yourcompany.net
#mail.debug=false
mail.contentencoding=UTF-8

### End mail.properties ###

web.properties

### Start web.properties ###

superadmin.cn=superadmin
superadmin.dn=CN=${superadmin.cn},O=Your Company,C=US

superadmin.batch=true

httpsserver.hostname=rootca.yourdomain.net
httpsserver.dn=CN=${httpsserver.hostname},O=Your Company,C=US

httpserver.pubhttp=8080

httpserver.pubhttps=8442

httpserver.privhttps=8443
#httpserver.external.privhttps=443

#httpserver.external.fqdn=
#httpserver.external.fqdn=${httpsserver.hostname}

#httpsserver.bindaddress.pubhttp=0.0.0.0
#httpsserver.bindaddress.pubhttps=0.0.0.0
#httpsserver.bindaddress.privhttps=0.0.0.0

web.contentencoding=UTF-8

web.selfreg.enabled=false
web.selfreg.defaultcerttype=1
web.selfreg.certtypes.1.description=User certificate
web.selfreg.certtypes.1.eeprofile=user
web.selfreg.certtypes.1.certprofile=user
web.renewalenabled=false
web.errorpage.notification=An exception has occurred.
web.errorpage.stacktrace=true

web.log.adminremoteip=true

### End web.properties ###
好了!下面可以开始尝试编译了。
cd ~/ejbca
ant deploy

部署的过程中可能会出这么几个问题:
06:05:16,848 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 1) JBAS014612: Operation ("composite") failed - address: ([]): java.lang.IllegalArgumentException

06:05:39,477 ERROR [org.hibernate.internal.util.xml.ErrorLogger] (MSC service thread 1-4) HHH000196: Error parsing XML (21) : cvc-complex-type.3.1: Value '1.0' of attribute 'version' of element 'entity-mappings' is not valid with respect to the corresponding attribute use. Attribute 'version' has a fixed value of '2.0'.

15:29:58,915 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (MSC service thread 1-2) JSF1051: Service entry 'org.jboss.as.web.deployment.jsf.JsfInjectionProvider' does not extend DiscoverableInjectionProvider. Entry will be ignored.
这些问题可以直接无视,这是因为 Jboss 的 Bug。当然,这些问题可能会导致部署失败。那就多试几次吧。。。
如果你在 Jboss 的日志中看到了这个,说明你可能部署成功了:
01:38:38,724 INFO [org.jboss.as] (MSC service thread 1-1) JBAS015874: JBoss AS 7.1.1.Final "Brontes" started in 7761ms - Started 2855 of 2968 services (111 services are passive or on-demand)
01:38:38,769 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "ejbca.ear"

顺便一说,部署的过程中你会看到大量的:
appserver.error.message:
[echo] jndi.properties.file: /home/ejbca/ejbca_ce_6_2_0/conf/jndi.properties.jboss7

没关系,这个我可以确定是完全正常,丝毫不影响后续的。。。

接下来重启 Jboss ,到之前打开的另一个终端或者 screen , Ctrl+C 结束掉 Jboss ,然后重新启动。
之后,回到 ~/ejbca ,执行 ant install
当你看到:

[echo] Initializing CA with 'mgmtCA' 'CN=mgmtca,O=Your Company,C=US' 'soft'

说明你的配置文件没有问题了,至于各种证书和存储库能不能正常生成,还是看脸。

如果你在终端看到 ant 返回 BUILD SUCCESS ,并且重启 Jboss 后能看到这样的日志,恭喜你,配置成功了!
06:20:59,482 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /${app.name}/publicweb/status
06:20:59,484 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb/apply
06:20:59,491 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb/webdist
06:20:59,506 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb
06:20:59,516 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/publicweb/healthcheck
06:20:59,521 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/clearcache
06:20:59,521 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/ejbcaws
06:20:59,571 INFO [org.jboss.web] (MSC service thread 1-4) JBAS018210: Registering web context: /ejbca
06:20:59,727 INFO [org.jboss.web] (MSC service thread 1-1) JBAS018210: Registering web context: /crls
06:20:59,728 INFO [org.jboss.web] (MSC service thread 1-2) JBAS018210: Registering web context: /certificates
06:21:00,141 INFO [org.jboss.web] (MSC service thread 1-3) JBAS018210: Registering web context: /ejbca/adminweb
06:21:16,576 INFO [org.jboss.web] (MSC service thread 1-1) JBAS018210: Registering web context: /ejbca/doc

WSDL published to: file:/opt/jboss-as-7.1.1.Final/standalone/data/wsdl/ejbca.ear/ejbca-ws-ejb.jar/EjbcaWSService.wsdl

接下来从服务器上将 superadmin.p12 拷贝出来,导入浏览器,就可以访问管理页面了!

当然,按照我的经验,看到这里的人 99% 都是要被坑的,你应该是无法正常安装的。如果没成功的话,不要灰心,多试几次。我将上述过程整整重新执行了一天,才最终装好一个。然后因为要修改一些配置,又挂了。所以说,这玩意能不碰就不碰,我已经在开头警告过了。。。

使用 stunnel 加密原本不支持加密的连接

之前在国内的 TX 云主机上安装了 cow 作为连接国外 ss 的跳板。最近由于 Wifi 安全问题被各种关注,就想到 cow 本身是只支持 http 协议的。也就是说,我跟这个代理的任何通信理论上都能被同一 AP 下的其它机器截获。

为了解决这个问题,同时也作为某些公众 Wifi 禁止连接 VPN 的解决方案,我使用了 stunnel 来将 cow 变为支持 https 的代理服务器。

PS:之所以使用 cow 而不是其它的专业代理服务器,是因为在使用 cow 的时候可以无缝连上国外网站,无痛上 Google ,所以。。。

下面说说配置过程:

因为 stunnel 已经发布到了 epel 源中,所以如果你的 CentOS 添加了 epel 源的话,可以直接 yum install stunnel. 如果想自己编译也不困难,下载源码 ./configure && make && make install 即可。下面主要说说配置:

如果你是用的 epel 源的 stunnel ,你会发现安装包已经自动建立了 /etc/stunnel/ 目录,只不过里面啥都没有。所以我们要先创建配置文件:

vim /etc/stunnel/stunnel.conf

写入如下内容:

cert = /etc/stunnel/stunnel.pem
chroot = /var/run/stunnel
setuid = nobody
setgid = nobody
pid = /stunnel.pid
debug = 7
options = NO_SSLv2
fips = no
compression = zlib

[cow]
accept = 8080
connect = 127.0.0.1:7777

其中[cow]段可以多次重复,这样的话可以一个配置文件加密多个程序,使用端口号区分。
注意,fips = no 如果不加上的话会出现这个错误:

FIPS_mode_set: 2D06C06E: error:2D06C06E:FIPS routines:FIPS_module_mode_set:fingerprint does not match

接下来写一个启动脚本放到 /etc/init.d/ 中:

vim /etc/init.d/stunnel
#!/bin/bash
#
# Script to run stunnel in daemon mode at boot time.
#
# Check http://www.gaztronics.net/ for the
# most up-to-date version of this script.
#
# This script is realeased under the terms of the GPL.
# You can source a copy at:
# http://www.fsf.org/copyleft/copyleft.html
#
# Please feel free to modify the script to suite your own needs.
# I always welcome email feedback with suggestions for improvements.
# Please do not email for general support. I do not have time to answer
# personal help requests.

# Author: Gary Myers MIIE MBCS
# email: http://www.gaztronics.net/webform/
# Revision 1.0 - 4th March 2005

#====================================================================
# Run level information:
#
# chkconfig: 2345 99 99
# description: Secure Tunnel
# processname: stunnel
#
# Run "/sbin/chkconfig --add stunnel" to add the Run levels.
# This will setup the symlinks and set the process to run at boot.
#====================================================================

#====================================================================
# Paths and variables and system checks.

# Source function library (It's a Red Hat thing!)
. /etc/rc.d/init.d/functions

# Check that networking is up.
#
[ ${NETWORKING} ="yes" ] || exit 0

# Path to the executable.
#
SEXE=`which stunnel`

# Path to the configuration file.
#
CONF=/etc/stunnel/stunnel.conf

# Check the configuration file exists.
#
if [ ! -f $CONF ] ; then
  echo "The configuration file cannot be found!"
exit 0
fi

CHROOT=`grep '^chroot' /etc/stunnel/stunnel.conf | head -n 1 | sed 's/ //g' | awk -F= '{ print $2 }'`
PIDFILE=`grep '^pid' /etc/stunnel/stunnel.conf | head -n 1 | sed 's/ //g' | awk -F= '{ print $2 }'`
if [ -n "$CHROOT" ]; then
    PIDFILE=$CHROOT/$PIDFILE
fi

# Path to the lock file.
#
LOCK_FILE=/var/lock/subsys/stunnel

#====================================================================

#====================================================================
# Run controls:

prog=$"stunnel"

RETVAL=0

# Start stunnel as daemon.
#
start() {
  if [ -f $LOCK_FILE ]; then
    echo "stunnel is already running!"
    exit 0
  else
    echo -n $"Starting $prog: "
    $SEXE $CONF
  fi

  RETVAL=$?
  [ $RETVAL -eq 0 ] && success
  echo
  [ $RETVAL -eq 0 ] && touch $LOCK_FILE
  return $RETVAL
}


# Stop stunnel.
#
stop() {
  if [ ! -f $LOCK_FILE ]; then
    echo "stunnel is not running!"
    exit 0

  else

    echo -n $"Shutting down $prog: "
    killproc -p $PIDFILE stunnel
    RETVAL=$?
    [ $RETVAL -eq 0 ]
     rm -f $LOCK_FILE
    echo
    return $RETVAL

  fi
}

# See how we were called.
case "$1" in
   start)
  start
  ;;
   stop)
  stop
  ;;
   restart)
  stop
  start
  ;;
   condrestart)
  if [ -f $LOCK_FILE ]; then
     stop
     start
     RETVAL=$?
  fi
  ;;
   status)
  status -p $PIDFILE stunnel
  RETVAL=$?
  ;;
   *)
    echo $"Usage: $0 {start|stop|restart|condrestart|status}"
    RETVAL=1
esac

exit $RETVAL

保存之后不要忘了给执行权限。
接下来就要配置证书了。将你的证书、私钥、CA证书按照如下顺序合并:

cat server.crt server.key ca.crt >/etc/stunnel/stunnel.pem

然后因为大部分人的私钥都是明文的,所以要注意这个文件的权限。如果文件权限比较危险的话 stunnel 会有提示。

chmod 600 /etc/stunnel/stunnel.pem

最后就是创建 stunnel 需要的临时文件夹并赋予权限了。

mkdir -p /var/run/stunnel/
chown nobody:nobody /var/run/stunnel

这个用户和组按照 stunnel.conf 中所写的来授权。
大功告成!来运行一下吧:

service stunnel start

使用 netstat -ntlp 来看看是否正常开始监听端口。如果监听正常就没有问题啦~

博客正式开启全站强制SSL

由于 Google 宣即将在Chrome浏览器中全面将HTTP网站标记为不安全(http://www.chromium.org/Home/chromium-security/marking-http-as-non-secure),我很早就想将博客开启全站HTTPS了。不过由于我的主机带宽不够,而且地理位置是在香港,所以无法在开启全站HTTPS之后提供较快的图片下载速度。而国内的CDN支持HTTPS的又少的可怜,只好开启了后台HTTPS,但是前台页面都没有开启HTTPS。
今天收到邮件看到七牛云存储做活动,发布了海外加速服务,于是就顺手去看了一眼。没想到无意中发现七牛已经开始给CDN部署HTTPS了。虽然只能使用自定义域名,但是对我没有影响,因为我是使用WP Super Cache插件将博客页面中的资源文件的链接在输出的时候直接替换成CDN的链接的,所以终于可以真正的开启全站HTTPS了。
现在再访问我的博客,如果使用HTTP访问,会被强制302到HTTPS的链接。在这个页面里查看源文件的话可以看到,资源文件都是从
https://dn-maoxian.qbox.me/
这个域名下载的。这就是七牛云存储的CDN域名。有了这个,再也不用担心HTTPS的页面什么CSS都加载不了被浏览器直接Block啦~

附上我的七牛邀请链接:

https://portal.qiniu.com/signup?code=3l7i9c6vk7qky

PS:不过七牛不好的一点是想得到免费额度需要身份认证。。。不过。。。这是国内CDN的通病了。。。没办法。。。这个就要自己权衡了~

开源堡垒机GateOne的安装、配置笔记

因为内部临时需要这么一套系统,所以搜搜查查,搞定了系统部署,使用pam认证的配置。
系统初始化是使用CentOS 6.5 Mini x64版本。

首先exports http_proxy和https_proxy,做好上网准备。

其次查看下安装需求。
http://liftoff.github.io/GateOne/About/index.html#prerequisites

这里有相关的包下载:
https://github.com/liftoff/GateOne/downloads

yum install -y http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
yum update -y

yum install -y python-devel gcc dtach python-pip python-imaging python-kerberos
yum install -y https://github.com/downloads/liftoff/GateOne/tornado-2.4-1.noarch.rpm
cd /usr/local/src
git clone https://github.com/liftoff/GateOne.git

cd GateOne
python setup.py isntall

service gateone start
service gateone stop

vi /etc/gateone/conf.d/10server.conf

origins = [“x.x.x.x”]
address = “x.x.x.x”
https_redirect = True

vi /etc/gateone/conf.d/20authentication.conf
auth = “pam”
pam_realm = “AccessGateway1”
pam_service = “gateone”

vi /etc/sysconfig/iptables
增加80和443端口
service iptables reload

nohup python gateone.py &

在Safari下无法使用,报错如下:
The WebSocket connection was closed. Will attempt to reconnect every 5 seconds…
NOTE: Some web proxies do not work properly with WebSockets.

PC和Android中的Chrome正常。

vi /etc/pam.d/gateone
auth required pam_userdb.so db=/root/pam-test/login
account required pam_userdb.so db=/root/pam-test/login

https://github.com/liftoff/GateOne/issues/118
这里提到是PyPAM,别安装错了。

yum install git pam-devel pam PyPAM pam-devel

然后生成pam db:
vim login.txt
user1
user1passwd

该文件一行用户名一行密码。写好之后wq保存退出。
db_load -T -f login.txt -t hash login.db
然后pam认证需要使用的密码文件就生成好了。之后可以把login.txt删除避免被别人看到用户名密码。
至此GateOne安装完毕。

附:给GateOne添加SSL证书的办法:
修改server.conf
certificate = “/path/to/your/ssl.crt”
disable_ssl = False
ca_certs = “/path/to/your/ca.pem”
keyfile = “/path/to/your/ssl.key”
重新启动,GateOne就会使用你定义的证书来监听443端口了。这样在使用SSL访问的时候就不会出现证书错误了。

Word一键居中所有图片

新建一个宏,贴入如下代码,执行即可。如果文章中图片较多可能会卡顿。
Sub centerPictures()
Dim shpIn As InlineShape, shp As Shape
For Each shpIn In ActiveDocument.InlineShapes
shpIn.Select
Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter
Next shpIn
For Each shp In ActiveDocument.Shapes
shp.Select
Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter
Next shp
End Sub

For something that turns out to be super-easy, there was not one place on the web that I could find this information. I needed to programmatically center all images in a Word document using Visual Basic for Applications (VBA). I searched high and low, and while I could find how to loop through all images, I couldn’t find how to center them. Then I turned to the macro writer’s best friend: the macro recorder. Duh! :blush:

It actually took me longer to find a document with pictures than it did to record the macro, see what it did, add it to my loops (see below), and test it.

You’ll notice that there are two loops in the code. That is so that it picks up inline figures as well wrapped figures.