英文:
Why does this exec.Command to a different opened tty not work properly
问题
有人可以帮我弄清楚我在这里做错了什么吗?
我试图执行一个命令(在这种情况下是打开vim),该命令在不同的tty中运行,即/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
英文:
Can anybody please help me figure out what I'm doing wrong here.
I'm trying to execute a command (opening vim in this case) that runs in a different tty, in this case /dev/ttys001, which is opened in another tab in my terminal.
Running the code below does render vim in /dev/ttys001's window, however, actually typing to stdin from that window doesn't register properly.
Any advice is much appreciated!
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)
}
}
I have also tried setting the command's SysProcAttr field with the following code but receive the error: fork/exec /usr/local/bin/vim: inappropriate ioctl for device.
procAttr := &syscall.SysProcAttr{
Setpgid: true,
Ctty: int(tty.Fd()),
Foreground: true,
}
c.SysProcAttr = procAttr
答案1
得分: 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)
}
}
}
希望对你有帮助!
英文:
For anybody who's interested, I came up with a solution, but I ended up having to use system calls instead of the os/exec package's functions.
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)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论