Slide 1

Slide 1 text

Goͷos/execύοέʔδʹ͓͚Δ౾஌ࣝ CAEC MeetUp #4 (1/28)

Slide 2

Slide 2 text

2 About Me @KKawabe108 Software Engineer • ઒෦ উ໵ • ࣳӜ޻ۀେֶେֶӃ ిؾిࢠ৘ใ޻ֶઐ߈M1 • όΠτઌ: ͳ͠ • ڵຯ: OS, ෼ࢄγεςϜ, ݴޠॲཧܥ • ͋ͱΫϥ΢υपΓશൠ • ࠷ۙ࡞ͬͨ΋ͷ: ෼ࢄKVS(raft), ΠϯλϓϦλ

Slide 3

Slide 3 text

Goݴޠʹ͍ͭͯ About Go which is programming language 01 03 02 Google͕։ൃͨ͠ίϯύΠϧܕݴޠ(Ken Thompson΍Rob PikeΒ͕ઃܭͨ͠) ੩తͳܕ෇͚Λߦ͏ݴޠͰڊେͳγεςϜͰ΋։ൃతʹ΋, ύϑΥʔϚϯεతʹ΋εέʔϧ͢Δ. GoroutineΛ࢝Ίͱͨܰ͠ྔͳฒྻॲཧػߏΛαϙʔτ͢Δ ϝδϟʔͳΤσΟλͰ͸΄΅ϑΥʔϚολ͕αϙʔτ͞Ε͍ͯΔͷͰଞਓͷίʔυ͕ඇৗʹ ಡΈ΍͍͢ɹ<= ݸਓతʹܹਪ͠ϙΠϯτ

Slide 4

Slide 4 text

ύοέʔδʹ͍ͭͯ About Go which is programming language • ϓϩάϥϜͷ໊લۭؒΛ෼͚ΔͨΊͷ࢓૊Έ • ಛఆͷॲཧΛύοέʔδʹ੾Γ෼͚Δ͜ͱͰӅṭԽΛߦ͏ • େମଞͷݴޠͷϥΠϒϥϦ΍ύοέʔδػߏͱಉ͡ײ֮Ͱ࢖͑Δ

Slide 5

Slide 5 text

os/exec ύοέʔδ About os/exec package GoͰ֎෦ίϚϯυΛ࣮ߦ͢Δࡍʹ࢖͏. ࣮ࡍʹ͸GoͷϥϯλΠϜ͕goroutineΛ ࢖͍, Α͠ͳʹผϓϩηεͷڍಈΛ؅ཧ ͯ͘͠ΕΔ. 1 package main 2 3 import ( 4 "os/exec" 5 ) 6 7 func main() { 8 cmd := exec.Command("ls", "-la") 9 if err := cmd.Run(); err != nil { 10 panic(err) 11 } 12 }

Slide 6

Slide 6 text

͋Δ೔, ༡ΜͰ͍Δͱ One day, I had be coding… 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 8 int main(){ 9 int result = write(0, "hello", 6); 10 if(result == -1){ 11 perror("write"); 12 exit(1); 13 } 14 printf("\nresult = %d", result); 15 return 0; 16 } ඪ४ೖྗʹhelloͱwriteγεςϜίʔϧ Ͱॻ͖ࠐΉ͚ͩͷίʔυ $ gcc sample.c -o sample $ ./sample hello result = 6%

Slide 7

Slide 7 text

os/execܦ༝Ͱ࣮ߦ͠Α͏ͱ͢Δͱ Try execute binary via os/exec. $ go run sample_exec.go 2019/01/21 11:01:30 exit status 1 exit status 1 Why??? 1 package main 2 3 import ( 4 "log" 5 "os/exec" 6 ) 7 8 func main() { 9 cmd := exec.Command("./sample") 10 if err := cmd.Run(); err != nil { 11 log.Fatal(err) 12 } 13 }

Slide 8

Slide 8 text

8 όΠφϦͷ໰୊ ͳͷ͔ ࣮ߦݖݶपΓ ͳͷ͔౳৭ʑௐ΂͚ͨͲ݁ہղܾ͠ͳ͔ͬͨ

Slide 9

Slide 9 text

9 TwitterͰฉ͍ͯΈͨ Help me twitter.

Slide 10

Slide 10 text

10 exec.Cmdߏ଄ମ exchange stdin ͔֬ʹexec.CommandͷฦΓ஋Ͱ͋Δexec.Cmdߏ଄ମ͸ඪ४ೖྗ౳ͷϝϯόΛ࣋ͬͯΔ

Slide 11

Slide 11 text

11 exec.Cmdͷ࣋ͭ, stdinΛૠ͛ସ͑Δ exchange stdin 1 func main() { 2 cmd := exec.Command("./sample") 3 cmd.Stdin = os.Stdin 4 _, err := cmd.Output() 5 if err != nil { 6 log.Fatal(err) 7 } 8 } 1 $ go run sample_exec.go 2 hello 1 package main 2 3 import ( 4 "log" 5 "os/exec" 6 ) 7 8 func main() { 9 cmd := exec.Command("./sample") 10 if err := cmd.Run(); err != nil { 11 log.Fatal(err) 12 } 13 } Outputؔ਺͸Runͯ͠ ඪ४ग़ྗʹॻ͖ࠐ·Εͨ݁Ռ΋औಘ͢Δ

