2016-09-06 70 views
0

有没有人可以帮我弄清楚我在这里做错了什么。为什么这个exec.Command打开一个不同的tty无法正常工作

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

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

任何意见是非常感谢!

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场用下面的代码,但收到错误消息:叉/ EXEC在/ usr/local/bin目录/ VIM:用于设备不合适的ioctl。

procAttr := &syscall.SysProcAttr{ 
    Setpgid: true, 
    Ctty:  int(tty.Fd()), 
    Foreground: true, 
} 
c.SysProcAttr = procAttr 
+0

尝试调用c.Wait()之后。 – AJPennster

+0

嘿@AJPennster,我目前使用c.Run而不是c.Start和c.Run自动调用等待你。 –

+0

啊对,我错过了。 – AJPennster

回答

0

对于任何人谁是有兴趣的,我想出了一个解决方案,但我最后不得不使用系统调用,而不是OS/EXEC包的功能。

package main 

import (
    "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) 
     } 
    } 
} 
相关问题