golang终端:syscall与os / exec stty

时间:2018-06-22 10:45:31

标签: go terminal system-calls stty

这是通过go进行系统调用来获得(POSIX)终端大小的方法:

func getTermDim() (width, height int, err error) {
    var termDim [4]uint16
    if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(0), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&termDim)), 0, 0, 0); err != 0 {
        return -1, -1, err
    }
    return int(termDim[1]), int(termDim[0]), nil
}

现在,同样的事情,用os / exec调用stty:

func getTermDim() (width, height int, err error) {
        cmd := exec.Command("stty", "size")
        cmd.Stdin = os.Stdin
        var termDim []byte
        if termDim, err = cmd.Output(); err != nil {
                return
        }
        fmt.Sscan(string(termDim), &height, &width)
        return
}

在实践中,第一种解决方案可能变得很笨重且难以理解,当必须将终端置于原始模式,设置选项等时。第二种解决方案是用来作发型(例如在shell脚本中)。容易得多!

所以我的问题是:使用第一个解决方案有什么好处?是速度吗?是不是我们不能依赖将stty命令安装在主机上?还有什么我没想到的?

简而言之,使用stty与syscall的“ 风险”或“ 成本”是什么?

1 个答案:

答案 0 :(得分:2)

关于风险:

  • stty:如果stty中没有$PATH命令,您的程序将无法正常运行。或者,如果stty中的$PATH命令不是您所期望的命令(可能是安全问题)。或者,如果程序在具有最小占用空间的Docker容器中运行:您必须在图像中放入stty
  • syscall:您的程序取决于操作系统。只要您将该功能写入受build tags保护的文件中,就可以确保该功能在不支持的OS上编译时会失败。

关于性能,只需使用软件包testing编写一个benchmark。但我已经可以告诉您,exec.Command意味着多个系统调用的费用要比IOCTL / TIOCGWINSZ高得多。