EOSIO MongoDB 插件系列:从 log 中找回丢失的插入记录

作者: UMU @ MEET.ONE 实验室

问题

当 MongoDB 因不可抗力故障,nodeos 重启后会丢失上次故障时正在插入的记录。

解决

nodeos 会将插入语句连同错误原因等信息一起写入 log,这给了我们手动修复丢失的机会。下面以 transaction_traces 为例,介绍修复流程。

1. 找出所有失败记录

1
grep 'mongo exception, trans_traces insert:' *.log > lost.txt

2. 从 log 生成 mongo script

1
2
3
4
5
6
echo 'print("++++");
var eos = db.getSiblingDB("EOS");' > lost.js

cat lost.txt | sed -n 's/.*, trans_traces insert: \(.*\), line 920, code.*/eos.transaction_traces.insert(\1)/p' >> lost.js

echo 'print("----");' >> lost.js

3. 导入 MongoDB

1
nohup mongo mongodb://$user:$password@127.0.0.1:$port/admin lost.js > lost.log

纯数字 EOS 账号

作者: UMU @ MEET.ONE 实验室

问题

2018 年最后一个工作日,智能合约开发小哥哥遇到一个奇怪的现象:某个账号给我们合约转账,在 EOS 浏览器上都可以找到记录,但用 cleos get table 在合约的 RAM 里找却找不到!

现象

了解具体情况后,注意到两个事实:

  1. 只有某个特定账号有问题,其它账号很正常。

  2. 那个有问题的账号是纯数字的。

这是 EOS 账号解析的问题,UMU 曾经给 EOS 提过一个相关的 issue:get_table_by_scope parameter lower_bound is NOT properly converted, cause enumeration dead loop #5824,里面有问题产生原因和解决方案。

分析

eosio::name 本质是一个 uint64_t 数字的 base32 编码,编码形式是为了方便人类记忆。举个例子:

shengxiaokai 本质上是 14075216089888066784 (0xc3553675c6a40ce0)

cleos get table 在解析账号时,兼容了这两种表达形式,所以 14075216089888066784shengxiaokai 是等价的。

但本身是纯数字的账号可就有歧义了,比如 313131313131 是当成一个 uint64_t 解释,还是当成 base32?很不巧,解析代码是优先当成 uint64_t 解释的。

解决方案

给纯数字 EOS 账号加上个空格后缀,比如 111122223333 可以改为 "111122223333 "

EOSIO 找出谁为我质押

作者: UMU @ MEET.ONE 实验室

问题

很多 EOS 浏览器都只能显示别人给我抵押了多少 EOS,但不能看到是哪个账号帮我抵押的。

分析

1. 看抵押的实现代码

eosio.contracts/eosio.system/src/delegate_bandwidth.cppdelegatebw 函数开始分析。

它调用了 changebw,其中的查表操作是这样的:

1
2
del_bandwidth_table     del_tbl( _self, from.value );
auto itr = del_tbl.find( receiver.value );

scope 是 from,而 from 就是要求的未知项,直接粉碎我们用这路线继续求解的可能。

2. 找交易记录

MEET.ONE 之前发布过几篇关于 MongoDB 插件的文章,这些积累为我们继续求解提供了很大便利。

直接在 Mongo Shell 里尝试:

1
2
use EOS
db.transaction_traces.findOne({"action_traces.act.account" : "eosio", "action_traces.act.name" : "delegatebw", "action_traces.act.data.receiver" : "shengxiaokai"})

执行之后,找到一条 trx_id 为 9bd50c0fd6f0e1d0ed4c6f5c6f873a33976955ff9dae2ac3eb16cb7e9a44d106 的交易记录,显示 1freeaccountshengxiaokai 抵押:

1
2
3
4
5
6
7
{
"from" : "1freeaccount",
"receiver" : "shengxiaokai",
"stake_net_quantity" : "0.0000 EOS",
"stake_cpu_quantity" : "0.5000 EOS",
"transfer" : 0
}

改进 EOSIO MongoDB 插件对分片集群的插入性能

作者: UMU @ MEET.ONE 实验室

