在 shell 脚本中调用链代码函数

Invoking a chaincode function inside a shell script

我已经构建了一个 Hyperledger Fabric 网络并且网络设置正常。链代码也已部署。现在,我想调用链​​码的一个函数。如果我必须通过终端来做,那么它就像:

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"StorePacketData","Args":["a0", "b0", "c0", "d0", "e0"]}'

这很好用。但是,我想从 shell 脚本中调用此函数,其中函数的参数将是变量。此 shell 脚本文件被另一个 shell 脚本调用。因此,我的 shell 脚本文件如下所示:

#!/bin/bash

invokeCC() {

   arg1=
   arg2=
   arg3=
   arg4=
   arg5=

   export PATH=${PWD}/../bin:$PATH
   export FABRIC_CFG_PATH=$PWD/../config/
   export CORE_PEER_TLS_ENABLED=true
   export CORE_PEER_LOCALMSPID="Org1MSP"
   export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   export CORE_PEER_ADDRESS=localhost:7051

   peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"StorePacketData","Args":["$arg1", "$arg2", "$arg3", "$arg4", "$arg5"]}'
}

invokeCC     

这个词很明显:

'{"function":"StorePacketData","Args":["$arg1", "$arg2", "$arg3", "$arg4", "$arg5"]}'

被当成一个完整的字符串,不能传递变量。因此,我尝试了一个变体:

#!/bin/bash

invokeCC() {

   arg1=
   arg2=
   arg3=
   arg4=
   arg5=

   export PATH=${PWD}/../bin:$PATH
   export FABRIC_CFG_PATH=$PWD/../config/
   export CORE_PEER_TLS_ENABLED=true
   export CORE_PEER_LOCALMSPID="Org1MSP"
   export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   export CORE_PEER_ADDRESS=localhost:7051
   QUOTE="'"
   args="{\"function\":\"StorePacketData\",\"Args\":[\"$arg1\", \"$arg2\", \"$arg3\", \"$arg4\", \"$arg5\"]}"

   peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c $QUOTE$args$QUOTE
}

invokeCC     

这也给出了错误

Error: chaincode argument error: invalid character '\'' looking for beginning of value

我知道我在第二种方法中出错了,但我不知道还能做什么。

请建议我在这里应该做什么来调用链代码。如果我需要提供任何其他信息,请告诉我。

提前致谢!

要使用任意命令行参数列表生成格式正确、语法有效的 JSON,请使用 jq 版本 1.6 和 $ARGS.positional:

#!/usr/bin/env bash

invokeCC() {
  args=$(jq -n '{"function":"StorePacketData", "Args": $ARGS.positional}' --args "$@")
  peer chaincode invoke ... --args "$args"
}

invokeCC "$@"

也可以使用 --arg$ARGS.named 实现相同的目标:

invokeCC() {
  local -a jq_args=( )
  local arg idx=0 idx_str
  for arg in "$@"; do
    printf -v idx_str '%04d' "$idx"
    jq_args+=( --arg "arg$idx_str" "$arg" )
    (( ++idx ))
  done
  jq -nc "${jq_args[@]}" '{"function": "StorePacketData", "Args": [$ARGS.named | to_entries | sort_by(.key)[] | .value]}'
}

invokeCC "$@"

正如@Charles Duffy 所建议的,我使用 jq 来传递参数。所以,我将 shell 脚本更改为:

#!/bin/bash

invokeCC() {

   arg1=
   arg2=
   arg3=
   arg4=
   arg5=

   export PATH=${PWD}/../bin:$PATH
   export FABRIC_CFG_PATH=$PWD/../config/
   export CORE_PEER_TLS_ENABLED=true
   export CORE_PEER_LOCALMSPID="Org1MSP"
   export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
   export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
   export CORE_PEER_ADDRESS=localhost:7051

   echo hello

   args=$(jq \
  -n --arg val1 "$arg1" \
  -n --arg val2 "$arg2" \
  -n --arg val3 "$arg3" \
  -n --arg val4 "$arg4" \
  -n --arg val5 "$arg5" \
  '{"function":"StorePacketData", "Args": [$val1, $val2, $val3, $val4, $val5]}'
  )
   echo "$args"

   peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c "$args"
}

invokeCC "" "" "" "" ""

这非常有效。但是,@Charles Duffy 建议的解决方案要好得多。