1

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!

nil
  • 59
  • 4
  • Have you checked the error value returned by `cmd.Run()` ? `err := cmd.Run(); if err != nil { fmt.Println("*** error", err) }` – LeGEC Sep 16 '22 at 03:47
  • for reference: the following code works as expected https://go.dev/play/p/uZkgNwHBLHB – LeGEC Sep 16 '22 at 04:16
  • @LeGEC tks, I have tried, the error is nil – nil Sep 16 '22 at 05:29
  • please paste the code you wrote to run the command and get the `.CombinedOutput()` output of it. – LeGEC Sep 16 '22 at 05:37
  • https://go.dev/play/p/ocClbwtzi9c I guess Ncftpput is running in another process, so no information can be captured @LeGEC – nil Sep 16 '22 at 05:58
  • what is the output you expect ? a progress meter ? – LeGEC Sep 16 '22 at 06:02

2 Answers2

0

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.

LeGEC
  • 46,477
  • 5
  • 57
  • 104
0

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")
}


nil
  • 59
  • 4