Метод exec.Cmd.StdinPipe
Метод StdinPipe структуры exec.Cmd создает
канал (pipe), который подключается к стандартному вводу
запускаемого процесса. Он возвращает интерфейс
io.WriteCloser, через который можно записывать
данные в стандартный ввод процесса. Этот метод полезен,
когда необходимо передать данные команде интерактивно
или по частям, а не через аргументы командной строки.
Важно закрыть канал после записи, чтобы процесс
получил сигнал о завершении ввода.
Синтаксис
cmd.StdinPipe()
Метод не принимает параметров и возвращает два значения:
канал для записи с типом io.WriteCloser и ошибку
типа error.
Простой пример использования
Давайте запустим команду grep и передадим ей
текст через стандартный ввод для поиска подстроки:
package main
import (
"fmt"
"io"
"os/exec"
)
func main() {
cmd := exec.Command("grep", "Go")
stdin, err := cmd.StdinPipe()
if err != nil {
fmt.Println("Error creating stdin pipe:", err)
return
}
go func() {
defer stdin.Close()
io.WriteString(stdin, "Hello Go\n")
io.WriteString(stdin, "Hello World\n")
}()
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Println("Error running command:", err)
return
}
fmt.Println(string(out))
}
Результат выполнения кода:
"Hello Go\n"
В этом примере мы создаем команду grep Go,
открываем канал для записи в стандартный ввод,
записываем две строки в горутине, а затем читаем
вывод команды через CombinedOutput.
Передача данных из файла
Давайте прочитаем данные из файла и передадим их
в стандартный ввод команды, используя метод
StdinPipe:
package main
import (
"fmt"
"io"
"os"
"os/exec"
)
func main() {
file, err := os.Open("input.txt")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
cmd := exec.Command("wc", "-l")
stdin, err := cmd.StdinPipe()
if err != nil {
fmt.Println("Error creating stdin pipe:", err)
return
}
go func() {
defer stdin.Close()
io.Copy(stdin, file)
}()
out, err := cmd.Output()
if err != nil {
fmt.Println("Error running command:", err)
return
}
fmt.Println(string(out))
}
Результат выполнения кода (предполагается, что файл
input.txt содержит 5 строк):
" 5\n"
Здесь мы открываем файл и передаем его содержимое
в стандартный ввод команды wc -l, которая
подсчитывает количество строк.
Интерактивное взаимодействие с процессом
Давайте создадим простую программу, которая читает ввод от пользователя и передает его процессу через стандартный ввод, а затем читает ответ процесса:
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("cat")
stdin, err := cmd.StdinPipe()
if err != nil {
fmt.Println("Error creating stdin pipe:", err)
return
}
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("Error creating stdout pipe:", err)
return
}
if err := cmd.Start(); err != nil {
fmt.Println("Error starting command:", err)
return
}
go func() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
if line == "exit" {
break
}
stdin.Write([]byte(line + "\n"))
}
stdin.Close()
}()
output := make([]byte, 1024)
n, err := stdout.Read(output)
if err == nil {
fmt.Println(string(output[:n]))
}
cmd.Wait()
}
При выполнении этого кода пользователь может вводить
строки, которые будут переданы команде cat,
и получать их обратно. Для выхода из программы
нужно ввести слово exit.
Смотрите также
-
метод
exec.Cmd.StdoutPipe,
который возвращает канал для чтения стандартного вывода процесса -
метод
exec.Cmd.StderrPipe,
который возвращает канал для чтения стандартного вывода ошибок процесса -
метод
exec.Cmd.Output,
который запускает команду и возвращает ее стандартный вывод -
метод
exec.Cmd.CombinedOutput,
который запускает команду и возвращает объединенный вывод