fabric bootstrap.sh 安装脚本分析

为什么要分析安装脚本

对于初学者,很多文档都是直接运行该安装脚本,就可以自动化部署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.8export CA_VERSION=1.4.7export THIRDPARTY_IMAGE_VERSION=0.4.21。默认使用的是这些参数。

首先是逻辑框架

前面默认给出的变量值都是true,通过判断参数值,执行相关功能。samplesInstallbinariesInstalldockerInstall

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
上一篇:部署 Hyperledger Fabric


下一篇:Markdown学习