为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
幕布斯7119047 2023-06-05 09:17:59
我正在尝试执行一个要求多个输入的命令,例如,如果您尝试将文件从本地设备复制到我们使用的远程设备,那么它会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 的密码上:并且没有文件被复制到远程设备。
查看完整描述

3 回答

?
精慕HU

TA贡献1845条经验 获得超8个赞

make menuconfig我在尝试通过 golang运行 linux 时遇到了这个问题os/exec。


要完成您想要实现的目标,请尝试将其设置cmd.Stdin为os.Stdin. 这是一个工作示例:


package main


import (

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

}


查看完整回答
反对 回复 2023-06-05
?
达令说

TA贡献1821条经验 获得超6个赞

解决此问题的一种方法是使用命令行标志:


package main


import (

    "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 name

ip: 12345678910


查看完整回答
反对 回复 2023-06-05
?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

解决方案 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 = r

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

...


查看完整回答
反对 回复 2023-06-05
  • 3 回答
  • 0 关注
  • 196 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信