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