猿问

如何在 golang 中执行交互式 CLI 命令?

我正在尝试执行一个要求多个输入的命令,例如,如果您尝试将文件从本地设备复制到我们使用的远程设备,那么它会scp test.txt user@domain:~/要求我们输入密码。我想要的是我想编写一个 go 代码,例如,我在代码本身中提供密码pass:='Secret Password'。同样,我有 CLI 命令,它要求我们提供 IP、名称等几项内容,因此我需要编写一段代码,我只在代码本身中声明所有值,当我运行代码时它不会询问任何内容只需从代码中获取所有输入并运行 CLI 命令,以防将文件复制到远程它不应该在我运行我的 go 二进制文件时询问我密码它应该直接将我的文件复制到远程决定。


func main() {

    cmd := exec.Command("scp", "text.txt", "user@domain:~/")        

    stdin, err := cmd.StdinPipe()

    if err = cmd.Start(); err != nil {

        log.Fatalf("failed to start command: %s", err)

    }

    io.WriteString(stdin, "password\n")

    if err = cmd.Wait(); err != nil {

    log.Fatalf("command failed: %s", err)

    }

}

如果我使用此代码,它会卡在 user@domain 的密码上:


并且没有文件被复制到远程设备。


幕布斯7119047
浏览 264回答 3
3回答

精慕HU

make menuconfig我在尝试通过 golang运行 linux 时遇到了这个问题os/exec。要完成您想要实现的目标,请尝试将其设置cmd.Stdin为os.Stdin. 这是一个工作示例:package mainimport (    "fmt"    "os"    "os/exec")type cmdWithEnv struct {    pwd     string    command string    cmdArgs []string    envs    []string}func runCommand(s cmdWithEnv) error {    cmd := exec.Command(s.command, s.cmdArgs...)    if len(s.pwd) != 0 {        cmd.Dir = s.pwd    }    env := os.Environ()    env = append(env, s.envs...)    cmd.Env = env    fmt.Printf("%v\n", cmd)    cmd.Stdout = os.Stdout    cmd.Stderr = os.Stderr    cmd.Stdin = os.Stdin // setting this allowed me to interact with ncurses interface from `make menuconfig`    err := cmd.Start()    if err != nil {        return err    }    if err := cmd.Wait(); err != nil {        return err    }    return nil}func buildPackage() {    makeKernelConfig := cmdWithEnv{        pwd:     "linux",        command: "make",        cmdArgs: []string{"-j12", "menuconfig"},        envs:    []string{"CROSS_COMPILE=ccache arm-linux-gnueabihf-", "ARCH=arm"},    }    runCommand(makeKernelConfig)}func main() {    buildPackage()}

达令说

解决此问题的一种方法是使用命令行标志:package mainimport (    "flag"    "fmt"    "math")func main() {    var (        name = flag.String("name", "John", "Enter your name.")        ip   = flag.Int("ip", 12345, "What is your ip?")    )    flag.Parse()    fmt.Println("name:", *name)    fmt.Println("ip:", *ip)}name现在您可以使用和标志运行程序ip:go run main.go -name="some random name" -ip=12345678910`some random nameip: 12345678910

有只小跳蛙

解决方案 1您可以使用printf命令绕过它cmd := "printf 'John Doe\nNew York\n35' | myInteractiveCmd"out, err := exec.Command("bash", "-c", cmd).Output()方案二你可以使用io.Pipe()。Pipe creates a synchronous in-memory pipe您可以将答案写入io.Writer,您的 cmd 将从io.Reader.r, w := io.Pipe()cmd := exec.Command("myInteractiveCmd")cmd.Stdin = rgo func() {    fmt.Fprintf(w, "John Doe\n")    fmt.Fprintf(w, "New York\n")    fmt.Fprintf(w, "35\n")    w.Close()}()cmd.Start()cmd.Wait()测试信息 为了对此进行测试,我编写了 cmd,它询问姓名、城市、年龄并将结果写入文件。reader := bufio.NewReader(os.Stdin)fmt.Print("Name: ")name, _ := reader.ReadString('\n')name = strings.Trim(name, "\n")...
随时随地看视频慕课网APP

相关分类

Go
我要回答