golang 中的终端:系统调用与 os/exec stty
Terminal in golang: syscall vs os/exec 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
}
在实践中,当必须将终端置于原始模式、设置选项等时,第一个解决方案可能会变得非常繁重且不可读。当一个人习惯于 stty 时(例如在 shell 脚本中) ,第二个解决方案就简单多了!
所以我的问题是:使用第一种解决方案有什么好处?是速度?是不是我们不能依赖stty命令安装到宿主机上?还有什么我没有想到的吗?
简而言之shell,使用 stty 与 a 的“风险”或“成本”是什么系统调用?
关于风险:
stty
:如果 stty
命令在 $PATH
中不可用,您的程序将无法正常运行。或者如果 $PATH
中的 stty
命令不是您期望的命令(这可能是一个安全问题)。或者,如果程序在具有极简主义足迹的 Docker 容器中运行:您必须将 stty
放入图像中。
- 系统调用:您的程序依赖于 OS。只要您在受 build tags 保护的文件中编写该函数就可以,以确保构建在编译时在不受支持的 OS.
上失败
关于性能,写一个benchmark using package testing
就可以了。但我已经可以告诉你 exec.Command
意味着多个系统调用比 IOCTL
/TIOCGWINSZ
.
成本高得多
这是通过 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
}
在实践中,当必须将终端置于原始模式、设置选项等时,第一个解决方案可能会变得非常繁重且不可读。当一个人习惯于 stty 时(例如在 shell 脚本中) ,第二个解决方案就简单多了!
所以我的问题是:使用第一种解决方案有什么好处?是速度?是不是我们不能依赖stty命令安装到宿主机上?还有什么我没有想到的吗?
简而言之shell,使用 stty 与 a 的“风险”或“成本”是什么系统调用?
关于风险:
stty
:如果stty
命令在$PATH
中不可用,您的程序将无法正常运行。或者如果$PATH
中的stty
命令不是您期望的命令(这可能是一个安全问题)。或者,如果程序在具有极简主义足迹的 Docker 容器中运行:您必须将stty
放入图像中。- 系统调用:您的程序依赖于 OS。只要您在受 build tags 保护的文件中编写该函数就可以,以确保构建在编译时在不受支持的 OS. 上失败
关于性能,写一个benchmark using package testing
就可以了。但我已经可以告诉你 exec.Command
意味着多个系统调用比 IOCTL
/TIOCGWINSZ
.