如何包装一个交互式的命令?

huangapple go评论76阅读模式
英文:

How wrap a command that is interactive

问题

我正在构建一个在生成之前执行一些操作的FTP包装器,我可以很容易地用shell脚本来实现,但我想知道如何在Go语言中实现。

对于简单的命令,可以使用exec.Command。

out, err := exec.Command("ls").Output() // 可行

但是,如何包装交互式命令,比如ftp呢?

out, err := exec.Command("ftp").Output()

它只是退出了。如何处理标准输入?

例如,bash的等效方式:

> ./t.sh 
欢迎来到myftp 

ftp> open blahblah.com

> cat t.sh 
#!/bin/bash
echo "欢迎来到myftp"
#其他命令,如auth/authoriz等
shift
echo "$@"
ftp

C++的等效方式:

int main() {
	system("ftp");
	return 0;
}
英文:

I am building an ftp wrapper that does some stuff before I spawn, I could easily do it in a shell script but wondering how I could do it in go

While exec.Command works for simple commands.

out, err := exec.Command("ls").Output() // Works

How do I wrap commands that are interactive e.g., ftp

out, err := exec.Command("ftp").Output()

It just exits. How do I deal with stdin ?

e.g., bash equivalent :

> ./t.sh 
Welcome to myftp 

ftp> open blahblah.com

> cat t.sh 
#!/bin/bash
echo "Welcome to myftp "
#extra commands such as auth/authoriz.. etc.,
shift
echo "$@"
ftp

c++ equivalent :

int main() {
	system("ftp");
	return 0;
}

答案1

得分: 3

我会做一些类似这样的事情,更本地化,不涉及外部包。

package main
import (
	"os"
	"os/exec"
)

func main() {

	cmd := exec.Command("ls")
	// 将输出重定向到终端
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	cmd.Run()

}
英文:

I would probably do something like this which is more native and doesn't involve an external package

package main
import (
	"os"
	"os/exec"
)

func main() {

	cmd := exec.Command("ls")
	// redirect the output to terminal
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	cmd.Run()

}

答案2

得分: 1

传统上,这种交互式脚本练习最好使用expect来完成。我可以建议你查看一个纯Go的等效工具

从自述文件中可以看到:

child, err := gexpect.Spawn("python")
if err != nil { panic(err) }
child.Expect(">>>")
child.SendLine("print 'Hello World'")
child.Interact()
child.Close()
英文:

Traditionally these sorts of interactive scripting exercises are best done with expect. May I suggest checking out a pure Go equivalent?

From the readme:

child, err := gexpect.Spawn("python")
if err != nil { panic(err) }
child.Expect(">>>")
child.SendLine("print 'Hello World'")
child.Interact()
child.Close()

答案3

得分: 0

运行任何需要提示用户输入的命令:

cmd := exec.Command("cf", "login")
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin

cmd.Run()
英文:

To run any commands which will prompt for user input:

cmd := exec.Command("cf", "login")
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin

cmd.Run()

答案4

得分: 0

可以使用以下完整脚本来“包装”一个命令,该脚本基于reticentroot的答案这个答案关于获取exec命令返回代码(go 1.12+):

package main

import (
	"os"
	"os/exec"
)

var (
	bin = "py"
	args = []string{"-3.8"}
)

func main() {
	cmd := exec.Command(bin, append(args, os.Args[1:]...)...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	if err := cmd.Run(); err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			os.Exit(exitError.ExitCode())
		}
	}
}

希望对你有帮助!

英文:

A command can be "wrapped" using the following complete script, based on reticentroot's answer and this answer regarding obtaining exec command return codes (go 1.12+):

package main

import (
	"os"
	"os/exec"
)

var (
	bin = "py"
	args = []string{"-3.8"}
)

func main() {
	cmd := exec.Command(bin, append(args, os.Args[1:]...)...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	if err := cmd.Run() ; err != nil {
		if exitError, ok := err.(*exec.ExitError); ok {
			os.Exit(exitError.ExitCode())
		}
	}
}

huangapple
  • 本文由 发表于 2016年9月28日 06:15:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/39735171.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定