Hyperledger Fabric 1.2系列:3.啟動first-network網路,解析byfn.sh啟動指令碼
簡介
在啟動網路之前,確保你已經安裝了所必要的依賴。如果沒有安裝,請參考之前的兩篇內容。
啟動網路
進入fabric-samples/first-network
資料夾內,執行byfn.sh
指令碼
cd fabric-samples/first-network
./byfn.sh
之後你會看到如下內容,則表示成功了:
Querying chaincode on peer1.org2... ===================== Querying on peer1.org2 on channel 'mychannel'... ===================== + peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}' Attempting to Query peer1.org2 ...3 secs + res=0 + set +x 90 ===================== Query successful on peer1.org2 on channel 'mychannel' ===================== ========= All GOOD, BYFN execution completed =========== _____ _ _ ____ | ____| | \ | | | _ \ | _| | \| | | | | | | |___ | |\ | | |_| | |_____| |_| \_| |____/
指令碼解析
指令碼的執行內容講解
指令碼的github地址:https://github.com/hyperledger/fabric-samples/blob/release-1.2/first-network/byfn.sh
也可以檢視這個地址:https://www.jianshu.com/p/6aa318eb938f
# Obtain the OS and Architecture string that will be used to select the correct # native binaries for your platform, e.g., darwin-amd64 or linux-amd64 OS_ARCH=$(echo "$(uname -s | tr '[:upper:]' '[:lower:]' | sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}') # timeout duration - the duration the CLI should wait for a response from # another container before giving up CLI_TIMEOUT=10 # default for delay between commands CLI_DELAY=3 # channel name defaults to "mychannel" CHANNEL_NAME="mychannel" # use this as the default docker-compose yaml definition COMPOSE_FILE=docker-compose-cli.yaml # COMPOSE_FILE_COUCH=docker-compose-couch.yaml # org3 docker compose file COMPOSE_FILE_ORG3=docker-compose-org3.yaml # # use golang as the default language for chaincode LANGUAGE=golang # default image tag IMAGETAG="latest" # Parse commandline args
OS_ARCH
//系統的架構CLI_TIMEOUT
// cli的超時時間CHANNEL_NAME
//通道的名字COMPOSE_FILE
//指定預設的配置檔案COMPOSE_FILE_COUCH
//指定預設的couchdb配置檔案COMPOSE_FILE_ORG3
// 指定組織3的配置檔案LANGUAGE
//指定預設的語言IMAGETAG
//指定預設的映象標籤
if [ "$1" = "-m" ]; then # supports old usage, muscle memory is powerful! shift fi MODE=$1 shift # Determine whether starting, stopping, restarting, generating or upgrading if [ "$MODE" == "up" ]; then EXPMODE="Starting" elif [ "$MODE" == "down" ]; then EXPMODE="Stopping" elif [ "$MODE" == "restart" ]; then EXPMODE="Restarting" elif [ "$MODE" == "generate" ]; then EXPMODE="Generating certs and genesis block" elif [ "$MODE" == "upgrade" ]; then EXPMODE="Upgrading the network" else printHelp exit 1 fi
根據命令列引數配置相關的內容。
while getopts "h?c:t:d:f:s:l:i:v" opt; do
case "$opt" in
h | \?)
printHelp
exit 0
;;
c)
CHANNEL_NAME=$OPTARG
;;
t)
CLI_TIMEOUT=$OPTARG
;;
d)
CLI_DELAY=$OPTARG
;;
f)
COMPOSE_FILE=$OPTARG
;;
s)
IF_COUCHDB=$OPTARG
;;
l)
LANGUAGE=$OPTARG
;;
i)
IMAGETAG=$(go env GOARCH)"-"$OPTARG
;;
v)
VERBOSE=true
;;
esac
done
使用getopts命令來獲取命令列引數,搭配case來根據條件賦值。
簡單的getopts相關的介紹,請參考:https://segmentfault.com/a/1190000010171506
如果你想啟動couchdb的話,你需要在啟動網路的時候,攜帶上-s couchdb
引數。例如:./byfn.sh -s couched
# Announce what was requested
if [ "${IF_COUCHDB}" == "couchdb" ]; then
echo
echo "${EXPMODE} for channel '${CHANNEL_NAME}' with CLI timeout of '${CLI_TIMEOUT}' seconds and CLI delay of '${CLI_DELAY}' seconds and using database '${IF_COUCHDB}'"
else
echo "${EXPMODE} for channel '${CHANNEL_NAME}' with CLI timeout of '${CLI_TIMEOUT}' seconds and CLI delay of '${CLI_DELAY}' seconds"
fi
判斷對應的變數,列印相關的資訊。
# ask for confirmation to proceed
askProceed
#Create the network using docker compose
if [ "${MODE}" == "up" ]; then
networkUp
elif [ "${MODE}" == "down" ]; then ## Clear the network
networkDown
elif [ "${MODE}" == "generate" ]; then ## Generate Artifacts
generateCerts
replacePrivateKey
generateChannelArtifacts
elif [ "${MODE}" == "restart" ]; then ## Restart the network
networkDown
networkUp
elif [ "${MODE}" == "upgrade" ]; then ## Upgrade the network from version 1.1.x to 1.2.x
upgradeNetwork
else
printHelp
exit 1
fi
如果命令列輸入的是./byfn.sh up
或者./byfn.sh -m up
則會執行networkUp
函式。下面的函式以此類推。
函式內容講解
askProceed
# Ask user for confirmation to proceed
function askProceed() {
read -p "Continue? [Y/n] " ans
case "$ans" in
y | Y | "")
echo "proceeding ..."
;;
n | N)
echo "exiting..."
exit 1
;;
*)
echo "invalid response"
askProceed
;;
esac
}
詢問是否繼續。輸入y
或者Y
則繼續指令碼的執行。輸入n
或則N
則停止執行指令碼。
#### clearContainers
function clearContainers() {
CONTAINER_IDS=$(docker ps -a | awk '($2 ~ /dev-peer.*.mycc.*/) {print $1}')
if [ -z "$CONTAINER_IDS" -o "$CONTAINER_IDS" == " " ]; then
echo "---- No containers available for deletion ----"
else
docker rm -f $CONTAINER_IDS
fi
}
function removeUnwantedImages() {
DOCKER_IMAGE_IDS=$(docker images | awk '($1 ~ /dev-peer.*.mycc.*/) {print $3}')
if [ -z "$DOCKER_IMAGE_IDS" -o "$DOCKER_IMAGE_IDS" == " " ]; then
echo "---- No images available for deletion ----"
else
docker rmi -f $DOCKER_IMAGE_IDS
fi
}
如果鏈碼容器存在,則刪除掉容器。否則輸出列印資訊。
checkPrereqs
# Versions of fabric known not to work with this release of first-network
BLACKLISTED_VERSIONS="^1\.0\. ^1\.1\.0-preview ^1\.1\.0-alpha"
# Do some basic sanity checking to make sure that the appropriate versions of fabric
# binaries/images are available. In the future, additional checking for the presence
# of go or other items could be added.
function checkPrereqs() {
# Note, we check configtxlator externally because it does not require a config file, and peer in the
# docker image because of FAB-8551 that makes configtxlator return 'development version' in docker
LOCAL_VERSION=$(configtxlator version | sed -ne 's/ Version: //p')
DOCKER_IMAGE_VERSION=$(docker run --rm hyperledger/fabric-tools:$IMAGETAG peer version | sed -ne 's/ Version: //p' | head -1)
echo "LOCAL_VERSION=$LOCAL_VERSION"
echo "DOCKER_IMAGE_VERSION=$DOCKER_IMAGE_VERSION"
if [ "$LOCAL_VERSION" != "$DOCKER_IMAGE_VERSION" ]; then
echo "=================== WARNING ==================="
echo " Local fabric binaries and docker images are "
echo " out of sync. This may cause problems. "
echo "==============================================="
fi
for UNSUPPORTED_VERSION in $BLACKLISTED_VERSIONS; do
echo "$LOCAL_VERSION" | grep -q $UNSUPPORTED_VERSION
if [ $? -eq 0 ]; then
echo "ERROR! Local Fabric binary version of $LOCAL_VERSION does not match this newer version of BYFN and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples."
exit 1
fi
echo "$DOCKER_IMAGE_VERSION" | grep -q $UNSUPPORTED_VERSION
if [ $? -eq 0 ]; then
echo "ERROR! Fabric Docker image version of $DOCKER_IMAGE_VERSION does not match this newer version of BYFN and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples."
exit 1
fi
done
}
設定當前不支援的版本號
BLACKLISTED_VERSIONS="^1\.0\. ^1\.1\.0-preview ^1\.1\.0-alpha"
檢查版本是否符合要求。
networkUp
# Generate the needed certificates, the genesis block and start the network.
function networkUp() {
checkPrereqs
# generate artifacts if they don't exist
if [ ! -d "crypto-config" ]; then
generateCerts
replacePrivateKey
generateChannelArtifacts
fi
if [ "${IF_COUCHDB}" == "couchdb" ]; then
IMAGE_TAG=$IMAGETAG docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH up -d 2>&1
else
IMAGE_TAG=$IMAGETAG docker-compose -f $COMPOSE_FILE up -d 2>&1
fi
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to start network"
exit 1
fi
# now run the end to end script
docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE
if [ $? -ne 0 ]; then
echo "ERROR !!!! Test failed"
exit 1
fi
}
這是啟動網路的函式。
- 先呼叫
checkPrereqs
函式,檢查版本是否符合要求。 - 再檢查
crypto-config
資料夾是否存在,如果不存在,則呼叫generateCerts
、replacePrivateKey
、generateChannelArtifacts
。 - 判斷是否指定了
couchdb
。 - 之後,進入
cli
容器,執行scripts/script.sh
指令碼
upgradeNetwork
function upgradeNetwork() {
docker inspect -f '{{.Config.Volumes}}' orderer.example.com | grep -q '/var/hyperledger/production/orderer'
if [ $? -ne 0 ]; then
echo "ERROR !!!! This network does not appear to be using volumes for its ledgers, did you start from fabric-samples >= v1.1.x?"
exit 1
fi
LEDGERS_BACKUP=./ledgers-backup
# create ledger-backup directory
mkdir -p $LEDGERS_BACKUP
export IMAGE_TAG=$IMAGETAG
if [ "${IF_COUCHDB}" == "couchdb" ]; then
COMPOSE_FILES="-f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH"
else
COMPOSE_FILES="-f $COMPOSE_FILE"
fi
# removing the cli container
docker-compose $COMPOSE_FILES stop cli
docker-compose $COMPOSE_FILES up -d --no-deps cli
echo "Upgrading orderer"
docker-compose $COMPOSE_FILES stop orderer.example.com
docker cp -a orderer.example.com:/var/hyperledger/production/orderer $LEDGERS_BACKUP/orderer.example.com
docker-compose $COMPOSE_FILES up -d --no-deps orderer.example.com
for PEER in peer0.org1.example.com peer1.org1.example.com peer0.org2.example.com peer1.org2.example.com; do
echo "Upgrading peer $PEER"
# Stop the peer and backup its ledger
docker-compose $COMPOSE_FILES stop $PEER
docker cp -a $PEER:/var/hyperledger/production $LEDGERS_BACKUP/$PEER/
# Remove any old containers and images for this peer
CC_CONTAINERS=$(docker ps | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_CONTAINERS" ]; then
docker rm -f $CC_CONTAINERS
fi
CC_IMAGES=$(docker images | grep dev-$PEER | awk '{print $1}')
if [ -n "$CC_IMAGES" ]; then
docker rmi -f $CC_IMAGES
fi
# Start the peer again
docker-compose $COMPOSE_FILES up -d --no-deps $PEER
done
docker exec cli scripts/upgrade_to_v12.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE
if [ $? -ne 0 ]; then
echo "ERROR !!!! Test failed"
exit 1
fi
}
這個函式是用來升級網路的。從1.1升級到1.2。
這個函式會停掉orderer和peers。備份orderer和peers的ledger。清空chaincode容器。
並且會重啟orderer和peer 使用latest tag
networkDown
# Tear down running network
function networkDown() {
# stop org3 containers also in addition to org1 and org2, in case we were running sample to add org3
docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH -f $COMPOSE_FILE_ORG3 down --volumes --remove-orphans
# Don't remove the generated artifacts -- note, the ledgers are always removed
if [ "$MODE" != "restart" ]; then
# Bring down the network, deleting the volumes
#Delete any ledger backups
docker run -v $PWD:/tmp/first-network --rm hyperledger/fabric-tools:$IMAGETAG rm -Rf /tmp/first-network/ledgers-backup
#Cleanup the chaincode containers
clearContainers
#Cleanup images
removeUnwantedImages
# remove orderer block and other channel configuration transactions and certs
rm -rf channel-artifacts/*.block channel-artifacts/*.tx crypto-config ./org3-artifacts/crypto-config/ channel-artifacts/org3.json
# remove the docker-compose yaml file that was customized to the example
rm -f docker-compose-e2e.yaml
fi
}
關閉網路,清空容器、刪除生成的證書及一些配置相關內容。
replacePrivateKey
function replacePrivateKey() {
# sed on MacOSX does not support -i flag with a null extension. We will use
# 't' for our back-up's extension and delete it at the end of the function
ARCH=$(uname -s | grep Darwin)
if [ "$ARCH" == "Darwin" ]; then
OPTS="-it"
else
OPTS="-I"
fi
# Copy the template to the file that will be modified to add the private key
cp docker-compose-e2e-template.yaml docker-compose-e2e.yaml
# The next steps will replace the template's contents with the
# actual values of the private key file names for the two CAs.
CURRENT_DIR=$PWD
cd crypto-config/peerOrganizations/org1.example.com/ca/
PRIV_KEY=$(ls *_sk)
cd "$CURRENT_DIR"
sed $OPTS "s/CA1_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose-e2e.yaml
cd crypto-config/peerOrganizations/org2.example.com/ca/
PRIV_KEY=$(ls *_sk)
cd "$CURRENT_DIR"
sed $OPTS "s/CA2_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose-e2e.yaml
# If MacOSX, remove the temporary backup of the docker-compose file
if [ "$ARCH" == "Darwin" ]; then
rm docker-compose-e2e.yamlt
fi
}
將docker-compose-e2e-template.yaml
複製到docker-compose-e2e.yaml
。
並替換證書檔案到docker-compose-e2e.yaml
中的固定位置。
generateCerts
function generateCerts() {
which cryptogen
if [ "$?" -ne 0 ]; then
echo "cryptogen tool not found. exiting"
exit 1
fi
echo
echo "##########################################################"
echo "##### Generate certificates using cryptogen tool #########"
echo "##########################################################"
if [ -d "crypto-config" ]; then
rm -Rf crypto-config
fi
set -x
cryptogen generate --config=./crypto-config.yaml
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate certificates..."
exit 1
fi
echo
}
判斷cryptogen
是否存在。
如果crypto-config
目錄存在,則刪除。
generateChannelArtifacts
function generateChannelArtifacts() {
which configtxgen
if [ "$?" -ne 0 ]; then
echo "configtxgen tool not found. exiting"
exit 1
fi
echo "##########################################################"
echo "######### Generating Orderer Genesis block ##############"
echo "##########################################################"
# Note: For some unknown reason (at least for now) the block file can't be
# named orderer.genesis.block or the orderer will fail to launch!
set -x
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate orderer genesis block..."
exit 1
fi
echo
echo "#################################################################"
echo "### Generating channel configuration transaction 'channel.tx' ###"
echo "#################################################################"
set -x
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate channel configuration transaction..."
exit 1
fi
echo
echo "#################################################################"
echo "####### Generating anchor peer update for Org1MSP ##########"
echo "#################################################################"
set -x
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate anchor peer update for Org1MSP..."
exit 1
fi
echo
echo "#################################################################"
echo "####### Generating anchor peer update for Org2MSP ##########"
echo "#################################################################"
set -x
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate \
./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
res=$?
set +x
if [ $res -ne 0 ]; then
echo "Failed to generate anchor peer update for Org2MSP..."
exit 1
fi
echo
}\
通過configtxgen
工具,讀取configtx.yaml
檔案來生成genesis.block
、channel.tx
、每個組織的anchor peer
genesis.block
是提供給orderer service
的。channel.tx
是建立通道時廣播給orderer service
的檔案。anchor peer
是每個組織都會有一個,參與通訊的節點。
涉及的檔案
- 在生成證書時
cryptogen
讀取crypto-config.yaml
檔案。 - 將
docker-compose-e2e-template.yaml
複製為docker-compose-e2e.yaml
configtxgen
讀取configtx.yaml
檔案。- 啟動網路時讀取
docker-compose-cli.yaml
如果啟用了couchdb則還會讀取docker-compose-couch.yaml
- 啟動指令碼為
scripts/script.sh
- 在
script.sh
指令碼中讀取了utils.sh
指令碼的內容。
作者:沙漠中的猴
連結:https://www.jianshu.com/p/00d67b0c7c80
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。