如何使用 exex(go) 在 linux/macOS 中正确模拟终端?
How to correctly emulate terminal in linux/macOS using exex(go)?
我需要在 go
中模拟一个终端。我尝试这样做:
lsCmd := exec.Command("bash", "-c", "ls")
lsOut, err := lsCmd.Output()
if err != nil {
panic(err)
}
fmt.Println(string(lsOut))
而且它似乎工作正常(本机 ubuntu 终端显示水平列表,而此功能的结果是垂直的)。
但是如果我特别调用了错误的命令,例如 exec.Command ("bash", "-c", "lss")
,我会得到:
panic: exit status 127
在本机 ubuntu 终端中,我得到以下结果:
Command 'lss' not found, did you mean:
和命令的枚举。
我需要与本地终端通信,如果我在标准 ubuntu 终端中编写命令,则得到与命令结果相同的结果。
最好的方法是什么?也许 exec
库不适合这个?所有这些都是与 OS 终端进行前端通信所必需的。在一个简单的html/css/js
页面上,用户输入命令,go
发送到操作系统的本机终端,returns将结果发送到前端。
如何获得与在本机终端中工作时相同的命令执行结果?
问题
But if I specifically call the wrong command, for example exec.Command
("bash", "-c", "lss"), I get:
panic: exit status 127
And in the native ubuntu terminal I get the following result:
Command 'lss' not found, did you mean:
and enumeration of commands.
这与 Go 无关,问题实际上有两个方面:
Ubuntu 附带一个特殊的软件包,command-not-found
,它通常是预先安装的,它试图通过采用两种技术使终端对普通人更友好:
- 它会尝试针对拼写错误提出更正建议(您的情况)。
- 当用户尝试执行一个程序时,它会尝试建议要安装的程序包,如果用户安装了特定的程序包,该程序将可用。
当找不到命令时,"plain"(见下文)shell 通过返回非零退出代码使尝试失败。
这绝对是意料之中的,也是正常的。
我的意思是,恐慌是绝对不明智的。
Unix 系统上 shell 与 运行 的历史差异。
当用户登录系统时(请记住,在发明 shell 概念的日子里,您将通过 hardware computer terminal 登录,这基本上就是您的 GNOME 终端window 但在硬件中,并通过电线连接),
所谓的登录shell就开始了
逻辑 shell 的主要思想是为用户提供 交互式 环境。
但是您肯定知道,shells 也可以执行脚本。
当 shell 执行脚本时,它 运行 处于非交互模式。
Unix shell 可以工作的模式
现在让我们深入探讨交互式与非交互式 shells。
在交互模式下:
- shell 通常连接到真实终端(硬件软件或 terminal emulator;您的 GNOME 终端 window 是终端模拟器)。
"Connected"表示shell的standard I/O streams连接到终端,所以shell打印的内容由终端显示。
- 它为用户启用了某些功能,通常提供有限的方式来编辑正在输入的内容(
bash
,例如,参与 GNU readline
。
非交互模式下:
- shell 的标准 I/O 流连接到某些文件(或连接到 "nowhere" — 如
/dev/null
)。
- 没有启用附加功能 — 因为没有人使用它们。
GNU bash
能够 运行 在两种模式下,运行 取决于哪种模式
在 how it was invoked.
在不同的模式下初始化时,bash
读取不同的初始化脚本, 这解释了为什么 command-not-found
包提供的机制参与交互模式,当 bash 为 运行 时则不会,否则 — 就像您在 Go 中的调用一样。
遇到问题怎么办
最简单的尝试是 运行 bash 使用 --login
命令行选项,或者让它认为 运行s 作为交互式 shell.
这可能会解决您的问题,但不一定。
下一个可能的问题是 一些 程序确实会检查它们是否 运行 在终端上——通常这些程序坚持与用户进行真正的交互,通常是为了出于安全目的,有些程序在未连接到真实终端时根本无法 运行 — 这些是 "full-screen" 文本 UI 程序,例如 GNU Midnight Commander、Vim、Emacs , GNU Nano 和类似的东西。
要解决这个问题,唯一的解决办法是在伪终端环境中运行 shell,这就是@eudore 在他们的评论中暗示的。
github.com/creack/pty
might be a package to start looking at; golang.org/x/crypto/ssh
还提供了一些处理 PTY 的方法。
我需要在 go
中模拟一个终端。我尝试这样做:
lsCmd := exec.Command("bash", "-c", "ls")
lsOut, err := lsCmd.Output()
if err != nil {
panic(err)
}
fmt.Println(string(lsOut))
而且它似乎工作正常(本机 ubuntu 终端显示水平列表,而此功能的结果是垂直的)。
但是如果我特别调用了错误的命令,例如 exec.Command ("bash", "-c", "lss")
,我会得到:
panic: exit status 127
在本机 ubuntu 终端中,我得到以下结果:
Command 'lss' not found, did you mean:
和命令的枚举。
我需要与本地终端通信,如果我在标准 ubuntu 终端中编写命令,则得到与命令结果相同的结果。
最好的方法是什么?也许 exec
库不适合这个?所有这些都是与 OS 终端进行前端通信所必需的。在一个简单的html/css/js
页面上,用户输入命令,go
发送到操作系统的本机终端,returns将结果发送到前端。
如何获得与在本机终端中工作时相同的命令执行结果?
问题
But if I specifically call the wrong command, for example exec.Command ("bash", "-c", "lss"), I get:
panic: exit status 127
And in the native ubuntu terminal I get the following result:
Command 'lss' not found, did you mean:
and enumeration of commands.
这与 Go 无关,问题实际上有两个方面:
Ubuntu 附带一个特殊的软件包,
command-not-found
,它通常是预先安装的,它试图通过采用两种技术使终端对普通人更友好:- 它会尝试针对拼写错误提出更正建议(您的情况)。
- 当用户尝试执行一个程序时,它会尝试建议要安装的程序包,如果用户安装了特定的程序包,该程序将可用。
当找不到命令时,"plain"(见下文)shell 通过返回非零退出代码使尝试失败。
这绝对是意料之中的,也是正常的。 我的意思是,恐慌是绝对不明智的。Unix 系统上 shell 与 运行 的历史差异。
当用户登录系统时(请记住,在发明 shell 概念的日子里,您将通过 hardware computer terminal 登录,这基本上就是您的 GNOME 终端window 但在硬件中,并通过电线连接), 所谓的登录shell就开始了
逻辑 shell 的主要思想是为用户提供 交互式 环境。但是您肯定知道,shells 也可以执行脚本。 当 shell 执行脚本时,它 运行 处于非交互模式。
Unix shell 可以工作的模式
现在让我们深入探讨交互式与非交互式 shells。
在交互模式下:
- shell 通常连接到真实终端(硬件软件或 terminal emulator;您的 GNOME 终端 window 是终端模拟器)。
"Connected"表示shell的standard I/O streams连接到终端,所以shell打印的内容由终端显示。 - 它为用户启用了某些功能,通常提供有限的方式来编辑正在输入的内容(
bash
,例如,参与 GNUreadline
。
- shell 通常连接到真实终端(硬件软件或 terminal emulator;您的 GNOME 终端 window 是终端模拟器)。
非交互模式下:
- shell 的标准 I/O 流连接到某些文件(或连接到 "nowhere" — 如
/dev/null
)。 - 没有启用附加功能 — 因为没有人使用它们。
- shell 的标准 I/O 流连接到某些文件(或连接到 "nowhere" — 如
GNU bash
能够 运行 在两种模式下,运行 取决于哪种模式
在 how it was invoked.
在不同的模式下初始化时,bash
读取不同的初始化脚本, 这解释了为什么 command-not-found
包提供的机制参与交互模式,当 bash 为 运行 时则不会,否则 — 就像您在 Go 中的调用一样。
遇到问题怎么办
最简单的尝试是 运行 bash 使用 --login
命令行选项,或者让它认为 运行s 作为交互式 shell.
这可能会解决您的问题,但不一定。
下一个可能的问题是 一些 程序确实会检查它们是否 运行 在终端上——通常这些程序坚持与用户进行真正的交互,通常是为了出于安全目的,有些程序在未连接到真实终端时根本无法 运行 — 这些是 "full-screen" 文本 UI 程序,例如 GNU Midnight Commander、Vim、Emacs , GNU Nano 和类似的东西。
要解决这个问题,唯一的解决办法是在伪终端环境中运行 shell,这就是@eudore 在他们的评论中暗示的。
github.com/creack/pty
might be a package to start looking at; golang.org/x/crypto/ssh
还提供了一些处理 PTY 的方法。