| 155 | } |
| 156 | |
| 157 | func (c *SSHClient) RunWithStreamOutput(command string, outputCallback func(string)) error { |
| 158 | session, err := c.Client.NewSession() |
| 159 | if err != nil { |
| 160 | return fmt.Errorf("failed to create SSH session: %w", err) |
| 161 | } |
| 162 | defer session.Close() |
| 163 | |
| 164 | stdout, err := session.StdoutPipe() |
| 165 | if err != nil { |
| 166 | return fmt.Errorf("failed to set up stdout pipe: %w", err) |
| 167 | } |
| 168 | |
| 169 | stderr, err := session.StderrPipe() |
| 170 | if err != nil { |
| 171 | return fmt.Errorf("failed to set up stderr pipe: %w", err) |
| 172 | } |
| 173 | |
| 174 | if err := session.Start(command); err != nil { |
| 175 | return fmt.Errorf("failed to start command: %w", err) |
| 176 | } |
| 177 | |
| 178 | stdoutCh := make(chan string, 100) |
| 179 | stderrCh := make(chan string, 100) |
| 180 | doneCh := make(chan struct{}) |
| 181 | |
| 182 | go func() { |
| 183 | buffer := make([]byte, 1024) |
| 184 | for { |
| 185 | n, err := stdout.Read(buffer) |
| 186 | if err != nil { |
| 187 | close(stdoutCh) |
| 188 | return |
| 189 | } |
| 190 | if n > 0 { |
| 191 | stdoutCh <- string(buffer[:n]) |
| 192 | } |
| 193 | } |
| 194 | }() |
| 195 | |
| 196 | go func() { |
| 197 | buffer := make([]byte, 1024) |
| 198 | for { |
| 199 | n, err := stderr.Read(buffer) |
| 200 | if err != nil { |
| 201 | close(stderrCh) |
| 202 | return |
| 203 | } |
| 204 | if n > 0 { |
| 205 | stderrCh <- string(buffer[:n]) |
| 206 | } |
| 207 | } |
| 208 | }() |
| 209 | |
| 210 | go func() { |
| 211 | for { |
| 212 | select { |
| 213 | case stdoutOutput, ok := <-stdoutCh: |
| 214 | if !ok { |