Home > Back-end >  golang exec command output empty
golang exec command output empty

Time:09-16

I want run ncftpput in go and want to get the output string for analysis but Only the following style can be output.

    cmdStr := "ncftpput -R -f C:\\Users\\xx\\source\\go\\depolyment\\cfg\\login.cfg / C:\\Users\\xx\\source\\go\\depolyment\\cfg"
    args := strings.Split(cmdStr, " ")
    cmd := exec.Command(args[0], args[1:]...)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Run()

I have tried many methods and the output is allways empty,such as:

cmd.Output()
cmd.CombinOutput()
io.Pipe()

Who can help me solve this problem, tks!

CodePudding user response:

From the man page of ncftpput :

-v/-V

Do (do not) use progress meters. The default is to use progress meters if the output stream is a TTY.

Like many commands (grep or ls with their colored output for example), ncftpput tries to detect if it is running in a terminal or not, and changes its default output based on that.

In a shell : try running ncftpput ... > /tmp/output && cat /tmp/output or ncftpput ... | cat to see what's the output when stdout is not a terminal (spoiler: it is probably going to be empty).


A command run in a exec.Command context is not run in a terminal context (its output is not a tty).

In your particular use case with ncftpoutput, if you want your progress meter output in all circumstances : just add -v to your command.

CodePudding user response:

My solution is add log file to ncftpput

package ncftp

import (
    "errors"
    "fmt"
    "io/ioutil"
    "os"
    "os/exec"
    "path/filepath"
    "strings"
)

type NcFtpPut struct {
    logdir    string
    loginCfg  string
    remotPath string
    localPath string
    debugFile string
}

func NewNcFtpPut(logdir, loginCfg, remotPath, localPath string) *NcFtpPut {
    return &NcFtpPut{
        logdir:    logdir,
        loginCfg:  loginCfg,
        remotPath: remotPath,
        localPath: localPath,
    }
}

func (n *NcFtpPut) Run() error {
    n.buildDebugFile()
    args := n.buildArgs()
    if err := n.execCmd(args[0], args[1:]...); err != nil {
        return err
    }
    if err := n.analisysDebugFile(); err != nil {
        return err
    }
    return nil
}

func (n *NcFtpPut) buildArgs() []string {
    args := []string{"ncftpput", "-R"}
    args = append(args, "-f")
    args = append(args, n.loginCfg)
    args = append(args, "-d")
    args = append(args, n.debugFile)
    args = append(args, n.remotPath)
    args = append(args, n.localPath)
    return args
}

func (n *NcFtpPut) buildDebugFile() {
    n.debugFile = filepath.Join(n.logdir, "ftp.log")
    os.Remove(n.debugFile)
}

func (n *NcFtpPut) execCmd(cmdName string, args ...string) error {
    cmd := exec.Command(cmdName, args...)
    stdOut, err := cmd.CombinedOutput()
    errOut := hasOutput(stdOut)
    if err != nil {
        if errOut != nil {
            return fmt.Errorf("%s:%s", err, errOut)
        }
        return err
    }
    if errOut != nil {
        return errOut
    }
    return nil
}

func hasOutput(stdOut []byte) error {
    if stdOut != nil {
        return errors.New(string(stdOut))
    }
    return nil
}

func (n *NcFtpPut) analisysDebugFile() error {
    buf, err := ioutil.ReadFile(n.debugFile)
    if err != nil {
        return err
    }
    ret := string(buf)
    if strings.Contains(ret, "Operation successful") {
        return nil
    }
    return errors.New("error pls read ftplog file")
}


  • Related