Executing bash script from Go using goa-webFramework / Command not executing

Tech-stack: HyperledgerFabric 1.4, Project-repository- FirstNetwork under FabricSamples Go – v1.15 , Goa- v3.2.5

Requirement: Using Goa framework, I need to trigger a Post request(http://localhost:8000/createChannelProfile) and it has to return the content of the file as a response. The user will input the channelName and channelProfile from frontend. Basically the routing happens this way ,triggers rest-api request-- this method has to call the script file---- the command in the script file should generate a file—that file has to be sent as a response. The point where I am stuck right now is the command in the script file is not getting executed. It is exiting with status code 127 and returning “failed” response. As part of first trial i’m just returning the string as a response instead of a generated output file. I am kinda new to go and Goa, still figuring out how to send a file as a response.If anyone knew please try to give me a hint. These are the commands i have executed as per GOA documentation: goa gen GoApp2/design, goa example GoApp2/design, go build ./cmd/fabric, ./fabric

design.go 
    
    package design
    
    import (
        "fmt"
        . "goa.design/goa/v3/dsl"
    )
    
    var _ = API("fabric", func() {
        Title("An api for fabric")
        Description("A simple goa service")
        Server("fabric", func() {
            Host("localhost", func() {
                URI("http://localhost:8000")
            })
        })
    })
    
    var _ = Service("fabric", func() {
        Description("The service to create a channel.tx file under channel-artifacts folder")
        //Method to add a new Channel Profile
        Method("create", func() {
            Payload(func() {
                Field(1, "channelName", String, "Name of the channel")
                Field(2, "channelProfile", String, "Name of the channel profile")
                Required("channelName", "channelProfile")
            })
            Result(String)
            Error("not_found", ErrorResult, "channelProfile not found")
            HTTP(func() {
                POST("/createChannelProfile")
                Response(StatusCreated)
            })
        })
        Files("/openapi.json", "./gen/http/openapi.json")
    })
fabric.go

//This is the file which calls the generateChannel.sh file

package fabricapi

import (
    fabric "GoApp2/gen/fabric"
    "context"
    "fmt"
    "log"
    "os/exec"
)

// fabric service example implementation.
// The example methods log the requests and return zero values.
type fabricsrvc struct {
    logger *log.Logger
}

// NewFabric returns the fabric service implementation.
func NewFabric(logger *log.Logger) fabric.Service {
    return &fabricsrvc{logger}
}

// Create implements create.
func (s *fabricsrvc) Create(ctx context.Context, p *fabric.CreatePayload) (res string, err error) {
    s.logger.Print("fabric.create")
    cmd := exec.Command("/bin/bash", "../generateChannel.sh", p.ChannelName, p.ChannelProfile)
    stdout, err := cmd.Output()
    fmt.Errorf("error %s", err)
    s.logger.Print(p.ChannelName)
    s.logger.Print(p.ChannelProfile)
    output := string(stdout)
    s.logger.Print(output)
    res = output

    return res, nil
}
generateChannel.sh file

#!/bin/bash
export CHANNELNAME="$1"
export CHANNELPROFILE="$2"

../bin/configtxgen -profile "${CHANNELPROFILE}" -outputCreateChannelTx "./channel-artifacts/${CHANNELNAME}.tx" -channelID "${CHANNELNAME}"
res=$?
echo ${res}
if [ $res -eq 0 ]; then
  echo "success"
  else
  echo "failed"
fi
Note: I have tested alone this file, it is executing perfectly. The command above in the script file looks for channelProfile and channelName which are defined in the configtx.yaml file and accordingly generates the channel.tx file.I have defined the environment variables and added the paths to the .bashrc and .profile files. Please help me where i am going wrong.

screenshot of go env
![image|690x425](upload://nHDGlXUJXbVsGKKFmYUTjUa7isN.png) 

Output from Postman:

![image|690x307](upload://3Bi9rnRw6iw5zChPFB9OPVI2Izx.png) 

Output from Terminal:

:~/workspace/fabric-samples/first-network/GoApp2$ ./fabric
[fabricapi] 12:47:59 HTTP "Create" mounted on POST /createChannelProfile
[fabricapi] 12:47:59 HTTP "./gen/http/openapi.json" mounted on GET /openapi.json
[fabricapi] 12:47:59 HTTP server listening on "localhost:8000"
[fabricapi] 12:48:05 id=95ISzo9L req=POST /createChannelProfile from=127.0.0.1
[fabricapi] 12:48:05 fabric.create
[fabricapi] 12:48:06 mychannel
[fabricapi] 12:48:06 TwoOrgsChannel
[fabricapi] 12:48:06 127
failed

Did you try to just do this without all the API stuff? Are you sure the Bash script is located where you think it is (one folder above where your Go code is executed)? Is the Bash script executable?

yes, the script file alone is executing perfectly. Yes the location of the bash Script file is correct. yes the bash script is executable.

Please check the Stderr, if you do not want to change your programm to much, just use CombinedOutput rather than Output.

It will tell you that it is unable to find your ../generateChannel.sh, because that is what exit code 127 means.

Remember that relative pathes are resolved from where you run the program, not from where you have the source file.

So if you run go run from your project root, then the script had to be one level up the project root.

It is able to pick the generateChannel.sh file. The result of the this command …/bin/configtxgen -profile “${CHANNELPROFILE}” -outputCreateChannelTx “./channel-artifacts/${CHANNELNAME}.tx” -channelID “${CHANNELNAME}” in the script file is exiting with status code 127. When alone executing the script file it is working fine. I have executed the same functionality using nodejs-Express, it was working fine.

Have you checked stdout in your go program as I said? Does bash print something there? What was it? Please share your project structure and also tell us from where you run what commands.

If in doubt recreat the problem in a minimal git repository and tell us the URL providing instructions in the README what to run from where to reproduce the error.

If bash exits with 127, it does mean that it was unable to find something, it will tell you on stderr what it was unable to find.

yes I have captured the stderr and stdout. stdout = failed
and stderr is
2020-11-12 16:47:43.920 IST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2020-11-12 16:47:43.921 IST [common.tools.configtxgen.localconfig] Load -> PANI 002 Error reading configuration: Unsupported Config Type “”
2020-11-12 16:47:43.921 IST [common.tools.configtxgen] func1 -> PANI 003 Error reading configuration: Unsupported Config Type “”
panic: Error reading configuration: Unsupported Config Type “” [recovered]
panic: Error reading configuration: Unsupported Config Type “”

goroutine 1 [running]:
.com/hyperledger/fabric/vendor/go.uber.org/zap/zapcore.(*CheckedEntry).Write(0xc0000f9c30, 0x0, 0x0, 0x0)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/vendor/go.uber.org/zap/zapcore/entry.go:229 +0x515
github.com/hyperledger/fabric/vendor/go.uber.org/zap.(*SugaredLogger).log(0xc00000e248, 0xc0002f7804, 0xc00003ce00, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/vendor/go.uber.org/zap/sugar.go:234 +0xf6
.com/hyperledger/fabric/vendor/go.uber.org/zap.(*SugaredLogger).Panicf(0xc00000e248, 0xc00003ce00, 0x38, 0x0, 0x0, 0x0)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/vendor/go.uber.org/zap/sugar.go:159 +0x79
.com/hyperledger/fabric/common/flogging.(*FabricLogger).Panic(0xc00000e250, 0xc0002f7908, 0x1, 0x1)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/common/flogging/zap.go:73 +0x75
main.main.func1()
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/common/tools/configtxgen/main.go:260 +0x1a9
panic(0xd62c40, 0xc0002e4a10)
/opt/go/go1.11.5.linux.amd64/src/runtime/panic.go:513 +0x1b9
.com/hyperledger/fabric/vendor/go.uber.org/zap/zapcore.(*CheckedEntry).Write(0xc0000f9c30, 0x0, 0x0, 0x0)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/vendor/go.uber.org/zap/zapcore/entry.go:229 +0x515
.com/hyperledger/fabric/vendor/go.uber.org/zap.(*SugaredLogger).log(0xc00000e228, 0xc0002f7c04, 0xc00003cc40, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/vendor/go.uber.org/zap/sugar.go:234 +0xf6
com/hyperledger/fabric/vendor/go.uber.org/zap.(*SugaredLogger).Panicf(0xc00000e228, 0xc00003cc40, 0x38, 0x0, 0x0, 0x0)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/vendor/go.uber.org/zap/sugar.go:159 +0x79
.com/hyperledger/fabric/common/flogging.(*FabricLogger).Panic(0xc00000e230, 0xc0002f7d88, 0x2, 0x2)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/common/flogging/zap.go:73 +0x75
github.com/hyperledger/fabric/common/tools/configtxgen/localconfig.Load(0x7ffccd0bdfb6, 0xe, 0x0, 0x0, 0x0, 0xc0004503b8)
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/common/tools/configtxgen/localconfig/config.go:276 +0x41f
main.main()
/w/workspace/fabric-release-jobs-x86_64/gopath/src/github.com/hyperledger/fabric/common/tools/configtxgen/main.go:271 +0xce0

The folder structure is as follows:
Note Earlier the bin folder was outside the first-network , now i place the bin folder inside the first-network
The status code of the command is exiting now with 2.

first-network------main folder
bin-----folder under first-network
configtxgen -------binary file under bin folder
GoApp2-----folder under first-network
design--------subfolder under GoApp2
design.go ----- file under design folder
fabric.go-------file under GoApp2
generateChannel.sh-----file under first-network

Running the commands from:
~/workspace/fabric-samples/first-network/GoApp2$ go build ./cmd/fabric
~/workspace/fabric-samples/first-network/GoApp2$ ./fabric

go build ./cmd/fabric which compiles the code and ./fabric will start the server

The output of executing the generateChannel.sh file directly:

~/workspace/fabric-samples/first-network$ ./generateChannel.sh mychannel TwoOrgsChannel
2020-11-12 16:46:13.152 IST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2020-11-12 16:46:13.403 IST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/upgrad/workspace/fabric-samples/first-network/configtx.yaml
2020-11-12 16:46:13.628 IST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2020-11-12 16:46:13.628 IST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /home/upgrad/workspace/fabric-samples/first-network/configtx.yaml
2020-11-12 16:46:13.628 IST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 005 Generating new channel configtx
2020-11-12 16:46:13.674 IST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 006 Writing new channel tx
0
success

stdout is success and exit status code is 0

It seems as if 127 is not necessarily the exit code that bash creates, but maybe the exit code propagated from your script, which according to the shown output can’t find its config.

yes , It cant find its config now. I will try inputting the config to the command and will check.

PS, just realising that your copied stacktrace does not provide an obvious hint to the exit code…

Can you please try to provide some simpler output while also using markdown code-blocks to format these outputs?

The error is resolved. Its working fine.