go调用shell命令两种方式实现(有无返回值)

简介: go调用shell命令两种方式实现(有无返回值)

阻塞方式(需要执行结果)

适用于执行普通非阻塞shell命令,且需要shell标准输出的

非阻塞方式(不需要执行结果)

阻塞方式(需要执行结果)
主要用于执行shell命令,并且返回shell的标准输出

适用于执行普通非阻塞shell命令,且需要shell标准输出的

//阻塞式的执行外部shell命令的函数,等待执行完毕并返回标准输出
func exec_shell(s string) (string, error){

//函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
cmd := exec.Command("/bin/bash", "-c", s)
//读取io.Writer类型的cmd.Stdout,再通过bytes.Buffer(缓冲byte类型的缓冲器)将byte类型转化为string类型(out.String():这是bytes类型提供的接口)
var out bytes.Buffer
cmd.Stdout = &out
//Run执行c包含的命令,并阻塞直到完成。  这里stdout被取出,cmd.Wait()无法正确获取stdin,stdout,stderr,则阻塞在那了
err := cmd.Run()
checkErr(err)
return out.String(), err

}
需要对shell标准输出的逐行实时进行处理的

func execCommand(commandName string, params []string) bool {

//函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
cmd := exec.Command(commandName, params...)
//显示运行的命令
fmt.Println(cmd.Args)
//StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。
stdout, err := cmd.StdoutPipe()
if err != nil {
    fmt.Println(err)
    return false
}
cmd.Start()
//创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
reader := bufio.NewReader(stdout)
//实时循环读取输出流中的一行内容
for {
    line, err2 := reader.ReadString('\n')
    if err2 != nil || io.EOF == err2 {
        break
    }
    fmt.Println(line)
}
//阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的
cmd.Wait()
return true

}
非阻塞方式(不需要执行结果)
通过shell调用自己的程序,并且程序是死循环,此时无法获取返回结果(否则程序会一直阻塞直至调用的 程序结束)

适用于调用自己写的程序(服务器死循环,且不需要返回结果的)

//不需要执行命令的结果与成功与否,执行命令马上就返回
func exec_shell_no_result(command string) {

//处理启动参数,通过空格分离 如:setsid /home/luojing/gotest/src/test_main/iwatch/test/while_little &
command_name_and_args := strings.FieldsFunc(command, splite_command)
//开始执行c包含的命令,但并不会等待该命令完成即返回
cmd.Start()
    if err != nil {
    fmt.Printf("%v: exec command:%v error:%v\n", get_time(), command, err)
}
fmt.Printf("Waiting for command:%v to finish...\n", command)
//阻塞等待fork出的子进程执行的结果,和cmd.Start()配合使用[不等待回收资源,会导致fork出执行shell命令的子进程变为僵尸进程]
err = cmd.Wait()
if err != nil {
    fmt.Printf("%v: Command finished with error: %v\n", get_time(), err)
}
return

}

/错误处理函数
func checkErr(err error) {

if err != nil {
    fmt.Println(err)
    panic(err)  
}

}
官网的标准中文库
引用部分文档

func (*Cmd) Run
func (c *Cmd) Run() error
Run执行c包含的命令,并阻塞直到完成。
如果命令成功执行,stdin、stdout、stderr的转交没有问题,并且返回状态码为0,方法的返回值为nil;如果命令没有执行或者执行失败,会返回*ExitError类型的错误;否则返回的error可能是表示I/O问题。

func (*Cmd) Start
func (c *Cmd) Start() error
Start开始执行c包含的命令,但并不会等待该命令完成即返回。Wait方法会返回命令的返回状态码并在命令返回后释放相关的资源。

func (*Cmd) Wait
func (c *Cmd) Wait() error
Wait会阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的。

如果命令成功执行,stdin、stdout、stderr的转交没有问题,并且返回状态码为0,方法的返回值为nil;如果命令没有执行或者执行失败,会返回*ExitError类型的错误;否则返回的error可能是表示I/O问题。Wait方法会在命令返回后释放相关的资源。

func (*Cmd) Output
func (c *Cmd) Output() ([]byte, error)
执行命令并返回标准输出的切片。

func (*Cmd) StderrPipe
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
StderrPipe方法返回一个在命令Start后与命令标准错误输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。但是在从管道读取完全部数据之前调用Wait是错误的;同样使用StderrPipe方法时调用Run函数也是错误的。
原文

目录
相关文章
|
4天前
|
Java Shell Windows
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
java Runtime.exec()执行shell/cmd命令:常见的几种陷阱与一种完善实现
14 1
|
1月前
|
Web App开发 网络协议 Linux
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
这篇文章是关于Linux命令的总结,涵盖了从基础操作到网络配置等多个方面的命令及其使用方法。
62 1
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
|
1月前
|
Shell 知识图谱
Shell printf 命令
10月更文挑战第3天
18 1
|
1月前
|
Unix Shell Linux
常见的shell命令
shell常用命令
39 11
|
1月前
|
Shell PHP
Shell echo命令
10月更文挑战第3天
20 0
|
1月前
|
JSON Java Shell
Dockerfile中RUN、CMD、ENTRYPOINT、SHELL命令的区别
理解这些指令的差异和应用场景,有助于构建高效、灵活且易于管理的Docker镜像。在实际应用中,根据需要选择合适的指令,可以有效地控制镜像构建和容器运行的行为。
144 0
|
1月前
|
SQL Shell 数据库
在TDengine容器中创建初始化数据库的Shell命令实例
以上就是在Docker容器环境中部署并初始化TDengine数据库的全过程,希望对你有所帮助。
63 0
|
1月前
|
Shell
一个用于添加/删除定时任务的shell脚本
一个用于添加/删除定时任务的shell脚本
75 1
|
17天前
|
Shell Linux 测试技术
6种方法打造出色的Shell脚本
6种方法打造出色的Shell脚本
42 2
6种方法打造出色的Shell脚本
|
4天前
|
XML JSON 监控
Shell脚本要点和难点以及具体应用和优缺点介绍
Shell脚本在系统管理和自动化任务中扮演着重要角色。尽管存在调试困难、可读性差等问题,但其简洁高效、易于学习和强大的功能使其在许多场景中不可或缺。通过掌握Shell脚本的基本语法、常用命令和函数,并了解其优缺点,开发者可以编写出高效的脚本来完成各种任务,提高工作效率。希望本文能为您在Shell脚本编写和应用中提供有价值的参考和指导。
14 1