猿问

为什么这个 exec.Command 到不同的打开的 tty 不能正常工作

任何人都可以帮我弄清楚我在这里做错了什么。


我正在尝试执行一个在不同的 tty 中运行的命令(在这种情况下打开 vim),在这种情况下是 /dev/ttys001,它在我的终端的另一个选项卡中打开。


运行下面的代码确实会在 /dev/ttys001 的窗口中渲染 vim,但是,实际上从该窗口输入标准输入并不能正确注册。


非常感谢任何建议!


package main


import (

    "log"

    "os"

    "os/exec"

)


func main() {

    tty, err := os.OpenFile("/dev/ttys001", os.O_RDWR, os.ModePerm)

    if err != nil {

        log.Fatalln(err)

    }

    defer tty.Close()


    c := exec.Command("vim")

    c.Stdin = tty

    c.Stdout = tty

    c.Stderr = tty

    if err := c.Run(); err != nil {

        log.Fatalln(err)

    }

}

我还尝试使用以下代码设置命令的 SysProcAttr 字段,但收到错误:fork/exec /usr/local/bin/vim: inappropriate ioctl for device.


procAttr := &syscall.SysProcAttr{

    Setpgid:    true,

    Ctty:       int(tty.Fd()),

    Foreground: true,

}

c.SysProcAttr = procAttr


幕布斯7119047
浏览 149回答 1
1回答

aluckdog

对于任何感兴趣的人,我想出了一个解决方案,但我最终不得不使用系统调用而不是 os/exec 包的函数。package mainimport (    "log"    "os"    "syscall"    "unsafe")var tty = "/dev/ttys001"var cmd = "vim\n"func main() {    ttyFile, err := os.Open(tty)    if err != nil {        log.Fatalln(err)    }    defer ttyFile.Close()    cbs, err := syscall.ByteSliceFromString(cmd)    if err != nil {        log.Fatalln(err)    }    var eno syscall.Errno    for _, c := range cbs {        _, _, eno = syscall.Syscall(syscall.SYS_IOCTL,            ttyFile.Fd(),            syscall.TIOCSTI,            uintptr(unsafe.Pointer(&c)),        )        if eno != 0 {            log.Fatalln(eno)        }    }}
随时随地看视频慕课网APP

相关分类

Go
我要回答