Synchronize SSH exec stdin with command start

This commit is contained in:
Fedor Korotkov 2026-05-01 14:00:09 -04:00
parent 3acdc77f40
commit 76c10f80e5
1 changed files with 23 additions and 13 deletions

View File

@ -19,6 +19,7 @@ type Exec struct {
stdout io.Reader stdout io.Reader
stderr io.Reader stderr io.Reader
stdin io.WriteCloser stdin io.WriteCloser
stdinReader *io.PipeReader
} }
func New(netConn net.Conn, user string, password string, stdin bool) (*Exec, error) { func New(netConn net.Conn, user string, password string, stdin bool) (*Exec, error) {
@ -52,14 +53,10 @@ func New(netConn net.Conn, user string, password string, stdin bool) (*Exec, err
} }
if stdin { if stdin {
exec.stdin, err = sshSession.StdinPipe() stdinReader, stdinWriter := io.Pipe()
if err != nil { sshSession.Stdin = stdinReader
_ = sshSession.Close() exec.stdinReader = stdinReader
_ = sshClient.Close() exec.stdin = stdinWriter
return nil, fmt.Errorf("failed to create standard input pipe "+
"for the SSH session: %w", err)
}
} }
exec.stdout, err = sshSession.StdoutPipe() exec.stdout, err = sshSession.StdoutPipe()
@ -92,6 +89,12 @@ func (exec *Exec) Run(
command string, command string,
outgoingFrames chan<- *execstream.Frame, outgoingFrames chan<- *execstream.Frame,
) error { ) error {
if exec.stdinReader != nil {
defer func() {
_ = exec.stdinReader.Close()
}()
}
if err := exec.sshSession.Start(command); err != nil { if err := exec.sshSession.Start(command); err != nil {
return fmt.Errorf("failed to start command %q: %w", command, err) return fmt.Errorf("failed to start command %q: %w", command, err)
} }
@ -188,6 +191,13 @@ func ioStreamReader(
} }
func (exec *Exec) Close() error { func (exec *Exec) Close() error {
if exec.stdin != nil {
_ = exec.stdin.Close()
}
if exec.stdinReader != nil {
_ = exec.stdinReader.Close()
}
if err := exec.sshSession.Close(); err != nil { if err := exec.sshSession.Close(); err != nil {
_ = exec.sshClient.Close() _ = exec.sshClient.Close()