Slide 12

Slide 12 text

12 ্ख͍ͬͨ͘!!! Ͱ΋, ԿͰϓϩηεͷඪ४ೖྗΛม͑Δͱ্ख͘ߦ͘ͷʁ

Slide 13

Slide 13 text

13 exec.CmdपΓͷίʔυΛ௥ͬͯΈΔ investigate exec.Cmd codes.

Slide 14

Slide 14 text

14 Let’s go 1 func (c *Cmd) Output() ([]byte, error) { 2 if c.Stdout != nil { 3 return nil, errors.New("exec: Stdout already set") 4 } 5 var stdout bytes.Buffer 6 c.Stdout = &stdout 7 8 captureErr := c.Stderr == nil 9 if captureErr { 10 c.Stderr = &prefixSuffixSaver{N: 32 << 10} 11 } 12 13 err := c.Run() 14 if err != nil && captureErr { 15 if ee, ok := err.(*ExitError); ok { 16 ee.Stderr = c.Stderr.(*prefixSuffixSaver).Bytes() 17 } 18 } 19 return stdout.Bytes(), err 20 } 1 func (c *Cmd) Run() error { 2 if err := c.Start(); err != nil { 3 return err 4 } 5 return c.Wait() 6 } ݁ہStartΛݺΜͰΔͷͰStartΛಡ΋͏ Cmdߏ଄ମͷඪ४ೖྗॳظԽ෦෼Λ୳͢ StdoutͱStderrʹؔͯ͠͸ॳظԽ͍ͯ͠Δ

Slide 15

Slide 15 text

15 Cmdߏ଄ମͷඪ४ೖྗॳظԽ෦෼Λ୳͢ Let’s go 1 func (c *Cmd) Start() error { 2 3 ... 4 5 type F func(*Cmd) (*os.File, error) 6 for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { 7 fd, err := setupFd(c) 8 if err != nil { 9 c.closeDescriptors(c.closeAfterStart) 10 c.closeDescriptors(c.closeAfterWait) 11 return err 12 } 13 c.childFiles = append(c.childFiles, fd) 14 } 15 c.childFiles = append(c.childFiles, c.ExtraFiles...) 16 17 ... 18 19 } ඪ४ೖྗͷॳظԽͬΆ͍ॲཧΛݟ͚ͭͨ Cmdߏ଄ମʹඥͮ͘stdinͱ͍͏ ؔ਺ϙΠϯλ

Slide 16

Slide 16 text

16 Cmdߏ଄ମͷඪ४ೖྗॳظԽ෦෼Λ୳͢ Let’s go 1 func (c *Cmd) stdin() (f *os.File, err error) { 2 if c.Stdin == nil { 3 f, err = os.Open(os.DevNull) 4 if err != nil { 5 return 6 } 7 c.closeAfterStart = append(c.closeAfterStart, f) 8 return 9 } 10 11 if f, ok := c.Stdin.(*os.File); ok { 12 return f, nil 13 } 14 15 pr, pw, err := os.Pipe() 16 if err != nil { 17 return 18 } /dev/nullΛopenͯ͠ඪ४ೖྗ ʹׂΓ౰͍ͯͯΔʂ ͋ΕʁͰ΋/dev/null͸ writeγεςϜίʔϧͰ΋ ॻ͖ࠐΊΔ͸ͣ ౾஌ࣝ: go͸ฦΓ஋ʹ໊લΛ͚ͭΔ ͜ͱ͕Ͱ͖, return͢ΔͱσϑΥϧ τͰͦͷ໊લͷม਺Λฦ͢

Slide 17

Slide 17 text

17 1 2 func main() { 3 devNull, _ := os.Open("/dev/null") 4 b, err := syscall.Write(int(devNull.Fd()), []byte("hello")) 5 if err != nil { 6 log.Fatal(err) 7 } 8 fmt.Println(b) 9 } ࣅͨΑ͏ͳίʔυͰ࣮ݧͯ͠ΈΔ experiment 1 go run sample_devnull.go 2 2019/01/21 13:56:03 bad file descriptor 3 exit status 1

Slide 18

Slide 18 text

18 Error: Bad file descriptor experiment ϑΝΠϧσΟεΫϦϓλʹ ॻ͖ࠐΈݖݶ͕෇༩͞Εͯͳ͍

Slide 19

Slide 19 text

19 os.OpenͷgodocΛಡΜͰΈΔͱɾɾɾ read GoDoc Read OnlyͰ։͍ͯΔ͔Βॻ͖ࠐΊͳ͔ͬͨʂʂʂ

Slide 20

Slide 20 text

20 ·ͱΊ conclusion • Goͷos.execύοέʔδ͸֎෦ίϚϯυΛ࣮ߦ͢Δࡍ, σϑΥϧτͰඪ४ೖྗΛ/dev/nullʹઃఆ͢Δ • ͜ͷ࣌, Read OnlyͳͷͰॻ͖ࠐΈ͸Ͱ͖ͳ͍ • ॻ͖ࠐΈ͍ͨ࣌͸cmd.Stdinʹॻ͖ࠐΈݖݶΛ෇༩ͨ͠σΟεΫϦϓλΛઃఆ͠Α͏

Slide 21

Slide 21 text

Thank you for listening! Let’s fun programming with go!