Here is a minimal working example:
package main
import (
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"github.com/fyne-io/terminal"
"log/slog"
"os"
"os/exec"
"sync"
)
func main() {
err := runMain()
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}
}
func runMain() error {
wg := sync.WaitGroup{}
wg.Add(1)
term := terminal.New()
go func() {
var err error
// This works
// err = term.RunLocalShell()
// This does not work, blank screen...
cmd := exec.Command("/usr/bin/bash")
si, err := cmd.StdinPipe()
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}
so, err := cmd.StdoutPipe()
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}
err = cmd.Start()
if err != nil {
slog.Error(err.Error())
os.Exit(1)
}
slog.Info("started", "pid", cmd.Process.Pid)
err = term.RunWithConnection(si, so)
if err != nil {
slog.Error(err.Error())
}
wg.Done()
}()
a := app.New()
go func() {
wg.Wait()
a.Quit()
}()
w := a.NewWindow("Test")
w.SetContent(container.New(layout.NewStackLayout(), term))
w.ShowAndRun()
return nil
}
So term.RunLocalShell()
works, but manually connection stdout and stdin of an os.Exec call to term.RunWithConnection(in, out)
does not work. It displays a blank screen, and there is no error message at all.
What is wrong here?
I can see that terminal.RunLocalShell calls terminal.open() and that uses github.com/creack/pty to create a pty. However, terminal.pty is not a public field, it cannot be accessed from outside. My goal is to run a shell command remotely, and display it in a local terminal emulator. E.g. the given example is really minimal, in reality stdin and stdout are pipes connected with TCP to a remote process.
If a remote system is the aim I’d recommend checking out an SSH app I wrote using the fyne terminal library - it probably does what you need.
https://github.com/andydotxyz/sshterm/blob/57557c8e6ab083370f00acd21d228b0bbd692518/main.go#L170