如何使用 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 的方法。