为什么要分析安装脚本
对于初学者,很多文档都是直接运行该安装脚本,就可以自动化部署Fabric程序,虽然表面上针对小白比较友好,不需要自己下载源码进行编译,但是很多资源都是国外的,下载速度缓慢我也是饱受折磨。下面分析一下安装脚本,有助于我们更加深入理解Fabric架构,同时分析安装逻辑。修改脚本方便部署。
安装脚本在哪里
我们以fabric1.4.8为例进行分析。相关github上面的链接如下。我们发现官方脚本不好用,下载非常缓慢,
https://github.com/hyperledger/fabric/blob/v1.4.8/scripts/bootstrap.sh
安装逻辑是什么
下面是安装脚本的基本逻辑框架代码。接下来我们一点点分析。
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# if version not passed in, default to latest released version
export VERSION=1.4.8
# if ca version not passed in, default to latest released version
export CA_VERSION=1.4.7
# current version of thirdparty images (couchdb, kafka and zookeeper) released
export THIRDPARTY_IMAGE_VERSION=0.4.21
export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')")
export MARCH=$(uname -m)
printHelp() {
}
dockerFabricPull() {
}
dockerThirdPartyImagesPull() {
}
dockerCaPull() {
}
samplesInstall() {
}
# Incrementally downloads the .tar.gz file locally first, only decompressing it
# after the download is complete. This is slower than binaryDownload() but
# allows the download to be resumed.
binaryIncrementalDownload() {
}
# This will attempt to download the .tar.gz all at once, but will trigger the
# binaryIncrementalDownload() function upon a failure, allowing for resume
# if there are network failures.
binaryDownload() {
}
dockerInstall() {
}
DOCKER=true
SAMPLES=true
BINARIES=true
# Parse commandline args pull out
# version and/or ca-version strings first
if [ ! -z "$1" -a ${1:0:1} != "-" ]; then
VERSION=$1;shift
if [ ! -z "$1" -a ${1:0:1} != "-" ]; then
CA_VERSION=$1;shift
if [ ! -z "$1" -a ${1:0:1} != "-" ]; then
THIRDPARTY_IMAGE_VERSION=$1;shift
fi
fi
fi
# prior to 1.2.0 architecture was determined by uname -m
if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then
export FABRIC_TAG=${MARCH}-${VERSION}
export CA_TAG=${MARCH}-${CA_VERSION}
export THIRDPARTY_TAG=${MARCH}-${THIRDPARTY_IMAGE_VERSION}
else
# starting with 1.2.0, multi-arch images will be default
: ${CA_TAG:="$CA_VERSION"}
: ${FABRIC_TAG:="$VERSION"}
: ${THIRDPARTY_TAG:="$THIRDPARTY_IMAGE_VERSION"}
fi
BINARY_FILE=hyperledger-fabric-${ARCH}-${VERSION}.tar.gz
CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${CA_VERSION}.tar.gz
# then parse opts
while getopts "h?dsb" opt; do
case "$opt" in
h|\?)
printHelp
exit 0
;;
d) DOCKER=false
;;
s) SAMPLES=false
;;
b) BINARIES=false
;;
esac
done
if [ "$SAMPLES" == "true" ]; then
echo
echo "Installing hyperledger/fabric-samples repo"
echo
samplesInstall
fi
if [ "$BINARIES" == "true" ]; then
echo
echo "Installing Hyperledger Fabric binaries"
echo
binariesInstall
fi
if [ "$DOCKER" == "true" ]; then
echo
echo "Installing Hyperledger Fabric docker images"
echo
dockerInstall
fi
和传统编程语言一样,此脚本首先定义了一下全局变量,同时通过if判断逻辑,执行先关函数,进行环境的部署,先关源码的下载。
逐一进行分析
首先看的肯定是帮助命令。
printHelp() {
echo "Usage: bootstrap.sh [version [ca_version [thirdparty_version]]] [options]"
echo
echo "options:"
echo "-h : this help"
echo "-d : bypass docker image download"
echo "-s : bypass fabric-samples repo clone"
echo "-b : bypass download of platform-specific binaries"
echo
echo "e.g. bootstrap.sh 1.4.8 -s"
echo "would download docker images and binaries for version 1.4.8"
}
我们可以看出,此脚本主要执行三部分功能,第一下载docker镜像,第二下载fabric-samples官方案例(为了更加方便的了解fabric构建项目),第三下载平台二进制文件。并且可以指定下载的版本。例如:1.4.8。同时可以参数选择不下载那一部分。代码最前面导入了相关变量export VERSION=1.4.8
、export CA_VERSION=1.4.7
、export THIRDPARTY_IMAGE_VERSION=0.4.21
。默认使用的是这些参数。
首先是逻辑框架
前面默认给出的变量值都是true,通过判断参数值,执行相关功能。samplesInstall
、binariesInstall
,dockerInstall
if [ "$SAMPLES" == "true" ]; then
echo
echo "Installing hyperledger/fabric-samples repo"
echo
samplesInstall
fi
if [ "$BINARIES" == "true" ]; then
echo
echo "Installing Hyperledger Fabric binaries"
echo
binariesInstall
fi
if [ "$DOCKER" == "true" ]; then
echo
echo "Installing Hyperledger Fabric docker images"
echo
dockerInstall
fi
dockerInstall
我们可以看到下载docker镜像,主要执行dockerFabricPull ${FABRIC_TAG}
dockerCaPull ${CA_TAG}
dockerThirdPartyImagesPull ${THIRDPARTY_TAG}
源文件无需更改,就可以执行。
这部分我们可以配置正确的docker国内加速源进行加速。不做过多的介绍。
dockerInstall() {
which docker >& /dev/null
NODOCKER=$?
if [ "${NODOCKER}" == 0 ]; then
echo "===> Pulling fabric Images"
dockerFabricPull ${FABRIC_TAG}
echo "===> Pulling fabric ca Image"
dockerCaPull ${CA_TAG}
echo "===> Pulling thirdparty docker images"
dockerThirdPartyImagesPull ${THIRDPARTY_TAG}
echo
echo "===> List out hyperledger docker images"
docker images | grep hyperledger*
else
echo "========================================================="
echo "Docker not installed, bypassing download of Fabric images"
echo "========================================================="
fi
}
dockerFabricPull() {
local FABRIC_TAG=$1
for IMAGES in peer orderer ccenv javaenv tools; do
echo "==> FABRIC IMAGE: $IMAGES"
echo
docker pull hyperledger/fabric-$IMAGES:$FABRIC_TAG
docker tag hyperledger/fabric-$IMAGES:$FABRIC_TAG hyperledger/fabric-$IMAGES
done
}
dockerCaPull() {
local CA_TAG=$1
echo "==> FABRIC CA IMAGE"
echo
docker pull hyperledger/fabric-ca:$CA_TAG
docker tag hyperledger/fabric-ca:$CA_TAG hyperledger/fabric-ca
}
dockerThirdPartyImagesPull() {
local THIRDPARTY_TAG=$1
for IMAGES in couchdb kafka zookeeper; do
echo "==> THIRDPARTY DOCKER IMAGE: $IMAGES"
echo
docker pull hyperledger/fabric-$IMAGES:$THIRDPARTY_TAG
docker tag hyperledger/fabric-$IMAGES:$THIRDPARTY_TAG hyperledger/fabric-$IMAGES
done
}
binariesInstall
这里面需要修改的地方是binaryDownload
函数,可以看出官方给出的下载链接为国外地址并且已经不在维护,也就是执行此脚本最缓慢的原因之一。https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric/
A
R
C
H
−
{ARCH}-
ARCH−{VERSION}/${BINARY_FILE}
此链接已经不在维护,所以要更换。如果想更快,使用https://hub.fastgit.org 加速github网站。进行下载
binariesInstall() {
echo "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries"
# wget https://hub.fastgit.org/hyperledger/fabric/releases/download/v1.4.8/hyperledger-fabric-linux-amd64-1.4.8.tar.gz
binaryDownload ${BINARY_FILE} https://hub.fastgit.org/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}
if [ $? -eq 22 ]; then
echo
echo "------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----"
echo
fi
echo "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary"
binaryDownload ${CA_BINARY_FILE} https://hub.fastgit.org/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}
if [ $? -eq 22 ]; then
echo
echo "------> ${CA_TAG} fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----"
echo
fi
}
binaryDownload() {
local BINARY_FILE=$1
local URL=$2
echo "===> Downloading: " ${URL}
# Check if a previous failure occurred and the file was partially downloaded
if [ -e ${BINARY_FILE} ]; then
echo "==> Partial binary file found. Resuming download..."
binaryIncrementalDownload ${BINARY_FILE} ${URL}
else
curl -L --retry 5 --retry-delay 3 ${URL} | tar xz || rc=$?
if [ ! -z "$rc" ]; then
echo "==> There was an error downloading the binary file. Switching to incremental download."
echo "==> Downloading file..."
binaryIncrementalDownload ${BINARY_FILE} ${URL}
else
echo "==> Done."
fi
fi
}
samplesInstall
更换国内源,使用码云的镜像,进行加速下载fabric-samples。
samplesInstall() {
# clone (if needed) hyperledger/fabric-samples and checkout corresponding
# version to the binaries and docker images to be downloaded
if [ -d first-network ]; then
# if we are in the fabric-samples repo, checkout corresponding version
echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
git checkout v${VERSION}
elif [ -d fabric-samples ]; then
# if fabric-samples repo already cloned and in current directory,
# cd fabric-samples and checkout corresponding version
echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
cd fabric-samples && git checkout v${VERSION}
else
echo "===> Cloning hyperledger/fabric-samples repo and checkout v${VERSION}"
# git clone -b master https://github.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
git clone -b master https://gitee.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
fi
}
将上面修改完成之后完整的bootstrap.sh代码。
bootstrap.sh
通过替换和修改源,最终实现加速效果。如果不想了解上述过程,就直接复制粘贴下面代码即可。
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# if version not passed in, default to latest released version
export VERSION=1.4.8
# if ca version not passed in, default to latest released version
export CA_VERSION=1.4.7
# current version of thirdparty images (couchdb, kafka and zookeeper) released
export THIRDPARTY_IMAGE_VERSION=0.4.21
export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')")
export MARCH=$(uname -m)
printHelp() {
echo "Usage: bootstrap.sh [version [ca_version [thirdparty_version]]] [options]"
echo
echo "options:"
echo "-h : this help"
echo "-d : bypass docker image download"
echo "-s : bypass fabric-samples repo clone"
echo "-b : bypass download of platform-specific binaries"
echo
echo "e.g. bootstrap.sh 1.4.8 -s"
echo "would download docker images and binaries for version 1.4.8"
}
dockerFabricPull() {
local FABRIC_TAG=$1
for IMAGES in peer orderer ccenv javaenv tools; do
echo "==> FABRIC IMAGE: $IMAGES"
echo
docker pull hyperledger/fabric-$IMAGES:$FABRIC_TAG
docker tag hyperledger/fabric-$IMAGES:$FABRIC_TAG hyperledger/fabric-$IMAGES
done
}
dockerThirdPartyImagesPull() {
local THIRDPARTY_TAG=$1
for IMAGES in couchdb kafka zookeeper; do
echo "==> THIRDPARTY DOCKER IMAGE: $IMAGES"
echo
docker pull hyperledger/fabric-$IMAGES:$THIRDPARTY_TAG
docker tag hyperledger/fabric-$IMAGES:$THIRDPARTY_TAG hyperledger/fabric-$IMAGES
done
}
dockerCaPull() {
local CA_TAG=$1
echo "==> FABRIC CA IMAGE"
echo
docker pull hyperledger/fabric-ca:$CA_TAG
docker tag hyperledger/fabric-ca:$CA_TAG hyperledger/fabric-ca
}
samplesInstall() {
# clone (if needed) hyperledger/fabric-samples and checkout corresponding
# version to the binaries and docker images to be downloaded
if [ -d first-network ]; then
# if we are in the fabric-samples repo, checkout corresponding version
echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
git checkout v${VERSION}
elif [ -d fabric-samples ]; then
# if fabric-samples repo already cloned and in current directory,
# cd fabric-samples and checkout corresponding version
echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
cd fabric-samples && git checkout v${VERSION}
else
echo "===> Cloning hyperledger/fabric-samples repo and checkout v${VERSION}"
git clone -b master https://gitee.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
fi
}
# Incrementally downloads the .tar.gz file locally first, only decompressing it
# after the download is complete. This is slower than binaryDownload() but
# allows the download to be resumed.
binaryIncrementalDownload() {
local BINARY_FILE=$1
local URL=$2
curl -f -s -C - ${URL} -o ${BINARY_FILE} || rc=$?
# Due to limitations in the current Nexus repo:
# curl returns 33 when there's a resume attempt with no more bytes to download
# curl returns 2 after finishing a resumed download
# with -f curl returns 22 on a 404
if [ "$rc" = 22 ]; then
# looks like the requested file doesn't actually exist so stop here
return 22
fi
if [ -z "$rc" ] || [ $rc -eq 33 ] || [ $rc -eq 2 ]; then
# The checksum validates that RC 33 or 2 are not real failures
echo "==> File downloaded. Verifying the md5sum..."
localMd5sum=$(md5sum ${BINARY_FILE} | awk '{print $1}')
remoteMd5sum=$(curl -s ${URL}.md5)
if [ "$localMd5sum" == "$remoteMd5sum" ]; then
echo "==> Extracting ${BINARY_FILE}..."
tar xzf ./${BINARY_FILE} --overwrite
echo "==> Done."
rm -f ${BINARY_FILE} ${BINARY_FILE}.md5
else
echo "Download failed: the local md5sum is different from the remote md5sum. Please try again."
rm -f ${BINARY_FILE} ${BINARY_FILE}.md5
exit 1
fi
else
echo "Failure downloading binaries (curl RC=$rc). Please try again and the download will resume from where it stopped."
exit 1
fi
}
# This will attempt to download the .tar.gz all at once, but will trigger the
# binaryIncrementalDownload() function upon a failure, allowing for resume
# if there are network failures.
binaryDownload() {
local BINARY_FILE=$1
local URL=$2
echo "===> Downloading: " ${URL}
# Check if a previous failure occurred and the file was partially downloaded
if [ -e ${BINARY_FILE} ]; then
echo "==> Partial binary file found. Resuming download..."
binaryIncrementalDownload ${BINARY_FILE} ${URL}
else
curl -L --retry 5 --retry-delay 3 ${URL} | tar xz || rc=$?
if [ ! -z "$rc" ]; then
echo "==> There was an error downloading the binary file. Switching to incremental download."
echo "==> Downloading file..."
binaryIncrementalDownload ${BINARY_FILE} ${URL}
else
echo "==> Done."
fi
fi
}
binariesInstall() {
echo "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries"
# wget https://hub.fastgit.org/hyperledger/fabric/releases/download/v1.4.8/hyperledger-fabric-linux-amd64-1.4.8.tar.gz
binaryDownload ${BINARY_FILE} https://hub.fastgit.org/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}
if [ $? -eq 22 ]; then
echo
echo "------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----"
echo
fi
echo "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary"
binaryDownload ${CA_BINARY_FILE} https://hub.fastgit.org/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}
if [ $? -eq 22 ]; then
echo
echo "------> ${CA_TAG} fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----"
echo
fi
}
dockerInstall() {
which docker >& /dev/null
NODOCKER=$?
if [ "${NODOCKER}" == 0 ]; then
echo "===> Pulling fabric Images"
dockerFabricPull ${FABRIC_TAG}
echo "===> Pulling fabric ca Image"
dockerCaPull ${CA_TAG}
echo "===> Pulling thirdparty docker images"
dockerThirdPartyImagesPull ${THIRDPARTY_TAG}
echo
echo "===> List out hyperledger docker images"
docker images | grep hyperledger*
else
echo "========================================================="
echo "Docker not installed, bypassing download of Fabric images"
echo "========================================================="
fi
}
DOCKER=true
SAMPLES=true
BINARIES=true
# Parse commandline args pull out
# version and/or ca-version strings first
if [ ! -z "$1" -a ${1:0:1} != "-" ]; then
VERSION=$1;shift
if [ ! -z "$1" -a ${1:0:1} != "-" ]; then
CA_VERSION=$1;shift
if [ ! -z "$1" -a ${1:0:1} != "-" ]; then
THIRDPARTY_IMAGE_VERSION=$1;shift
fi
fi
fi
# prior to 1.2.0 architecture was determined by uname -m
if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then
export FABRIC_TAG=${MARCH}-${VERSION}
export CA_TAG=${MARCH}-${CA_VERSION}
export THIRDPARTY_TAG=${MARCH}-${THIRDPARTY_IMAGE_VERSION}
else
# starting with 1.2.0, multi-arch images will be default
: ${CA_TAG:="$CA_VERSION"}
: ${FABRIC_TAG:="$VERSION"}
: ${THIRDPARTY_TAG:="$THIRDPARTY_IMAGE_VERSION"}
fi
BINARY_FILE=hyperledger-fabric-${ARCH}-${VERSION}.tar.gz
CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${CA_VERSION}.tar.gz
# then parse opts
while getopts "h?dsb" opt; do
case "$opt" in
h|\?)
printHelp
exit 0
;;
d) DOCKER=false
;;
s) SAMPLES=false
;;
b) BINARIES=false
;;
esac
done
if [ "$SAMPLES" == "true" ]; then
echo
echo "Installing hyperledger/fabric-samples repo"
echo
samplesInstall
fi
if [ "$BINARIES" == "true" ]; then
echo
echo "Installing Hyperledger Fabric binaries"
echo
binariesInstall
fi
if [ "$DOCKER" == "true" ]; then
echo
echo "Installing Hyperledger Fabric docker images"
echo
dockerInstall
fi