Метод exec.Cmd.StderrPipe
Метод exec.Cmd.StderrPipe создает канал (pipe),
который подключается к стандартному потоку ошибок
(STDERR) команды. Он возвращает io.ReadCloser,
из которого можно читать вывод ошибок команды.
Этот метод полезен, когда нужно отдельно обрабатывать
ошибочный вывод команды, не смешивая его с обычным
выводом (STDOUT).
Важно: канал должен быть прочитан полностью до вызова
exec.Cmd.Run или exec.Cmd.Wait,
иначе команда может заблокироваться при записи в STDERR.
Обычно чтение из канала выполняют в отдельной горутине
или читают весь вывод через io.ReadAll.
Синтаксис
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
Пример
Давайте выполним команду, которая всегда завершается с ошибкой, и прочитаем её STDERR:
package main
import (
"bytes"
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("ls", "--invalid-flag")
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("Error creating pipe:", err)
return
}
err = cmd.Start()
if err != nil {
fmt.Println("Error starting command:", err)
return
}
var errBuf bytes.Buffer
_, err = errBuf.ReadFrom(stderr)
if err != nil {
fmt.Println("Error reading stderr:", err)
return
}
err = cmd.Wait()
if err != nil {
fmt.Println("Command finished with error:", err)
}
fmt.Println("STDERR output:", errBuf.String())
}
Результат выполнения кода:
"Command finished with error: exit status 2"
"STDERR output: ls: unrecognized option '--invalid-flag'"
Пример
Теперь рассмотрим пример, где мы читаем STDERR и STDOUT одновременно из одной команды:
package main
import (
"bufio"
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("sh", "-c", "echo 'stdout text' && echo 'stderr text' >&2")
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("Error creating stdout pipe:", err)
return
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("Error creating stderr pipe:", err)
return
}
err = cmd.Start()
if err != nil {
fmt.Println("Error starting command:", err)
return
}
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
fmt.Println("STDOUT:", scanner.Text())
}
}()
scanner := bufio.NewScanner(stderr)
for scanner.Scan() {
fmt.Println("STDERR:", scanner.Text())
}
err = cmd.Wait()
if err != nil {
fmt.Println("Command finished with error:", err)
}
}
Результат выполнения кода:
"STDERR: stderr text"
"STDOUT: stdout text"
Пример
Если нужно прочитать STDERR как строку, можно использовать
функцию io.ReadAll:
package main
import (
"fmt"
"io"
"os/exec"
)
func main() {
cmd := exec.Command("go", "mod", "tidy")
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("Error creating pipe:", err)
return
}
err = cmd.Start()
if err != nil {
fmt.Println("Error starting command:", err)
return
}
errData, err := io.ReadAll(stderr)
if err != nil {
fmt.Println("Error reading stderr:", err)
return
}
err = cmd.Wait()
if err != nil {
fmt.Println("Command finished with error:", err)
}
if len(errData) > 0 {
fmt.Println("STDERR:", string(errData))
} else {
fmt.Println("No stderr output")
}
}
Результат выполнения кода:
"No stderr output"
Смотрите также
-
метод
exec.Cmd.StdinPipe,
который создает канал для записи в STDIN команды -
метод
exec.Cmd.StdoutPipe,
который создает канал для чтения STDOUT команды -
метод
exec.Cmd.Output,
который возвращает STDOUT команды как байтовый срез -
метод
exec.Cmd.CombinedOutput,
который возвращает объединенный вывод STDOUT и STDERR