在 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 建议的解决方案要好得多。
我已经构建了一个 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 建议的解决方案要好得多。