The Go language calls Shell with the implementation of the executable
- 2020-11-20 06:08:38
- OfStack
The os/exec package can be used to invoke external commands, can pipe input and output, and supports blocking and non-blocking execution of commands.
The key type in the os/exec package is Cmd, and all of the methods described below serve this type:
func Command(name string, arg ...string) *Cmd
Method returns 1 *Cmd to execute the program specified by name (with the arg parameter)
func (c *Cmd) Run() error
Executes the command contained in Cmd and blocks until the command execution is complete
func (c *Cmd) Start() error
Execute the command contained in Cmd, and the method returns immediately without waiting for the command to complete execution
func (c *Cmd) Wait() error
This method blocks until the command in Cmd, which must have been started by the Start method, completes
func (c *Cmd) Output() ([]byte, error)
Execute the command contained in Cmd and return the standard output slice
func (c *Cmd) CombinedOutput() ([]byte, error)
Execute the command contained in Cmd and return a slice of standard output merged with standard error
func (c *Cmd) StdinPipe() (io.WriteCloser, error)
Returns a pipe that connects to its standard input after the command in Cmd is started
func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
Returns a pipe that connects to its standard output after the command in Cmd is started
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
Returns a pipe that connects to standard error after the command in Cmd is started
Examples of ordinary calls:
Call the Shell command or executable
Demo creates an empty file in the current directory
package main
import (
"fmt"
"os/exec"
)
func main(){
cmd := exec.Command("touch", "test_file")
err := cmd.Run()
if err != nil {
fmt.Println("Execute Command failed:" + err.Error())
return
}
fmt.Println("Execute Command finished.")
}
1 It is generally not recommended to call the Shell script using this default mode:
cmd := exec.Command("my_shell.sh")
Because of the actual execution result and command line execution #sh ES84en_shell.sh1 in this way, if your Shell script does not meet the specification of sh, the call will fail.
Call the Shell script
Set bash to invoke the specified Shell script, dir_size.sh for the Shell script we tested. After the call is complete, print the standard output of the Shell script to the console.
package main
import (
"fmt"
"os/exec"
)
func main(){
command := `./dir_size.sh .`
cmd := exec.Command("/bin/bash", "-c", command)
output, err := cmd.Output()
if err != nil {
fmt.Printf("Execute Shell:%s failed with error:%s", command, err.Error())
return
}
fmt.Printf("Execute Shell:%s finished with output:\n%s", command, string(output))
}
dir_size.sh sample file contains the following contents to output the size of the current directory:
#!/bin/bash
du -h --max-depth=1 $1
Go program results:
[root@localhost opt]# ll
total 2120
-rwx------. 1 root root 36 Jan 22 16:37 dir_size.sh
-rwx------. 1 root root 2152467 Jan 22 16:39 execCommand
drwxrwxr-x. 11 1000 1000 4096 Jul 12 2017 kibana
drwx------. 2 root root 4096 Jan 16 10:45 sftpuser
drwx------. 3 root root 4096 Jan 22 16:41 upload
[root@localhost opt]# ./execCommand
Execute Shell:./dir_size.sh . finished with output:
4.0K ./sftpuser
181M ./kibana
1.1G ./upload
1.2G .
Use I/O Pipe
Demonstrates the standard input of the grep command using a pipe to filter the string containing test, and the standard output using a pipe to print the run result:
package main
import (
"fmt"
"io/ioutil"
"os/exec"
)
func main(){
cmd := exec.Command("/bin/bash", "-c", "grep test")
stdin, _ := cmd.StdinPipe()
stdout, _ := cmd.StdoutPipe()
if err := cmd.Start(); err != nil{
fmt.Println("Execute failed when Start:" + err.Error())
return
}
stdin.Write([]byte("go text for grep\n"))
stdin.Write([]byte("go test text for grep\n"))
stdin.Close()
out_bytes, _ := ioutil.ReadAll(stdout)
stdout.Close()
if err := cmd.Wait(); err != nil {
fmt.Println("Execute failed when Wait:" + err.Error())
return
}
fmt.Println("Execute finished:" + string(out_bytes))
}
Go program results:
[
[root@localhost ~]# ./execCommand
Execute finished:go test text for grep
Blocking/non-blocking calls
The introduction to the method at the beginning of the article is very clear, and the previous examples are covered, so I will not explain it separately.
Reference document:
GoLang standard library documentation