问题

为了保证 MongoDB 服务器的容量足够应对未来发展,我们做了分片,但经过对比测试,发现每隔 15 分钟左右,nodeos 就会报错,并优雅退出。

查看了社区的 issues 发现有类似情况:mongodb shard: line 870, code 61, generic server error

解决

定位代码

反复测试发现,总是同一个地方抛出异常:

1
2
3
4
5
6
7
8
9
10
11
// insert action_traces
if( write_atraces ) {
try {
if( !bulk_action_traces.execute() ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail,
"Bulk action traces insert failed for transaction trace: ${id}", ("id", t->id) );
}
} catch( ... ) {
handle_mongo_exception( "action traces insert", __LINE__ );
}
}

插入数据的代码很多,但就这个地方报错,说明 action_traces 表有特殊性。

分析异同

action_traces 的 shard key 被定义为 _id,而其他没报错的表并不是 _id。

理论

批量插入时,_id 是有单调递增性的,根据官方文档
Avoid Monotonic Throttling,需要降低单调递增性,才能使批量插入均匀分散到各个 shard 上。

成果

(#6498) Fix cluster writes for mongo DB

EOSIO 的连续通胀率 4.879% 是怎么算出来的?

作者: UMU @ MEET.ONE 实验室

问题

eosio.contracts/eosio.system/src/producer_pay.cpp 中有这样一行代码:

1
const double   continuous_rate       = 0.04879;          // 5% annual rate

搜索一下,会得到这样的解释:

EOS是连续增发的模式,连续通胀率是 4.879%,年度通胀是 5%;

运用微积分的知识,可以推导出来,假设是增发的次数是无限多次,那么,连续通胀的情景下,所设置的连续通胀率就是 4.879%。

然而,并没有解释具体算法……

求解

  • 假设通胀率是“每日结算”的,记为 daily_rate,则:
1
2
3
(1 + daily_rate / 365) ^ 365 = 1 + annual_rate

注:这里的 ^ 表示幂,不是 XOR 运算。

那么计算 daily_rate 的公式为:

1
2
3
[365TH_ROOT(1 + annual_rate) - 1] * 365

注:365TH_ROOT 是开 365 次方

把 5% 带入,计算结果是:0.048793425246406,这个数值已经和 0.04879 基本一样了。

  • 但是“每日结算”并不够,接下来推到时时刻刻都在结算的情况。

问题本质:已知 annual_rate、(1 + continuous_rate / N) ^ N = 1 + annual_rate,求 continuous_rate 在 N 为无穷大时的解。

复习一下大学数学,马上就会发现 lim N->∞ (1 + x / N) ^ N 就是 e ^ x 的定义,所以:

1
continuous_rate = ln(1 + annual_rate)

把 5% 代入 annual_rate,continuous_rate = 0.048790164169432

参考

#1537 DAWN-651 ⁃ setting correct per-block “continuous inflation” so annual inflation is 5%

EOSIO 1.5.0 MongoDB 插件搭配 MongoDB 4.0.4

问题描述

在前文《为 EOSIO MongoDB 插件搭建高可用集群》中,我们使用了 MongoDB 4.0.4,如果直接配套 EOSIO 1.5 版本,MongoDB 插件用的 MongoDB C Driver 与 MongoDB 4.0.4 是不完全兼容的。

  • EOSIO 1.5 指定的 MongoDB 版本是 3.6.3;

  • MongoDB 4.0 的客户端需要 MongoDB C Driver 1.11.0,而 EOSIO 1.5 用的是 1.10.2。

参考:Release Notes for MongoDB 4.0

改进方案

修改 eos/scripts/eosio_build_${SYS_NAME}.sh,其中 SYS_NAME 是系统名字,以 macOS 为例,应该改的是 eos/scripts/eosio_build_darwin.sh

  • 把 mongo-c-driver 版本改到足够高,比如 1.13.0,即把脚本里的下载链接 https://github.com/mongodb/mongo-c-driver/releases/download/1.10.2/mongo-c-driver-1.10.2.tar.gz 改为 https://github.com/mongodb/mongo-c-driver/releases/download/1.13.0/mongo-c-driver-1.13.0.tar.gz

  • 把 mongo-cxx-driver 版本改到足够高,比如 3.4.0,可以直接把脚本里的 git clone https://github.com/mongodb/mongo-cxx-driver.git --branch releases/v3.3 --depth 1 改为 git clone https://github.com/mongodb/mongo-cxx-driver.git --branch releases/stable --depth 1

  • Ubuntu 操作参考:

1
2
3
4
5
6
7
8
9
10
11
12
sed -i 's/releases\/v3.3/releases\/stable/;s/1\.10\.2/1\.13\.0/g' scripts/eosio_build_ubuntu.sh

# 编译前
grep "Version:" /usr/local/lib/pkgconfig/libmongocxx-static.pc
Version: 3.3.2-pre

# 编译
./eosio_build.sh

# 编译后
grep "Version:" /usr/local/lib/pkgconfig/libmongocxx-static.pc
Version: 3.4.0

然后编译、安装 eos。

参考:

mongo-c-driver 1.13.0

MongoDB C++11 Driver 3.4.0

注意事项

以上方法不适用于 v1.7.0,新版 eos 已经使用新版 mongo-c-driver 和 MongoDB C++11 Driver,唯一需要改的是 eos/scripts/eosio_build.sh 的这行:

1
export MONGODB_VERSION=4.0.6 #3.6.3

为 EOSIO MongoDB 插件搭建高可用集群

选型

系统:CentOS7。 正像大部分国人喜欢用免费的 Windows 旗舰版,采用 RedHat 社区版,既有“企业级待遇”,又免费。实在是解决选择恐惧症必备良药……

MongoDB:4.0.4。 4.0 之前的版本不支持一些类型转换的函数,后期使用起来很麻烦。举个例子:

$toDate

New in version 4.0.

文件系统:XFS。 4.0 已经抛弃 MMAPv1 Storage Engine,官方文档强烈建议
WiredTiger Storage Engine
和 XFS 配套使用。

With the WiredTiger storage engine, using XFS is strongly recommended for data bearing nodes to avoid performance issues that may occur when using EXT4 with WiredTiger.

副本数:1。 数据可以很容易重新获取,丢失的代价不高,所以副本不是很重要(有钱请搞三副本)。另外,目前 nodeos 较常把数据弄脏,在它本身没高可用时,不宜对数据库投入太多成本。

机器配置:某云服务器一台。 16 Cores,256G RAM,启动盘 10G,额外八个 1T Disk。

1
2
3
4
5
6
7
8
9
10
11
12
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 10G 0 disk
└─sda1 8:1 0 10G 0 part /
sdb 8:16 0 1T 0 disk
sdc 8:32 0 1T 0 disk
sdd 8:48 0 1T 0 disk
sde 8:64 0 1T 0 disk
sdf 8:80 0 1T 0 disk
sdg 8:96 0 1T 0 disk
sdh 8:112 0 1T 0 disk
sdi 8:128 0 1T 0 disk

环境配置

1. 设置 SE Linux

安装过程中,若您需要 reboot 系统,则每次 reboot 之后都要做一次:

1
setenforce Permissive

2. 关闭 TPH

以下命令不是持久化改变,但比较容易说明改了啥,仅供参考:

1
2
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

根据 Disable Transparent Huge Pages (THP),真正使用的是:

1
2
3
4
5
6
7
8
9
mkdir -p /etc/tuned/no-thp

echo '[main]
include=virtual-guest

[vm]
transparent_hugepages=never' > /etc/tuned/no-thp/tuned.conf

tuned-adm profile no-thp

3. TCP 优化

以下命令不是持久化改变,但比较容易说明优化了啥,仅供参考:

1
2
3
echo 120 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 3 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 3 > /proc/sys/net/ipv4/tcp_orphan_retries

真正使用的是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FILE=/etc/sysctl.conf
cp $FILE ${FILE}_`date +%Y%m%d%H%M`

KEY=tcp_keepalive_time
VALUE=120

egrep "net.ipv4.$KEY" $FILE && sed -i -c "s/net\.ipv4\.$KEY.*/net\.ipv4\.$KEY = $VALUE/g" $FILE || echo "net.ipv4.$KEY = $VALUE" >> $FILE

VALUE=3
KEY=tcp_fin_timeout

egrep "net.ipv4.$KEY" $FILE && sed -i -c "s/net\.ipv4\.$KEY.*/net\.ipv4\.$KEY = $VALUE/g" $FILE || echo "net.ipv4.$KEY = $VALUE" >> $FILE

KEY=tcp_orphan_retries

egrep "net.ipv4.$KEY" $FILE && sed -i -c "s/net\.ipv4\.$KEY.*/net\.ipv4\.$KEY = $VALUE/g" $FILE || echo "net.ipv4.$KEY = $VALUE" >> $FILE

sysctl -p 2>/tmp/sysctl.tmp

安装步骤

1. 全局设置

1
2
3
4
5
6
7
8
PASSWORD=MEETONE_FAKE_PASSWORD

PREFIX=/disk
BIND_IP=10.140.0.10
D_PORT=17089
CS_PORT=17088
S_PORT=17087
NUM_SHARD=7

2. 防火墙例外

1
semanage port -a -t mongod_port_t -p tcp 17087-17095

3. 分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
yum install -y xfsprogs

function InitDisk {
umount ${PREFIX}*
sed -i "s:^LABEL=${PREFIX}:#LABEL=${PREFIX}:" /etc/fstab
i=0
for drv in {b..i}; do
/sbin/parted /dev/sd"$drv" -s mklabel gpt mkpart primary 2048s 100%
sleep 1
mkfs.xfs -f -b size=4096 -d su=64k,sw=4,agcount=2000 /dev/sd"$drv"1
xfs_admin -L ${PREFIX}$i /dev/sd"$drv"1
mkdir -p ${PREFIX}$i
echo "LABEL=${PREFIX}$i ${PREFIX}$i xfs rw,noatime,nodiratime,allocsize=16M,inode64,logbsize=256k,delaylog,nobarrier,nolargeio,swalloc 0 0" >> /etc/fstab

i=$[i+1]
done
mount -a
}

InitDisk

4. 安装 MongoDB Community Edition

参考官网的安装文档:Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux

1
2
3
4
5
6
7
8
9
10
echo '[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc' > /etc/yum.repos.d/mongodb-org-4.0.repo

yum install -y mongodb-org

echo 'exclude=mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools' >> /etc/yum.conf

5. 初始化数据库目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function InitDir {
rm -rf ${PREFIX}0/mongod_conf_data ${PREFIX}0/mongo_log
for ((i = 1; i <= $NUM_SHARD; ++i)); do
rm -rf ${PREFIX}$i/mongo*
done

mkdir -p ${PREFIX}0/mongod_conf_data
chown -R mongod. ${PREFIX}0/mongod_conf_data
mkdir -p ${PREFIX}0/mongo_log
chown -R mongod. ${PREFIX}0/mongo_log
for ((i = 1; i <= $NUM_SHARD; ++i)); do
mkdir -p ${PREFIX}$i/mongod_data
chown mongod. ${PREFIX}$i/mongo*
done
}

InitDir

6. 配置 MongoD 分片服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
function CreateShardConfig {
for ((i = 1; i <= $NUM_SHARD; ++i)); do
echo "shardsvr=true
replSet=shard$i
bind_ip=127.0.0.1,$BIND_IP
port=$[D_PORT+i-1]
dbpath=${PREFIX}$i/mongod_data
logpath=${PREFIX}0/mongo_log/shard$i.log
pidfilepath=/var/run/mongodb/mongod_shard$i.pid
logappend=true
logRotate=reopen
fork=true
wiredTigerCacheSizeGB=10
#keyFile=/etc/mongodb-keyfile
#verbose=true
directoryperdb=true
wiredTigerDirectoryForIndexes=true" > /etc/mongod_shard$i.conf
chown mongod. /etc/mongod_shard$i.conf
done
}

function CreateShardService {
for ((i = 1; i <= $NUM_SHARD; ++i)); do
echo "[Unit]
Description=MongoD
After=network.target
Documentation=https://docs.mongodb.org/manual

[Service]
User=mongod
Group=mongod
Environment=\"OPTIONS=-f /etc/mongod_shard$i.conf\"
EnvironmentFile=-/etc/sysconfig/mongod
ExecStart=/usr/bin/mongod \$OPTIONS
ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb
ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb
ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb
PermissionsStartOnly=true
PIDFile=/var/run/mongodb/mongod_shard$i.pid
Type=forking
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings

[Install]
WantedBy=multi-user.target" > /usr/lib/systemd/system/mongod_shard$i.service
done

systemctl daemon-reload
}

function InitShard {
SH=/tmp/mongod_shard.sh
echo "" > $FILE
for ((i = 1; i <= $NUM_SHARD; ++i)); do
PORT=$[D_PORT+i-1]
echo "echo \"rs.initiate({_id: 'shard$i', members:[{_id: 0, host: '$BIND_IP:$PORT'}]})\" | mongo --host 127.0.0.1 --port $PORT" >> $SH
done
bash $SH
}

function CreateShardUser {
JS=/tmp/mongod_shard.js

echo "use admin;
db.createUser({ \"user\": \"MongoAdmin\", \"pwd\": \"${PASSWORD}\", \"roles\": [\"root\"]});
cfg = rs.conf();
cfg.members[0].priority = 10;
rs.reconfig(cfg);" > $JS

for ((i = 1; i <= $NUM_SHARD; ++i)); do
mongo --port $[CS_PORT+i-1] < $JS
done
}

CreateShardConfig
CreateShardService
for ((i = 1; i <= $NUM_SHARD; ++i)); do systemctl restart mongod_shard$i.service; done
InitShard
CreateShardUser

7. 配置 MongDB Config Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
function CreateConfigServerConfig {
FILE=/etc/mongod.conf

echo "replSet=csReplSet
configsvr=true
bind_ip=127.0.0.1,$BIND_IP
port=$CS_PORT
dbpath=${PREFIX}0/mongod_conf_data
logpath=${PREFIX}0/mongo_log/config.log
pidfilepath=/var/run/mongodb/mongod.pid
logappend=true
logRotate=reopen
fork=true
#keyFile=/etc/mongodb-keyfile" > $FILE

chown mongod. $FILE
}

function CreateConfigServerService {
echo '[Unit]
Description=MongoCS
After=network.target
Documentation=https://docs.mongodb.org/manual

[Service]
User=mongod
Group=mongod
Environment="OPTIONS=-f /etc/mongod.conf"
EnvironmentFile=-/etc/sysconfig/mongod
ExecStart=/usr/bin/mongod $OPTIONS
ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb
ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb
ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb
PermissionsStartOnly=true
PIDFile=/var/run/mongodb/mongod.pid
Type=forking
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings

[Install]
WantedBy=multi-user.target' > /usr/lib/systemd/system/mongod.service

systemctl daemon-reload
}

CreateConfigServerConfig
CreateConfigServerService

systemctl restart mongod.service

sleep 5
echo "rs.initiate({_id: 'csReplSet', members:[{_id: 0, host: '$BIND_IP:$CS_PORT'}]})" | mongo --port $CS_PORT
echo "use admin;
db.createUser({ \"user\": \"MongoAdmin\", \"pwd\": \"${PASSWORD}\", \"roles\": [\"root\"]});" | mongo --port $CS_PORT

8. 配置 MongS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
function CreateMongoSConfig {
FILE=/etc/mongos.conf

echo "configdb=csReplSet/$BIND_IP:$CS_PORT
bind_ip_all=true
port=17087
logpath=${PREFIX}0/mongos_log/mongos.log
pidfilepath=/var/run/mongodb/mongos.pid
logappend=true
logRotate=reopen
fork=true
#keyFile=/etc/mongodb-keyfile" > $FILE

chown mongod. $FILE

mkdir -p ${PREFIX}0/mongos_log
chown -R mongod. ${PREFIX}0/mongos_log
}

function CreateMongoSService {
echo '[Unit]
Description=MongoS
After=network.target
Documentation=https://docs.mongodb.org/manual

[Service]
User=mongod
Group=mongod
Environment="OPTIONS=-f /etc/mongos.conf"
EnvironmentFile=-/etc/sysconfig/mongod
ExecStart=/usr/bin/mongos $OPTIONS
ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb
ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb
ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb
PermissionsStartOnly=true
PIDFile=/var/run/mongodb/mongos.pid
Type=forking
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings

[Install]
WantedBy=multi-user.target' > /usr/lib/systemd/system/mongos.service

systemctl daemon-reload
}

function AddShards {
FILE=/tmp/mongo_add_shards.js
echo "use admin;" > $FILE
for ((i = 1; i <= $NUM_SHARD; ++i)); do
echo "db.runCommand({addshard:\"shard$i/$BIND_IP:$[D_PORT+i-1]\"});" >> $FILE
done

mongo --port $S_PORT < $FILE
}

CreateMongoSConfig
CreateMongoSService

systemctl restart mongos.service

AddShards

9. 【可选】配置 keyfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function ConfigKeyfile {
FILE=/etc/mongodb-keyfile
openssl rand -base64 745 > $FILE
chown mongod. $FILE
chmod 600 $FILE

grep -P '^#keyFile' /etc/mongod*.conf && sed -i 's/#keyFile/keyFile/g' /etc/mongod*.conf

grep -P '^#keyFile' /etc/mongos.conf && sed -i 's/#keyFile/keyFile/g' /etc/mongos.conf
}

function RestartMongo {
systemctl restart mongod.service
for ((i = 1; i <= $NUM_SHARD; ++i)); do
systemctl restart mongod_shard$i.service;
done
systemctl restart mongos.service
}

ConfigKeyfile
RestartMongo

10. 【可选】配置集合和创建索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use EOS
db.action_traces.createIndex({"act.account": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"act.name": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"act.data.receiver": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"act.data.from": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"act.data.to": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"act.data.name": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"act.data.voter": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"act.authorization.actor": 1, "_id":1},{background: true, sparse: true})
db.action_traces.createIndex({"receipt.receiver": 1, "_id":1},{background: true, sparse: true})

db.action_traces.createIndex({"block_num": 1, "_id":1},{background: true})
db.action_traces.createIndex({"block_time": 1, "_id":1},{background: true})

db.transaction_traces.createIndex({"id": 1, "_id":1},{background: true})

sh.enableSharding("EOS")
sh.shardCollection("EOS.action_traces", {"_id" : 1}, true)
sh.shardCollection("EOS.transaction_traces", {"_id" : 1}, true)

11. 【可选】安装 EOSIO 1.5

1
2
wget https://github.com/eosio/eos/releases/download/v1.5.0/eosio-1.5.0-1.el7.x86_64.rpm
rpm -ivh ./eosio-1.5.0-1.el7.x86_64.rpm --nodeps

为编译 EOSIO 降级 boost 到 1.67

问题

目前 EOSIO 1.5 依赖的 boost 版本为 1.67,但最新的 boost 是 1.68,如果不小心用 brew upgrade 把 boost 升级到最新,则 EOSIO 代码将无法顺利编译。

解决

不必删除 1.68 版本,当之前安装过 1.67,再安装 1.68 时,其实两者是同时存在的,只是系统目录下的链接是指向最新版本而已。只要把链接改回 1.67 即可。

以下脚本适用于 macOS Mojave 系统,其它系统请自行做相应修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
ln -s /usr/local/include/boost /usr/local/Cellar/boost/1.67.0_1/include/boost 

ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_atomic-mt.a /usr/local/lib/libboost_atomic-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_atomic-mt.dylib /usr/local/lib/libboost_atomic-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono-mt.a /usr/local/lib/libboost_chrono-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono-mt.dylib /usr/local/lib/libboost_chrono-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono.a /usr/local/lib/libboost_chrono.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono.dylib /usr/local/lib/libboost_chrono.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container-mt.a /usr/local/lib/libboost_container-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container-mt.dylib /usr/local/lib/libboost_container-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container.a /usr/local/lib/libboost_container.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container.dylib /usr/local/lib/libboost_container.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_context-mt.a /usr/local/lib/libboost_context-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_context-mt.dylib /usr/local/lib/libboost_context-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract-mt.a /usr/local/lib/libboost_contract-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract-mt.dylib /usr/local/lib/libboost_contract-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract.a /usr/local/lib/libboost_contract.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract.dylib /usr/local/lib/libboost_contract.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine-mt.a /usr/local/lib/libboost_coroutine-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine-mt.dylib /usr/local/lib/libboost_coroutine-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine.a /usr/local/lib/libboost_coroutine.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine.dylib /usr/local/lib/libboost_coroutine.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time-mt.a /usr/local/lib/libboost_date_time-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time-mt.dylib /usr/local/lib/libboost_date_time-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time.a /usr/local/lib/libboost_date_time.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time.dylib /usr/local/lib/libboost_date_time.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_exception-mt.a /usr/local/lib/libboost_exception-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_exception.a /usr/local/lib/libboost_exception.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_fiber-mt.a /usr/local/lib/libboost_fiber-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_fiber-mt.dylib /usr/local/lib/libboost_fiber-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem-mt.a /usr/local/lib/libboost_filesystem-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem-mt.dylib /usr/local/lib/libboost_filesystem-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem.a /usr/local/lib/libboost_filesystem.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem.dylib /usr/local/lib/libboost_filesystem.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph-mt.a /usr/local/lib/libboost_graph-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph-mt.dylib /usr/local/lib/libboost_graph-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph.a /usr/local/lib/libboost_graph.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph.dylib /usr/local/lib/libboost_graph.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams-mt.a /usr/local/lib/libboost_iostreams-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams-mt.dylib /usr/local/lib/libboost_iostreams-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams.a /usr/local/lib/libboost_iostreams.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams.dylib /usr/local/lib/libboost_iostreams.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_locale-mt.a /usr/local/lib/libboost_locale-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_locale-mt.dylib /usr/local/lib/libboost_locale-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log-mt.a /usr/local/lib/libboost_log-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log-mt.dylib /usr/local/lib/libboost_log-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log.a /usr/local/lib/libboost_log.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log.dylib /usr/local/lib/libboost_log.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup-mt.a /usr/local/lib/libboost_log_setup-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup-mt.dylib /usr/local/lib/libboost_log_setup-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup.a /usr/local/lib/libboost_log_setup.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup.dylib /usr/local/lib/libboost_log_setup.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99-mt.a /usr/local/lib/libboost_math_c99-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99-mt.dylib /usr/local/lib/libboost_math_c99-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99.a /usr/local/lib/libboost_math_c99.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99.dylib /usr/local/lib/libboost_math_c99.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f-mt.a /usr/local/lib/libboost_math_c99f-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f-mt.dylib /usr/local/lib/libboost_math_c99f-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f.a /usr/local/lib/libboost_math_c99f.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f.dylib /usr/local/lib/libboost_math_c99f.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l-mt.a /usr/local/lib/libboost_math_c99l-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l-mt.dylib /usr/local/lib/libboost_math_c99l-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l.a /usr/local/lib/libboost_math_c99l.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l.dylib /usr/local/lib/libboost_math_c99l.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1-mt.a /usr/local/lib/libboost_math_tr1-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1-mt.dylib /usr/local/lib/libboost_math_tr1-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1.a /usr/local/lib/libboost_math_tr1.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1.dylib /usr/local/lib/libboost_math_tr1.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f-mt.a /usr/local/lib/libboost_math_tr1f-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f-mt.dylib /usr/local/lib/libboost_math_tr1f-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f.a /usr/local/lib/libboost_math_tr1f.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f.dylib /usr/local/lib/libboost_math_tr1f.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l-mt.a /usr/local/lib/libboost_math_tr1l-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l-mt.dylib /usr/local/lib/libboost_math_tr1l-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l.a /usr/local/lib/libboost_math_tr1l.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l.dylib /usr/local/lib/libboost_math_tr1l.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor-mt.a /usr/local/lib/libboost_prg_exec_monitor-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor-mt.dylib /usr/local/lib/libboost_prg_exec_monitor-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor.a /usr/local/lib/libboost_prg_exec_monitor.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor.dylib /usr/local/lib/libboost_prg_exec_monitor.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options-mt.a /usr/local/lib/libboost_program_options-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options-mt.dylib /usr/local/lib/libboost_program_options-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options.a /usr/local/lib/libboost_program_options.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options.dylib /usr/local/lib/libboost_program_options.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random-mt.a /usr/local/lib/libboost_random-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random-mt.dylib /usr/local/lib/libboost_random-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random.a /usr/local/lib/libboost_random.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random.dylib /usr/local/lib/libboost_random.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex-mt.a /usr/local/lib/libboost_regex-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex-mt.dylib /usr/local/lib/libboost_regex-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex.a /usr/local/lib/libboost_regex.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex.dylib /usr/local/lib/libboost_regex.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization-mt.a /usr/local/lib/libboost_serialization-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization-mt.dylib /usr/local/lib/libboost_serialization-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization.a /usr/local/lib/libboost_serialization.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization.dylib /usr/local/lib/libboost_serialization.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals-mt.a /usr/local/lib/libboost_signals-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals-mt.dylib /usr/local/lib/libboost_signals-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals.a /usr/local/lib/libboost_signals.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals.dylib /usr/local/lib/libboost_signals.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line-mt.a /usr/local/lib/libboost_stacktrace_addr2line-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line-mt.dylib /usr/local/lib/libboost_stacktrace_addr2line-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line.a /usr/local/lib/libboost_stacktrace_addr2line.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line.dylib /usr/local/lib/libboost_stacktrace_addr2line.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic-mt.a /usr/local/lib/libboost_stacktrace_basic-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic-mt.dylib /usr/local/lib/libboost_stacktrace_basic-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic.a /usr/local/lib/libboost_stacktrace_basic.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic.dylib /usr/local/lib/libboost_stacktrace_basic.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop-mt.a /usr/local/lib/libboost_stacktrace_noop-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop-mt.dylib /usr/local/lib/libboost_stacktrace_noop-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop.a /usr/local/lib/libboost_stacktrace_noop.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop.dylib /usr/local/lib/libboost_stacktrace_noop.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system-mt.a /usr/local/lib/libboost_system-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system-mt.dylib /usr/local/lib/libboost_system-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system.a /usr/local/lib/libboost_system.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system.dylib /usr/local/lib/libboost_system.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_test_exec_monitor-mt.a /usr/local/lib/libboost_test_exec_monitor-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_test_exec_monitor.a /usr/local/lib/libboost_test_exec_monitor.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_thread-mt.a /usr/local/lib/libboost_thread-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_thread-mt.dylib /usr/local/lib/libboost_thread-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer-mt.a /usr/local/lib/libboost_timer-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer-mt.dylib /usr/local/lib/libboost_timer-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer.a /usr/local/lib/libboost_timer.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer.dylib /usr/local/lib/libboost_timer.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure-mt.a /usr/local/lib/libboost_type_erasure-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure-mt.dylib /usr/local/lib/libboost_type_erasure-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure.a /usr/local/lib/libboost_type_erasure.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure.dylib /usr/local/lib/libboost_type_erasure.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework-mt.a /usr/local/lib/libboost_unit_test_framework-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework-mt.dylib /usr/local/lib/libboost_unit_test_framework-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework.a /usr/local/lib/libboost_unit_test_framework.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework.dylib /usr/local/lib/libboost_unit_test_framework.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wave-mt.a /usr/local/lib/libboost_wave-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wave-mt.dylib /usr/local/lib/libboost_wave-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization-mt.a /usr/local/lib/libboost_wserialization-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization-mt.dylib /usr/local/lib/libboost_wserialization-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization.a /usr/local/lib/libboost_wserialization.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization.dylib /usr/local/lib/libboost_wserialization.dylib