Skip to content

Commit c00f3c7

Browse files
authored
Merge pull request #360 from devlights/devlights/os-exec-stdinpipe-stdoutpipe-354
Add example of (*Cmd).StdinPipe/StdoutPipe/StderrPipe
2 parents 065c41c + 87cbeeb commit c00f3c7

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

internal/examples/basic/cmdexec/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
|oneshotwithstderr.go|cmdexec\_oneshot\_with\_stderr|コマンドを一発実行して結果を取得するサンプルです。(標準エラー出力も含む)|
99
|stdinouterr.go|cmdexec\_stdinouterr|標準入力・標準出力・標準エラー出力を指定してコマンドを実行するサンプルです|
1010
|withcontext.go|cmdexec\_withcontext|コマンドを context.Context 付きで実行するサンプルです|
11+
|pipe.go|cmdexec\_pipe|(*Cmd).StdinPipe,StdoutPipe,StderrPipeのサンプルです|

internal/examples/basic/cmdexec/examples.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ func (r *register) Regist(m mappings.ExampleMapping) {
1919
m["cmdexec_oneshot_with_stderr"] = OneShotWithStderr
2020
m["cmdexec_stdinouterr"] = Stdinouterr
2121
m["cmdexec_withcontext"] = WithContext
22+
m["cmdexec_pipe"] = Pipe
2223
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package cmdexec
2+
3+
import (
4+
"bufio"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"os/exec"
9+
"runtime"
10+
)
11+
12+
// Pipe は、 (*Cmd).StdinPipe,StdoutPipe,StderrPipeのサンプルです。
13+
//
14+
// REFERENCES:
15+
// - https://golang.org/pkg/os/exec/#example_Cmd_StdinPipe
16+
func Pipe() error {
17+
if runtime.GOOS == "windows" {
18+
return errors.New("this example cannot run on Windows, sorry")
19+
}
20+
21+
const (
22+
Shell = "/bin/bash"
23+
)
24+
25+
var (
26+
cmd *exec.Cmd // コマンド
27+
fd0Pipe io.WriteCloser // 標準入力のパイプ
28+
fd1Pipe io.ReadCloser // 標準出力のパイプ
29+
fd2Pipe io.ReadCloser // 標準エラー出力のパイプ
30+
)
31+
32+
// コマンド構築
33+
cmd = exec.Command(Shell, "-c", "tr a-z A-Z | sort; echo ...done... 1>&2")
34+
35+
//
36+
// パイプを取得
37+
// パイプを扱う場合は、それぞれを非同期で処理する必要がある。
38+
//
39+
fd0Pipe, _ = cmd.StdinPipe()
40+
fd1Pipe, _ = cmd.StdoutPipe()
41+
fd2Pipe, _ = cmd.StderrPipe()
42+
43+
//
44+
// コマンド実行
45+
// StdoutPipe または StderrPipe を利用する場合
46+
// (*Cmd).Run() でコマンドを実行しない。
47+
// (*Cmd).Start() で実行して (*Cmd).Wait() で待つようにする。
48+
//
49+
if err := cmd.Start(); err != nil {
50+
return err
51+
}
52+
53+
// 標準入力のハンドリング
54+
go func() {
55+
//
56+
// 入力が完了したことを示すために明示的に Close する
57+
//
58+
defer fd0Pipe.Close()
59+
60+
io.WriteString(fd0Pipe, "python\n")
61+
io.WriteString(fd0Pipe, "csharp\n")
62+
io.WriteString(fd0Pipe, "golang\n")
63+
io.WriteString(fd0Pipe, "java\n")
64+
}()
65+
66+
// 標準出力のハンドリング
67+
go func() {
68+
//
69+
// 標準出力のパイプは (*Cmd).Wait() の呼び出しにて Close されるので
70+
// 通常呼ぶ必要はない。
71+
//
72+
scanner := bufio.NewScanner(fd1Pipe)
73+
for scanner.Scan() {
74+
fmt.Println(scanner.Text())
75+
}
76+
}()
77+
78+
// 標準エラー出力のハンドリング
79+
go func() {
80+
//
81+
// 標準エラー出力のパイプは (*Cmd).Wait() の呼び出しにて Close されるので
82+
// 通常呼ぶ必要はない。
83+
//
84+
b, _ := io.ReadAll(fd2Pipe)
85+
fmt.Println(string(b))
86+
}()
87+
88+
// コマンド終了待ち
89+
if err := cmd.Wait(); err != nil {
90+
return err
91+
}
92+
93+
return nil
94+
}

0 commit comments

Comments
 (0)